Skip to content

Commit ceea62e

Browse files
ojedaintel-lab-lkp
authored andcommittedAug 23, 2023
rust: upgrade to Rust 1.72.0
This is the second upgrade to the Rust toolchain, from 1.71.1 to 1.72.0 (i.e. the latest) [1]. See the upgrade policy [2] and the comments on the first upgrade in commit 3ed03f4 ("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 [3] for details. # Other improvements Previously, the compiler could incorrectly generate a `.eh_frame` section under `-Cpanic=abort`. We were hitting this bug in our old `rust` branch [4]. Gary fixed the issue in Rust 1.72.0 [5]. # Required changes For the upgrade, the following changes are required: - A call to `Box::from_raw` in `rust/kernel/sync/arc.rs` now requires an explicit `drop()` call. See previous patch for details. # `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://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1720-2023-08-24 [1] Link: https://rust-for-linux.com/rust-version-policy [2] Link: Rust-for-Linux#2 [3] Closes: Rust-for-Linux#1012 [4] Link: rust-lang/rust#112403 [5] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 32348c3 commit ceea62e

File tree

8 files changed

+187
-266
lines changed

8 files changed

+187
-266
lines changed
 

‎Documentation/process/changes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils.
3131
====================== =============== ========================================
3232
GNU C 5.1 gcc --version
3333
Clang/LLVM (optional) 11.0.0 clang --version
34-
Rust (optional) 1.71.1 rustc --version
34+
Rust (optional) 1.72.0 rustc --version
3535
bindgen (optional) 0.65.1 bindgen --version
3636
GNU make 3.82 make --version
3737
bash 4.2 bash --version

‎rust/alloc/alloc.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
#[cfg(not(test))]
88
use core::intrinsics;
9+
#[cfg(all(bootstrap, not(test)))]
910
use core::intrinsics::{min_align_of_val, size_of_val};
1011

12+
#[cfg(all(bootstrap, not(test)))]
1113
use core::ptr::Unique;
1214
#[cfg(not(test))]
1315
use core::ptr::{self, NonNull};
@@ -40,7 +42,6 @@ extern "Rust" {
4042
#[rustc_nounwind]
4143
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
4244

43-
#[cfg(not(bootstrap))]
4445
static __rust_no_alloc_shim_is_unstable: u8;
4546
}
4647

@@ -98,7 +99,6 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
9899
unsafe {
99100
// Make sure we don't accidentally allow omitting the allocator shim in
100101
// stable code until it is actually stabilized.
101-
#[cfg(not(bootstrap))]
102102
core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable);
103103

104104
__rust_alloc(layout.size(), layout.align())
@@ -339,14 +339,15 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
339339
}
340340
}
341341

342-
#[cfg_attr(not(test), lang = "box_free")]
342+
#[cfg(all(bootstrap, not(test)))]
343+
#[lang = "box_free"]
343344
#[inline]
344345
// This signature has to be the same as `Box`, otherwise an ICE will happen.
345346
// When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as
346347
// well.
347348
// For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`,
348349
// this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well.
349-
pub(crate) unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) {
350+
unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) {
350351
unsafe {
351352
let size = size_of_val(ptr.as_ref());
352353
let align = min_align_of_val(ptr.as_ref());

‎rust/alloc/boxed.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,8 +1215,16 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
12151215

12161216
#[stable(feature = "rust1", since = "1.0.0")]
12171217
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
1218+
#[inline]
12181219
fn drop(&mut self) {
1219-
// FIXME: Do nothing, drop is currently performed by compiler.
1220+
// the T in the Box is dropped by the compiler before the destructor is run
1221+
1222+
let ptr = self.0;
1223+
1224+
unsafe {
1225+
let layout = Layout::for_value_raw(ptr.as_ptr());
1226+
self.1.deallocate(From::from(ptr.cast()), layout)
1227+
}
12201228
}
12211229
}
12221230

‎rust/alloc/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
//! [`Rc`]: rc
5959
//! [`RefCell`]: core::cell
6060
61+
// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be
62+
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
63+
// rustc itself never sets the feature, so this line has no affect there.
64+
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
65+
//
6166
#![allow(unused_attributes)]
6267
#![stable(feature = "alloc", since = "1.36.0")]
6368
#![doc(
@@ -77,11 +82,6 @@
7782
))]
7883
#![no_std]
7984
#![needs_allocator]
80-
// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be
81-
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
82-
// rustc itself never sets the feature, so this line has no affect there.
83-
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
84-
//
8585
// Lints:
8686
#![deny(unsafe_op_in_unsafe_fn)]
8787
#![deny(fuzzy_provenance_casts)]

‎rust/alloc/vec/drain_filter.rs

Lines changed: 0 additions & 199 deletions
This file was deleted.

‎rust/alloc/vec/extract_if.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR MIT
2+
3+
use crate::alloc::{Allocator, Global};
4+
use core::ptr;
5+
use core::slice;
6+
7+
use super::Vec;
8+
9+
/// An iterator which uses a closure to determine if an element should be removed.
10+
///
11+
/// This struct is created by [`Vec::extract_if`].
12+
/// See its documentation for more.
13+
///
14+
/// # Example
15+
///
16+
/// ```
17+
/// #![feature(extract_if)]
18+
///
19+
/// let mut v = vec![0, 1, 2];
20+
/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(|x| *x % 2 == 0);
21+
/// ```
22+
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
23+
#[derive(Debug)]
24+
#[must_use = "iterators are lazy and do nothing unless consumed"]
25+
pub struct ExtractIf<
26+
'a,
27+
T,
28+
F,
29+
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
30+
> where
31+
F: FnMut(&mut T) -> bool,
32+
{
33+
pub(super) vec: &'a mut Vec<T, A>,
34+
/// The index of the item that will be inspected by the next call to `next`.
35+
pub(super) idx: usize,
36+
/// The number of items that have been drained (removed) thus far.
37+
pub(super) del: usize,
38+
/// The original length of `vec` prior to draining.
39+
pub(super) old_len: usize,
40+
/// The filter test predicate.
41+
pub(super) pred: F,
42+
}
43+
44+
impl<T, F, A: Allocator> ExtractIf<'_, T, F, A>
45+
where
46+
F: FnMut(&mut T) -> bool,
47+
{
48+
/// Returns a reference to the underlying allocator.
49+
#[unstable(feature = "allocator_api", issue = "32838")]
50+
#[inline]
51+
pub fn allocator(&self) -> &A {
52+
self.vec.allocator()
53+
}
54+
}
55+
56+
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
57+
impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A>
58+
where
59+
F: FnMut(&mut T) -> bool,
60+
{
61+
type Item = T;
62+
63+
fn next(&mut self) -> Option<T> {
64+
unsafe {
65+
while self.idx < self.old_len {
66+
let i = self.idx;
67+
let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len);
68+
let drained = (self.pred)(&mut v[i]);
69+
// Update the index *after* the predicate is called. If the index
70+
// is updated prior and the predicate panics, the element at this
71+
// index would be leaked.
72+
self.idx += 1;
73+
if drained {
74+
self.del += 1;
75+
return Some(ptr::read(&v[i]));
76+
} else if self.del > 0 {
77+
let del = self.del;
78+
let src: *const T = &v[i];
79+
let dst: *mut T = &mut v[i - del];
80+
ptr::copy_nonoverlapping(src, dst, 1);
81+
}
82+
}
83+
None
84+
}
85+
}
86+
87+
fn size_hint(&self) -> (usize, Option<usize>) {
88+
(0, Some(self.old_len - self.idx))
89+
}
90+
}
91+
92+
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
93+
impl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A>
94+
where
95+
F: FnMut(&mut T) -> bool,
96+
{
97+
fn drop(&mut self) {
98+
unsafe {
99+
if self.idx < self.old_len && self.del > 0 {
100+
// This is a pretty messed up state, and there isn't really an
101+
// obviously right thing to do. We don't want to keep trying
102+
// to execute `pred`, so we just backshift all the unprocessed
103+
// elements and tell the vec that they still exist. The backshift
104+
// is required to prevent a double-drop of the last successfully
105+
// drained item prior to a panic in the predicate.
106+
let ptr = self.vec.as_mut_ptr();
107+
let src = ptr.add(self.idx);
108+
let dst = src.sub(self.del);
109+
let tail_len = self.old_len - self.idx;
110+
src.copy_to(dst, tail_len);
111+
}
112+
self.vec.set_len(self.old_len - self.del);
113+
}
114+
}
115+
}

‎rust/alloc/vec/mod.rs

Lines changed: 51 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ use crate::boxed::Box;
7474
use crate::collections::{TryReserveError, TryReserveErrorKind};
7575
use crate::raw_vec::RawVec;
7676

77-
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
78-
pub use self::drain_filter::DrainFilter;
77+
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
78+
pub use self::extract_if::ExtractIf;
7979

80-
mod drain_filter;
80+
mod extract_if;
8181

8282
#[cfg(not(no_global_oom_handling))]
8383
#[stable(feature = "vec_splice", since = "1.21.0")]
@@ -618,22 +618,20 @@ impl<T> Vec<T> {
618618
/// Using memory that was allocated elsewhere:
619619
///
620620
/// ```rust
621-
/// #![feature(allocator_api)]
622-
///
623-
/// use std::alloc::{AllocError, Allocator, Global, Layout};
621+
/// use std::alloc::{alloc, Layout};
624622
///
625623
/// fn main() {
626624
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
627625
///
628626
/// let vec = unsafe {
629-
/// let mem = match Global.allocate(layout) {
630-
/// Ok(mem) => mem.cast::<u32>().as_ptr(),
631-
/// Err(AllocError) => return,
632-
/// };
627+
/// let mem = alloc(layout).cast::<u32>();
628+
/// if mem.is_null() {
629+
/// return;
630+
/// }
633631
///
634632
/// mem.write(1_000_000);
635633
///
636-
/// Vec::from_raw_parts_in(mem, 1, 16, Global)
634+
/// Vec::from_raw_parts(mem, 1, 16)
637635
/// };
638636
///
639637
/// assert_eq!(vec, &[1_000_000]);
@@ -876,19 +874,22 @@ impl<T, A: Allocator> Vec<T, A> {
876874
/// Using memory that was allocated elsewhere:
877875
///
878876
/// ```rust
879-
/// use std::alloc::{alloc, Layout};
877+
/// #![feature(allocator_api)]
878+
///
879+
/// use std::alloc::{AllocError, Allocator, Global, Layout};
880880
///
881881
/// fn main() {
882882
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
883+
///
883884
/// let vec = unsafe {
884-
/// let mem = alloc(layout).cast::<u32>();
885-
/// if mem.is_null() {
886-
/// return;
887-
/// }
885+
/// let mem = match Global.allocate(layout) {
886+
/// Ok(mem) => mem.cast::<u32>().as_ptr(),
887+
/// Err(AllocError) => return,
888+
/// };
888889
///
889890
/// mem.write(1_000_000);
890891
///
891-
/// Vec::from_raw_parts(mem, 1, 16)
892+
/// Vec::from_raw_parts_in(mem, 1, 16, Global)
892893
/// };
893894
///
894895
/// assert_eq!(vec, &[1_000_000]);
@@ -2507,7 +2508,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
25072508
let len = self.len();
25082509

25092510
if new_len > len {
2510-
self.extend_with(new_len - len, ExtendElement(value))
2511+
self.extend_with(new_len - len, value)
25112512
} else {
25122513
self.truncate(new_len);
25132514
}
@@ -2545,7 +2546,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
25452546
let len = self.len();
25462547

25472548
if new_len > len {
2548-
self.try_extend_with(new_len - len, ExtendElement(value))
2549+
self.try_extend_with(new_len - len, value)
25492550
} else {
25502551
self.truncate(new_len);
25512552
Ok(())
@@ -2684,26 +2685,10 @@ impl<T, A: Allocator, const N: usize> Vec<[T; N], A> {
26842685
}
26852686
}
26862687

2687-
// This code generalizes `extend_with_{element,default}`.
2688-
trait ExtendWith<T> {
2689-
fn next(&mut self) -> T;
2690-
fn last(self) -> T;
2691-
}
2692-
2693-
struct ExtendElement<T>(T);
2694-
impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
2695-
fn next(&mut self) -> T {
2696-
self.0.clone()
2697-
}
2698-
fn last(self) -> T {
2699-
self.0
2700-
}
2701-
}
2702-
2703-
impl<T, A: Allocator> Vec<T, A> {
2688+
impl<T: Clone, A: Allocator> Vec<T, A> {
27042689
#[cfg(not(no_global_oom_handling))]
2705-
/// Extend the vector by `n` values, using the given generator.
2706-
fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) {
2690+
/// Extend the vector by `n` clones of value.
2691+
fn extend_with(&mut self, n: usize, value: T) {
27072692
self.reserve(n);
27082693

27092694
unsafe {
@@ -2715,24 +2700,24 @@ impl<T, A: Allocator> Vec<T, A> {
27152700

27162701
// Write all elements except the last one
27172702
for _ in 1..n {
2718-
ptr::write(ptr, value.next());
2703+
ptr::write(ptr, value.clone());
27192704
ptr = ptr.add(1);
2720-
// Increment the length in every step in case next() panics
2705+
// Increment the length in every step in case clone() panics
27212706
local_len.increment_len(1);
27222707
}
27232708

27242709
if n > 0 {
27252710
// We can write the last element directly without cloning needlessly
2726-
ptr::write(ptr, value.last());
2711+
ptr::write(ptr, value);
27272712
local_len.increment_len(1);
27282713
}
27292714

27302715
// len set by scope guard
27312716
}
27322717
}
27332718

2734-
/// Try to extend the vector by `n` values, using the given generator.
2735-
fn try_extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) -> Result<(), TryReserveError> {
2719+
/// Try to extend the vector by `n` clones of value.
2720+
fn try_extend_with(&mut self, n: usize, value: T) -> Result<(), TryReserveError> {
27362721
self.try_reserve(n)?;
27372722

27382723
unsafe {
@@ -2744,15 +2729,15 @@ impl<T, A: Allocator> Vec<T, A> {
27442729

27452730
// Write all elements except the last one
27462731
for _ in 1..n {
2747-
ptr::write(ptr, value.next());
2732+
ptr::write(ptr, value.clone());
27482733
ptr = ptr.add(1);
2749-
// Increment the length in every step in case next() panics
2734+
// Increment the length in every step in case clone() panics
27502735
local_len.increment_len(1);
27512736
}
27522737

27532738
if n > 0 {
27542739
// We can write the last element directly without cloning needlessly
2755-
ptr::write(ptr, value.last());
2740+
ptr::write(ptr, value);
27562741
local_len.increment_len(1);
27572742
}
27582743

@@ -3210,6 +3195,12 @@ impl<T, A: Allocator> Vec<T, A> {
32103195
/// If the closure returns false, the element will remain in the vector and will not be yielded
32113196
/// by the iterator.
32123197
///
3198+
/// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
3199+
/// or the iteration short-circuits, then the remaining elements will be retained.
3200+
/// Use [`retain`] with a negated predicate if you do not need the returned iterator.
3201+
///
3202+
/// [`retain`]: Vec::retain
3203+
///
32133204
/// Using this method is equivalent to the following code:
32143205
///
32153206
/// ```
@@ -3228,28 +3219,28 @@ impl<T, A: Allocator> Vec<T, A> {
32283219
/// # assert_eq!(vec, vec![1, 4, 5]);
32293220
/// ```
32303221
///
3231-
/// But `drain_filter` is easier to use. `drain_filter` is also more efficient,
3222+
/// But `extract_if` is easier to use. `extract_if` is also more efficient,
32323223
/// because it can backshift the elements of the array in bulk.
32333224
///
3234-
/// Note that `drain_filter` also lets you mutate every element in the filter closure,
3225+
/// Note that `extract_if` also lets you mutate every element in the filter closure,
32353226
/// regardless of whether you choose to keep or remove it.
32363227
///
32373228
/// # Examples
32383229
///
32393230
/// Splitting an array into evens and odds, reusing the original allocation:
32403231
///
32413232
/// ```
3242-
/// #![feature(drain_filter)]
3233+
/// #![feature(extract_if)]
32433234
/// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
32443235
///
3245-
/// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
3236+
/// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>();
32463237
/// let odds = numbers;
32473238
///
32483239
/// assert_eq!(evens, vec![2, 4, 6, 8, 14]);
32493240
/// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]);
32503241
/// ```
3251-
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
3252-
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F, A>
3242+
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
3243+
pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
32533244
where
32543245
F: FnMut(&mut T) -> bool,
32553246
{
@@ -3260,7 +3251,7 @@ impl<T, A: Allocator> Vec<T, A> {
32603251
self.set_len(0);
32613252
}
32623253

3263-
DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false }
3254+
ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter }
32643255
}
32653256
}
32663257

@@ -3290,9 +3281,14 @@ impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec<T, A> {
32903281

32913282
/// Implements comparison of vectors, [lexicographically](Ord#lexicographical-comparison).
32923283
#[stable(feature = "rust1", since = "1.0.0")]
3293-
impl<T: PartialOrd, A: Allocator> PartialOrd for Vec<T, A> {
3284+
impl<T, A1, A2> PartialOrd<Vec<T, A2>> for Vec<T, A1>
3285+
where
3286+
T: PartialOrd,
3287+
A1: Allocator,
3288+
A2: Allocator,
3289+
{
32943290
#[inline]
3295-
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
3291+
fn partial_cmp(&self, other: &Vec<T, A2>) -> Option<Ordering> {
32963292
PartialOrd::partial_cmp(&**self, &**other)
32973293
}
32983294
}

‎scripts/min-tool-version.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ llvm)
3131
fi
3232
;;
3333
rustc)
34-
echo 1.71.1
34+
echo 1.72.0
3535
;;
3636
bindgen)
3737
echo 0.65.1

0 commit comments

Comments
 (0)
Please sign in to comment.