Commit 89eed1ab authored by Miguel Ojeda's avatar Miguel Ojeda

rust: upgrade to Rust 1.71.1

This is the second upgrade to the Rust toolchain, from 1.68.2 to 1.71.1
(i.e. the latest).

See the upgrade policy [1] and the comments on the first upgrade in
commit 3ed03f4d ("rust: upgrade to Rust 1.68.2").

# Unstable features

No unstable features (that we use) were stabilized.

Therefore, the only unstable feature allowed to be used outside
the `kernel` crate is still `new_uninit`, though other code to be
upstreamed may increase the list.

Please see [2] for details.

# Required changes

For the upgrade, this patch requires the following changes:

  - Removal of the `__rust_*` allocator functions, together with
    the addition of the `__rust_no_alloc_shim_is_unstable` static.
    See [3] for details.

  - Some more compiler builtins added due to `<f{32,64}>::midpoint()`
    that got added in Rust 1.71 [4].

# `alloc` upgrade and reviewing

The vast majority of changes are due to our `alloc` fork being upgraded
at once.

There are two kinds of changes to be aware of: the ones coming from
upstream, which we should follow as closely as possible, and the updates
needed in our added fallible APIs to keep them matching the newer
infallible APIs coming from upstream.

Instead of taking a look at the diff of this patch, an alternative
approach is reviewing a diff of the changes between upstream `alloc` and
the kernel's. This allows to easily inspect the kernel additions only,
especially to check if the fallible methods we already have still match
the infallible ones in the new version coming from upstream.

Another approach is reviewing the changes introduced in the additions in
the kernel fork between the two versions. This is useful to spot
potentially unintended changes to our additions.

To apply these approaches, one may follow steps similar to the following
to generate a pair of patches that show the differences between upstream
Rust and the kernel (for the subset of `alloc` we use) before and after
applying this patch:

    # Get the difference with respect to the old version.
    git -C rust checkout $(linux/scripts/min-tool-version.sh rustc)
    git -C linux ls-tree -r --name-only HEAD -- rust/alloc |
        cut -d/ -f3- |
        grep -Fv README.md |
        xargs -IPATH cp rust/library/alloc/src/PATH linux/rust/alloc/PATH
    git -C linux diff --patch-with-stat --summary -R > old.patch
    git -C linux restore rust/alloc

    # Apply this patch.
    git -C linux am rust-upgrade.patch

    # Get the difference with respect to the new version.
    git -C rust checkout $(linux/scripts/min-tool-version.sh rustc)
    git -C linux ls-tree -r --name-only HEAD -- rust/alloc |
        cut -d/ -f3- |
        grep -Fv README.md |
        xargs -IPATH cp rust/library/alloc/src/PATH linux/rust/alloc/PATH
    git -C linux diff --patch-with-stat --summary -R > new.patch
    git -C linux restore rust/alloc

Now one may check the `new.patch` to take a look at the additions (first
approach) or at the difference between those two patches (second
approach). For the latter, a side-by-side tool is recommended.

Link: https://rust-for-linux.com/rust-version-policy [1]
Link: https://github.com/Rust-for-Linux/linux/issues/2 [2]
Link: https://github.com/rust-lang/rust/pull/86844 [3]
Link: https://github.com/rust-lang/rust/pull/92048 [4]
Closes: https://github.com/Rust-for-Linux/linux/issues/68Reviewed-by: default avatarMartin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: default avatarTrevor Gross <tmgross@umich.edu>
Link: https://lore.kernel.org/r/20230729220317.416771-1-ojeda@kernel.orgSigned-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
parent 41bdc6de
...@@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils. ...@@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils.
====================== =============== ======================================== ====================== =============== ========================================
GNU C 5.1 gcc --version GNU C 5.1 gcc --version
Clang/LLVM (optional) 11.0.0 clang --version Clang/LLVM (optional) 11.0.0 clang --version
Rust (optional) 1.68.2 rustc --version Rust (optional) 1.71.1 rustc --version
bindgen (optional) 0.56.0 bindgen --version bindgen (optional) 0.56.0 bindgen --version
GNU make 3.82 make --version GNU make 3.82 make --version
bash 4.2 bash --version bash 4.2 bash --version
......
...@@ -379,8 +379,8 @@ rust-analyzer: ...@@ -379,8 +379,8 @@ rust-analyzer:
$(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
redirect-intrinsics = \ redirect-intrinsics = \
__eqsf2 __gesf2 __lesf2 __nesf2 __unordsf2 \ __addsf3 __eqsf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __unordsf2 \
__unorddf2 \ __adddf3 __ledf2 __ltdf2 __muldf3 __unorddf2 \
__muloti4 __multi3 \ __muloti4 __multi3 \
__udivmodti4 __udivti3 __umodti3 __udivmodti4 __udivti3 __umodti3
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#[doc(inline)] #[doc(inline)]
pub use core::alloc::*; pub use core::alloc::*;
use core::marker::Destruct;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
...@@ -41,6 +39,9 @@ ...@@ -41,6 +39,9 @@
#[rustc_allocator_zeroed] #[rustc_allocator_zeroed]
#[rustc_nounwind] #[rustc_nounwind]
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
#[cfg(not(bootstrap))]
static __rust_no_alloc_shim_is_unstable: u8;
} }
/// The global memory allocator. /// The global memory allocator.
...@@ -94,7 +95,14 @@ ...@@ -94,7 +95,14 @@
#[must_use = "losing the pointer will leak memory"] #[must_use = "losing the pointer will leak memory"]
#[inline] #[inline]
pub unsafe fn alloc(layout: Layout) -> *mut u8 { pub unsafe fn alloc(layout: Layout) -> *mut u8 {
unsafe { __rust_alloc(layout.size(), layout.align()) } unsafe {
// Make sure we don't accidentally allow omitting the allocator shim in
// stable code until it is actually stabilized.
#[cfg(not(bootstrap))]
core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable);
__rust_alloc(layout.size(), layout.align())
}
} }
/// Deallocate memory with the global allocator. /// Deallocate memory with the global allocator.
...@@ -333,16 +341,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { ...@@ -333,16 +341,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
#[cfg_attr(not(test), lang = "box_free")] #[cfg_attr(not(test), lang = "box_free")]
#[inline] #[inline]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
// This signature has to be the same as `Box`, otherwise an ICE will happen. // This signature has to be the same as `Box`, otherwise an ICE will happen.
// When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as
// well. // well.
// For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`, // For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`,
// this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well. // this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well.
pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Destruct>( pub(crate) unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) {
ptr: Unique<T>,
alloc: A,
) {
unsafe { unsafe {
let size = size_of_val(ptr.as_ref()); let size = size_of_val(ptr.as_ref());
let align = min_align_of_val(ptr.as_ref()); let align = min_align_of_val(ptr.as_ref());
......
This diff is collapsed.
...@@ -89,35 +89,37 @@ ...@@ -89,35 +89,37 @@
#![warn(missing_debug_implementations)] #![warn(missing_debug_implementations)]
#![warn(missing_docs)] #![warn(missing_docs)]
#![allow(explicit_outlives_requirements)] #![allow(explicit_outlives_requirements)]
#![warn(multiple_supertrait_upcastable)]
// //
// Library features: // Library features:
// tidy-alphabetical-start
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
#![cfg_attr(test, feature(is_sorted))]
#![cfg_attr(test, feature(new_uninit))]
#![feature(alloc_layout_extra)] #![feature(alloc_layout_extra)]
#![feature(allocator_api)] #![feature(allocator_api)]
#![feature(array_chunks)] #![feature(array_chunks)]
#![feature(array_into_iter_constructors)] #![feature(array_into_iter_constructors)]
#![feature(array_methods)] #![feature(array_methods)]
#![feature(array_windows)] #![feature(array_windows)]
#![feature(ascii_char)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(async_iterator)] #![feature(async_iterator)]
#![feature(coerce_unsized)] #![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![feature(const_align_of_val)]
#![feature(const_box)] #![feature(const_box)]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
#![cfg_attr(not(no_borrow), feature(const_cow_is_borrowed))] #![cfg_attr(not(no_borrow), feature(const_cow_is_borrowed))]
#![feature(const_convert)] #![feature(const_eval_select)]
#![feature(const_size_of_val)]
#![feature(const_align_of_val)]
#![feature(const_ptr_read)]
#![feature(const_maybe_uninit_zeroed)]
#![feature(const_maybe_uninit_write)]
#![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_maybe_uninit_write)]
#![feature(const_maybe_uninit_zeroed)]
#![feature(const_pin)]
#![feature(const_refs_to_cell)] #![feature(const_refs_to_cell)]
#![feature(const_size_of_val)]
#![feature(const_waker)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(core_panic)] #![feature(core_panic)]
#![feature(const_eval_select)]
#![feature(const_pin)]
#![feature(const_waker)]
#![feature(cstr_from_bytes_until_nul)]
#![feature(dispatch_from_dyn)] #![feature(dispatch_from_dyn)]
#![feature(error_generic_member_access)] #![feature(error_generic_member_access)]
#![feature(error_in_core)] #![feature(error_in_core)]
...@@ -128,7 +130,6 @@ ...@@ -128,7 +130,6 @@
#![feature(hasher_prefixfree_extras)] #![feature(hasher_prefixfree_extras)]
#![feature(inline_const)] #![feature(inline_const)]
#![feature(inplace_iteration)] #![feature(inplace_iteration)]
#![cfg_attr(test, feature(is_sorted))]
#![feature(iter_advance_by)] #![feature(iter_advance_by)]
#![feature(iter_next_chunk)] #![feature(iter_next_chunk)]
#![feature(iter_repeat_n)] #![feature(iter_repeat_n)]
...@@ -136,8 +137,6 @@ ...@@ -136,8 +137,6 @@
#![feature(maybe_uninit_slice)] #![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array)]
#![feature(maybe_uninit_uninit_array_transpose)] #![feature(maybe_uninit_uninit_array_transpose)]
#![cfg_attr(test, feature(new_uninit))]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(pattern)] #![feature(pattern)]
#![feature(pointer_byte_offsets)] #![feature(pointer_byte_offsets)]
#![feature(provide_any)] #![feature(provide_any)]
...@@ -153,6 +152,7 @@ ...@@ -153,6 +152,7 @@
#![feature(slice_ptr_get)] #![feature(slice_ptr_get)]
#![feature(slice_ptr_len)] #![feature(slice_ptr_len)]
#![feature(slice_range)] #![feature(slice_range)]
#![feature(std_internals)]
#![feature(str_internals)] #![feature(str_internals)]
#![feature(strict_provenance)] #![feature(strict_provenance)]
#![feature(trusted_len)] #![feature(trusted_len)]
...@@ -163,40 +163,42 @@ ...@@ -163,40 +163,42 @@
#![feature(unicode_internals)] #![feature(unicode_internals)]
#![feature(unsize)] #![feature(unsize)]
#![feature(utf8_chunks)] #![feature(utf8_chunks)]
#![feature(std_internals)] // tidy-alphabetical-end
// //
// Language features: // Language features:
// tidy-alphabetical-start
#![cfg_attr(not(test), feature(generator_trait))]
#![cfg_attr(test, feature(panic_update_hook))]
#![cfg_attr(test, feature(test))]
#![feature(allocator_internals)] #![feature(allocator_internals)]
#![feature(allow_internal_unstable)] #![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
#![feature(c_unwind)]
#![feature(cfg_sanitize)] #![feature(cfg_sanitize)]
#![feature(const_deref)]
#![feature(const_mut_refs)] #![feature(const_mut_refs)]
#![feature(const_ptr_write)]
#![feature(const_precise_live_drops)] #![feature(const_precise_live_drops)]
#![feature(const_ptr_write)]
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#![feature(const_try)] #![feature(const_try)]
#![feature(dropck_eyepatch)] #![feature(dropck_eyepatch)]
#![feature(exclusive_range_pattern)] #![feature(exclusive_range_pattern)]
#![feature(fundamental)] #![feature(fundamental)]
#![cfg_attr(not(test), feature(generator_trait))]
#![feature(hashmap_internals)] #![feature(hashmap_internals)]
#![feature(lang_items)] #![feature(lang_items)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(multiple_supertrait_upcastable)]
#![feature(negative_impls)] #![feature(negative_impls)]
#![feature(never_type)] #![feature(never_type)]
#![feature(pointer_is_aligned)]
#![feature(rustc_allow_const_fn_unstable)] #![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![feature(pointer_is_aligned)]
#![feature(slice_internals)] #![feature(slice_internals)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
#![cfg_attr(test, feature(test))]
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(unsized_fn_params)] #![feature(unsized_fn_params)]
#![feature(c_unwind)]
#![feature(with_negative_coherence)] #![feature(with_negative_coherence)]
#![cfg_attr(test, feature(panic_update_hook))] // tidy-alphabetical-end
// //
// Rustdoc features: // Rustdoc features:
#![feature(doc_cfg)] #![feature(doc_cfg)]
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
use core::cmp; use core::cmp;
use core::intrinsics; use core::intrinsics;
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ops::Drop;
use core::ptr::{self, NonNull, Unique}; use core::ptr::{self, NonNull, Unique};
use core::slice; use core::slice;
...@@ -274,10 +273,15 @@ fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> { ...@@ -274,10 +273,15 @@ fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
if T::IS_ZST || self.cap == 0 { if T::IS_ZST || self.cap == 0 {
None None
} else { } else {
// We have an allocated chunk of memory, so we can bypass runtime // We could use Layout::array here which ensures the absence of isize and usize overflows
// checks to get our current layout. // 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.
let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
unsafe { unsafe {
let layout = Layout::array::<T>(self.cap).unwrap_unchecked(); let align = mem::align_of::<T>();
let size = mem::size_of::<T>().unchecked_mul(self.cap);
let layout = Layout::from_size_align_unchecked(size, align);
Some((self.ptr.cast().into(), layout)) Some((self.ptr.cast().into(), layout))
} }
} }
...@@ -465,11 +469,13 @@ fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> { ...@@ -465,11 +469,13 @@ fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity"); assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
// See current_memory() why this assert is here
let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
let ptr = unsafe { let ptr = unsafe {
// `Layout::array` cannot overflow here because it would have // `Layout::array` cannot overflow here because it would have
// overflowed earlier when capacity was larger. // overflowed earlier when capacity was larger.
let new_layout = Layout::array::<T>(cap).unwrap_unchecked(); let new_size = mem::size_of::<T>().unchecked_mul(cap);
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
self.alloc self.alloc
.shrink(ptr, layout, new_layout) .shrink(ptr, layout, new_layout)
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
......
...@@ -784,6 +784,38 @@ fn borrow_mut(&mut self) -> &mut [T] { ...@@ -784,6 +784,38 @@ fn borrow_mut(&mut self) -> &mut [T] {
} }
} }
// 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<T, A: Allocator> {
fn clone_into(&self, target: &mut Vec<T, A>);
}
#[cfg(not(no_global_oom_handling))]
impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
default fn clone_into(&self, target: &mut Vec<T, A>) {
// 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<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
fn clone_into(&self, target: &mut Vec<T, A>) {
target.clear();
target.extend_from_slice(self);
}
}
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> ToOwned for [T] { impl<T: Clone> ToOwned for [T] {
...@@ -799,16 +831,7 @@ fn to_owned(&self) -> Vec<T> { ...@@ -799,16 +831,7 @@ fn to_owned(&self) -> Vec<T> {
} }
fn clone_into(&self, target: &mut Vec<T>) { fn clone_into(&self, target: &mut Vec<T>) {
// drop anything in target that will not be overwritten SpecCloneIntoVec::clone_into(self, target);
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);
} }
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
/// ///
/// ``` /// ```
/// let mut v = vec![0, 1, 2]; /// let mut v = vec![0, 1, 2];
/// let iter: std::vec::Drain<_> = v.drain(..); /// let iter: std::vec::Drain<'_, _> = v.drain(..);
/// ``` /// ```
#[stable(feature = "drain", since = "1.6.0")] #[stable(feature = "drain", since = "1.6.0")]
pub struct Drain< pub struct Drain<
...@@ -114,9 +114,7 @@ pub fn keep_rest(self) { ...@@ -114,9 +114,7 @@ pub fn keep_rest(self) {
let unyielded_ptr = this.iter.as_slice().as_ptr(); let unyielded_ptr = this.iter.as_slice().as_ptr();
// ZSTs have no identity, so we don't need to move them around. // ZSTs have no identity, so we don't need to move them around.
let needs_move = mem::size_of::<T>() != 0; if !T::IS_ZST {
if needs_move {
let start_ptr = source_vec.as_mut_ptr().add(start); let start_ptr = source_vec.as_mut_ptr().add(start);
// memmove back unyielded elements // memmove back unyielded elements
...@@ -199,7 +197,7 @@ fn drop(&mut self) { ...@@ -199,7 +197,7 @@ fn drop(&mut self) {
} }
} }
let iter = mem::replace(&mut self.iter, (&mut []).iter()); let iter = mem::take(&mut self.iter);
let drop_len = iter.len(); let drop_len = iter.len();
let mut vec = self.vec; let mut vec = self.vec;
......
// SPDX-License-Identifier: Apache-2.0 OR MIT // SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::alloc::{Allocator, Global}; use crate::alloc::{Allocator, Global};
use core::mem::{self, ManuallyDrop}; use core::mem::{ManuallyDrop, SizedTypeProperties};
use core::ptr; use core::ptr;
use core::slice; use core::slice;
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
/// #![feature(drain_filter)] /// #![feature(drain_filter)]
/// ///
/// let mut v = vec![0, 1, 2]; /// let mut v = vec![0, 1, 2];
/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); /// let iter: std::vec::DrainFilter<'_, _, _> = v.drain_filter(|x| *x % 2 == 0);
/// ``` /// ```
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
#[derive(Debug)] #[derive(Debug)]
...@@ -98,9 +98,7 @@ pub fn keep_rest(self) { ...@@ -98,9 +98,7 @@ pub fn keep_rest(self) {
unsafe { unsafe {
// ZSTs have no identity, so we don't need to move them around. // ZSTs have no identity, so we don't need to move them around.
let needs_move = mem::size_of::<T>() != 0; if !T::IS_ZST && this.idx < this.old_len && this.del > 0 {
if needs_move && this.idx < this.old_len && this.del > 0 {
let ptr = this.vec.as_mut_ptr(); let ptr = this.vec.as_mut_ptr();
let src = ptr.add(this.idx); let src = ptr.add(this.idx);
let dst = src.sub(this.del); let dst = src.sub(this.del);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
}; };
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::num::NonZeroUsize;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use core::ops::Deref; use core::ops::Deref;
use core::ptr::{self, NonNull}; use core::ptr::{self, NonNull};
...@@ -109,7 +110,7 @@ fn as_raw_mut_slice(&mut self) -> *mut [T] { ...@@ -109,7 +110,7 @@ fn as_raw_mut_slice(&mut self) -> *mut [T] {
/// ``` /// ```
/// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter(); /// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter();
/// let mut into_iter = std::mem::replace(&mut into_iter, Vec::new().into_iter()); /// let mut into_iter = std::mem::replace(&mut into_iter, Vec::new().into_iter());
/// (&mut into_iter).for_each(core::mem::drop); /// (&mut into_iter).for_each(drop);
/// std::mem::forget(into_iter); /// std::mem::forget(into_iter);
/// ``` /// ```
/// ///
...@@ -215,7 +216,7 @@ fn size_hint(&self) -> (usize, Option<usize>) { ...@@ -215,7 +216,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
} }
#[inline] #[inline]
fn advance_by(&mut self, n: usize) -> Result<(), usize> { fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
let step_size = self.len().min(n); let step_size = self.len().min(n);
let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size); let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size);
if T::IS_ZST { if T::IS_ZST {
...@@ -229,10 +230,7 @@ fn advance_by(&mut self, n: usize) -> Result<(), usize> { ...@@ -229,10 +230,7 @@ fn advance_by(&mut self, n: usize) -> Result<(), usize> {
unsafe { unsafe {
ptr::drop_in_place(to_drop); ptr::drop_in_place(to_drop);
} }
if step_size < n { NonZeroUsize::new(n - step_size).map_or(Ok(()), Err)
return Err(step_size);
}
Ok(())
} }
#[inline] #[inline]
...@@ -315,7 +313,7 @@ fn next_back(&mut self) -> Option<T> { ...@@ -315,7 +313,7 @@ fn next_back(&mut self) -> Option<T> {
} }
#[inline] #[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
let step_size = self.len().min(n); let step_size = self.len().min(n);
if T::IS_ZST { if T::IS_ZST {
// SAFETY: same as for advance_by() // SAFETY: same as for advance_by()
...@@ -329,10 +327,7 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { ...@@ -329,10 +327,7 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
unsafe { unsafe {
ptr::drop_in_place(to_drop); ptr::drop_in_place(to_drop);
} }
if step_size < n { NonZeroUsize::new(n - step_size).map_or(Ok(()), Err)
return Err(step_size);
}
Ok(())
} }
} }
...@@ -349,6 +344,24 @@ impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {} ...@@ -349,6 +344,24 @@ impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}
#[unstable(feature = "trusted_len", issue = "37572")] #[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {} unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}
#[stable(feature = "default_iters", since = "1.70.0")]
impl<T, A> Default for IntoIter<T, A>
where
A: Allocator + Default,
{
/// Creates an empty `vec::IntoIter`.
///
/// ```
/// # use std::vec;
/// let iter: vec::IntoIter<u8> = 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)] #[doc(hidden)]
#[unstable(issue = "none", feature = "std_internals")] #[unstable(issue = "none", feature = "std_internals")]
#[rustc_unsafe_specialization_marker] #[rustc_unsafe_specialization_marker]
......
...@@ -58,13 +58,9 @@ ...@@ -58,13 +58,9 @@
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use core::cmp; use core::cmp;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::convert::TryFrom;
use core::fmt; use core::fmt;
use core::hash::{Hash, Hasher}; use core::hash::{Hash, Hasher};
use core::intrinsics::assume;
use core::iter; use core::iter;
#[cfg(not(no_global_oom_handling))]
use core::iter::FromIterator;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ops::{self, Index, IndexMut, Range, RangeBounds}; use core::ops::{self, Index, IndexMut, Range, RangeBounds};
...@@ -381,8 +377,8 @@ ...@@ -381,8 +377,8 @@
/// Currently, `Vec` does not guarantee the order in which elements are dropped. /// Currently, `Vec` does not guarantee the order in which elements are dropped.
/// The order has changed in the past and may change again. /// The order has changed in the past and may change again.
/// ///
/// [`get`]: ../../std/vec/struct.Vec.html#method.get /// [`get`]: slice::get
/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut /// [`get_mut`]: slice::get_mut
/// [`String`]: crate::string::String /// [`String`]: crate::string::String
/// [`&str`]: type@str /// [`&str`]: type@str
/// [`shrink_to_fit`]: Vec::shrink_to_fit /// [`shrink_to_fit`]: Vec::shrink_to_fit
...@@ -708,14 +704,14 @@ pub const fn new_in(alloc: A) -> Self { ...@@ -708,14 +704,14 @@ pub const fn new_in(alloc: A) -> Self {
/// ///
/// // The vector contains no items, even though it has capacity for more /// // The vector contains no items, even though it has capacity for more
/// assert_eq!(vec.len(), 0); /// assert_eq!(vec.len(), 0);
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// ///
/// // These are all done without reallocating... /// // These are all done without reallocating...
/// for i in 0..10 { /// for i in 0..10 {
/// vec.push(i); /// vec.push(i);
/// } /// }
/// assert_eq!(vec.len(), 10); /// assert_eq!(vec.len(), 10);
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// ///
/// // ...but this may make the vector reallocate /// // ...but this may make the vector reallocate
/// vec.push(11); /// vec.push(11);
...@@ -766,14 +762,14 @@ pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { ...@@ -766,14 +762,14 @@ pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
/// ///
/// // The vector contains no items, even though it has capacity for more /// // The vector contains no items, even though it has capacity for more
/// assert_eq!(vec.len(), 0); /// assert_eq!(vec.len(), 0);
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// ///
/// // These are all done without reallocating... /// // These are all done without reallocating...
/// for i in 0..10 { /// for i in 0..10 {
/// vec.push(i); /// vec.push(i);
/// } /// }
/// assert_eq!(vec.len(), 10); /// assert_eq!(vec.len(), 10);
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// ///
/// // ...but this may make the vector reallocate /// // ...but this may make the vector reallocate
/// vec.push(11); /// vec.push(11);
...@@ -999,7 +995,7 @@ pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { ...@@ -999,7 +995,7 @@ pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) {
/// ``` /// ```
/// let mut vec: Vec<i32> = Vec::with_capacity(10); /// let mut vec: Vec<i32> = Vec::with_capacity(10);
/// vec.push(42); /// vec.push(42);
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
...@@ -1150,7 +1146,7 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE ...@@ -1150,7 +1146,7 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE
/// ``` /// ```
/// let mut vec = Vec::with_capacity(10); /// let mut vec = Vec::with_capacity(10);
/// vec.extend([1, 2, 3]); /// vec.extend([1, 2, 3]);
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// vec.shrink_to_fit(); /// vec.shrink_to_fit();
/// assert!(vec.capacity() >= 3); /// assert!(vec.capacity() >= 3);
/// ``` /// ```
...@@ -1177,7 +1173,7 @@ pub fn shrink_to_fit(&mut self) { ...@@ -1177,7 +1173,7 @@ pub fn shrink_to_fit(&mut self) {
/// ``` /// ```
/// let mut vec = Vec::with_capacity(10); /// let mut vec = Vec::with_capacity(10);
/// vec.extend([1, 2, 3]); /// vec.extend([1, 2, 3]);
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// vec.shrink_to(4); /// vec.shrink_to(4);
/// assert!(vec.capacity() >= 4); /// assert!(vec.capacity() >= 4);
/// vec.shrink_to(0); /// vec.shrink_to(0);
...@@ -1212,7 +1208,7 @@ pub fn shrink_to(&mut self, min_capacity: usize) { ...@@ -1212,7 +1208,7 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
/// let mut vec = Vec::with_capacity(10); /// let mut vec = Vec::with_capacity(10);
/// vec.extend([1, 2, 3]); /// vec.extend([1, 2, 3]);
/// ///
/// assert_eq!(vec.capacity(), 10); /// assert!(vec.capacity() >= 10);
/// let slice = vec.into_boxed_slice(); /// let slice = vec.into_boxed_slice();
/// assert_eq!(slice.into_vec().capacity(), 3); /// assert_eq!(slice.into_vec().capacity(), 3);
/// ``` /// ```
...@@ -1358,11 +1354,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] { ...@@ -1358,11 +1354,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
pub fn as_ptr(&self) -> *const T { pub fn as_ptr(&self) -> *const T {
// We shadow the slice method of the same name to avoid going through // We shadow the slice method of the same name to avoid going through
// `deref`, which creates an intermediate reference. // `deref`, which creates an intermediate reference.
let ptr = self.buf.ptr(); self.buf.ptr()
unsafe {
assume(!ptr.is_null());
}
ptr
} }
/// Returns an unsafe mutable pointer to the vector's buffer, or a dangling /// Returns an unsafe mutable pointer to the vector's buffer, or a dangling
...@@ -1395,11 +1387,7 @@ pub fn as_ptr(&self) -> *const T { ...@@ -1395,11 +1387,7 @@ pub fn as_ptr(&self) -> *const T {
pub fn as_mut_ptr(&mut self) -> *mut T { pub fn as_mut_ptr(&mut self) -> *mut T {
// We shadow the slice method of the same name to avoid going through // We shadow the slice method of the same name to avoid going through
// `deref_mut`, which creates an intermediate reference. // `deref_mut`, which creates an intermediate reference.
let ptr = self.buf.ptr(); self.buf.ptr()
unsafe {
assume(!ptr.is_null());
}
ptr
} }
/// Returns a reference to the underlying allocator. /// Returns a reference to the underlying allocator.
...@@ -2891,35 +2879,6 @@ fn deref_mut(&mut self) -> &mut [T] { ...@@ -2891,35 +2879,6 @@ fn deref_mut(&mut self) -> &mut [T] {
} }
} }
#[cfg(not(no_global_oom_handling))]
trait SpecCloneFrom {
fn clone_from(this: &mut Self, other: &Self);
}
#[cfg(not(no_global_oom_handling))]
impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
default fn clone_from(this: &mut Self, other: &Self) {
// drop anything that will not be overwritten
this.truncate(other.len());
// self.len <= other.len due to the truncate above, so the
// slices here are always in-bounds.
let (init, tail) = other.split_at(this.len());
// reuse the contained values' allocations/resources.
this.clone_from_slice(init);
this.extend_from_slice(tail);
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
fn clone_from(this: &mut Self, other: &Self) {
this.clear();
this.extend_from_slice(other);
}
}
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> { impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
...@@ -2940,7 +2899,7 @@ fn clone(&self) -> Self { ...@@ -2940,7 +2899,7 @@ fn clone(&self) -> Self {
} }
fn clone_from(&mut self, other: &Self) { fn clone_from(&mut self, other: &Self) {
SpecCloneFrom::clone_from(self, other) crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self);
} }
} }
...@@ -2948,7 +2907,6 @@ fn clone_from(&mut self, other: &Self) { ...@@ -2948,7 +2907,6 @@ fn clone_from(&mut self, other: &Self) {
/// as required by the `core::borrow::Borrow` implementation. /// as required by the `core::borrow::Borrow` implementation.
/// ///
/// ``` /// ```
/// #![feature(build_hasher_simple_hash_one)]
/// use std::hash::BuildHasher; /// use std::hash::BuildHasher;
/// ///
/// let b = std::collections::hash_map::RandomState::new(); /// let b = std::collections::hash_map::RandomState::new();
...@@ -3330,7 +3288,7 @@ fn extend_reserve(&mut self, additional: usize) { ...@@ -3330,7 +3288,7 @@ fn extend_reserve(&mut self, additional: usize) {
} }
} }
/// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). /// Implements comparison of vectors, [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd, A: Allocator> PartialOrd for Vec<T, A> { impl<T: PartialOrd, A: Allocator> PartialOrd for Vec<T, A> {
#[inline] #[inline]
...@@ -3342,7 +3300,7 @@ fn partial_cmp(&self, other: &Self) -> Option<Ordering> { ...@@ -3342,7 +3300,7 @@ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: Eq, A: Allocator> Eq for Vec<T, A> {} impl<T: Eq, A: Allocator> Eq for Vec<T, A> {}
/// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). /// Implements ordering of vectors, [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord, A: Allocator> Ord for Vec<T, A> { impl<T: Ord, A: Allocator> Ord for Vec<T, A> {
#[inline] #[inline]
...@@ -3365,8 +3323,7 @@ fn drop(&mut self) { ...@@ -3365,8 +3323,7 @@ fn drop(&mut self) {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] impl<T> Default for Vec<T> {
impl<T> const Default for Vec<T> {
/// Creates an empty `Vec<T>`. /// Creates an empty `Vec<T>`.
/// ///
/// The vector will not allocate until elements are pushed onto it. /// The vector will not allocate until elements are pushed onto it.
...@@ -3462,10 +3419,7 @@ fn from(s: &mut [T]) -> Vec<T> { ...@@ -3462,10 +3419,7 @@ fn from(s: &mut [T]) -> Vec<T> {
/// ``` /// ```
#[cfg(not(test))] #[cfg(not(test))]
fn from(s: [T; N]) -> Vec<T> { fn from(s: [T; N]) -> Vec<T> {
<[T]>::into_vec( <[T]>::into_vec(Box::new(s))
#[rustc_box]
Box::new(s),
)
} }
#[cfg(test)] #[cfg(test)]
...@@ -3490,8 +3444,8 @@ impl<'a, T> From<Cow<'a, [T]>> for Vec<T> ...@@ -3490,8 +3444,8 @@ impl<'a, T> From<Cow<'a, [T]>> for Vec<T>
/// ///
/// ``` /// ```
/// # use std::borrow::Cow; /// # use std::borrow::Cow;
/// let o: Cow<[i32]> = Cow::Owned(vec![1, 2, 3]); /// let o: Cow<'_, [i32]> = Cow::Owned(vec![1, 2, 3]);
/// let b: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]); /// let b: Cow<'_, [i32]> = Cow::Borrowed(&[1, 2, 3]);
/// assert_eq!(Vec::from(o), Vec::from(b)); /// assert_eq!(Vec::from(o), Vec::from(b));
/// ``` /// ```
fn from(s: Cow<'a, [T]>) -> Vec<T> { fn from(s: Cow<'a, [T]>) -> Vec<T> {
......
...@@ -37,14 +37,21 @@ pub extern "C" fn $ident() { ...@@ -37,14 +37,21 @@ pub extern "C" fn $ident() {
); );
define_panicking_intrinsics!("`f32` should not be used", { define_panicking_intrinsics!("`f32` should not be used", {
__addsf3,
__eqsf2, __eqsf2,
__gesf2, __gesf2,
__lesf2, __lesf2,
__ltsf2,
__mulsf3,
__nesf2, __nesf2,
__unordsf2, __unordsf2,
}); });
define_panicking_intrinsics!("`f64` should not be used", { define_panicking_intrinsics!("`f64` should not be used", {
__adddf3,
__ledf2,
__ltdf2,
__muldf3,
__unorddf2, __unorddf2,
}); });
......
...@@ -83,53 +83,6 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { ...@@ -83,53 +83,6 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
#[global_allocator] #[global_allocator]
static ALLOCATOR: KernelAllocator = KernelAllocator; static ALLOCATOR: KernelAllocator = KernelAllocator;
// `rustc` only generates these for some crate types. Even then, we would need // See <https://github.com/rust-lang/rust/pull/86844>.
// to extract the object file that has them from the archive. For the moment,
// let's generate them ourselves instead.
//
// Note: Although these are *safe* functions, they are called by the compiler
// with parameters that obey the same `GlobalAlloc` function safety
// requirements: size and align should form a valid layout, and size is
// greater than 0.
//
// Note that `#[no_mangle]` implies exported too, nowadays.
#[no_mangle] #[no_mangle]
fn __rust_alloc(size: usize, align: usize) -> *mut u8 { static __rust_no_alloc_shim_is_unstable: u8 = 0;
// SAFETY: See assumption above.
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
// SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
// than 0.
unsafe { krealloc_aligned(ptr::null_mut(), layout, bindings::GFP_KERNEL) }
}
#[no_mangle]
fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
unsafe { bindings::kfree(ptr as *const core::ffi::c_void) };
}
#[no_mangle]
fn __rust_realloc(ptr: *mut u8, _old_size: usize, align: usize, new_size: usize) -> *mut u8 {
// SAFETY: See assumption above.
let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, align) };
// SAFETY: Per assumption above, `ptr` is allocated by `__rust_*` before, and the size of
// `new_layout` is greater than 0.
unsafe { krealloc_aligned(ptr, new_layout, bindings::GFP_KERNEL) }
}
#[no_mangle]
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
// SAFETY: See assumption above.
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
// SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
// than 0.
unsafe {
krealloc_aligned(
ptr::null_mut(),
layout,
bindings::GFP_KERNEL | bindings::__GFP_ZERO,
)
}
}
...@@ -31,7 +31,7 @@ llvm) ...@@ -31,7 +31,7 @@ llvm)
fi fi
;; ;;
rustc) rustc)
echo 1.68.2 echo 1.71.1
;; ;;
bindgen) bindgen)
echo 0.56.0 echo 0.56.0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment