From nobody Tue Sep 9 12:15:46 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8663BC61DA3 for ; Fri, 24 Feb 2023 09:12:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229695AbjBXJMJ (ORCPT ); Fri, 24 Feb 2023 04:12:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229635AbjBXJMF (ORCPT ); Fri, 24 Feb 2023 04:12:05 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DBAA05D460; Fri, 24 Feb 2023 01:12:04 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id C82703FB17; Fri, 24 Feb 2023 09:12:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677229923; bh=wkplfyZ81CMYGIVsW/sksaSI2sUSjgdmqyg/orT1EzU=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=sSC0VSiw/DFJcOw0MluWtnpjsgxnaq5CRtv7bT0CgvUiR3KLVKidiViSTDTIrv9Y4 A7SYMnJsBK19GyYUUOxTtR1+UEwroRWOqFfiWQ19NETTJEJSGos1xZwqygD7mF0j8C jyLEuKh4WJMXMQh6IPFGkChcOoF+PTmb9cVE5vqvqj9rtaDLnPS3UbiHHntG0q9Vpr oPJWSuhzluFMHv0Wz4+3R4lYTYv/dTifwgoxPPukgEYRwziQqn0aUgGO+KwGtUWFT1 up4AmdxFwYePNonwk1gUiSUGcjRfPrKH89FZermEbHlCFIcaJifuvnam0UQFY5jj9f QivRoXWGRXZ3A== From: Asahi Lina Date: Fri, 24 Feb 2023 18:11:47 +0900 Subject: [PATCH 1/4] rust: Import upstream `alloc::vec::set_len_on_drop` module MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20230224-rust-vec-v1-1-733b5b5a57c5@asahilina.net> References: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> In-Reply-To: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677229917; l=1615; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=wkplfyZ81CMYGIVsW/sksaSI2sUSjgdmqyg/orT1EzU=; b=dpihB9SPTYWGtGlJDBu1TR+XXTZHd3dUY5XNgEcfL9XzxZo4G8htddwW/e3Rk+nV1QD7x8SyI 47RrcxWK6GnBI/z/4z6xeqIM19pQDYRDiG1WxZRMFh7rPO8plJONNEB X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is a subset of the Rust standard library `alloc` crate, version 1.66.0, licensed under "Apache-2.0 OR MIT", from: https://github.com/rust-lang/rust/tree/1.66.0/library/alloc/src The file is copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers). For copyright details, please see: https://github.com/rust-lang/rust/blob/1.66.0/COPYRIGHT Signed-off-by: Asahi Lina --- rust/alloc/vec/set_len_on_drop.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/rust/alloc/vec/set_len_on_drop.rs b/rust/alloc/vec/set_len_on_= drop.rs new file mode 100644 index 000000000000..8b66bc812129 --- /dev/null +++ b/rust/alloc/vec/set_len_on_drop.rs @@ -0,0 +1,28 @@ +// Set the length of the vec when the `SetLenOnDrop` value goes out of sco= pe. +// +// 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 +=3D increment; + } +} + +impl Drop for SetLenOnDrop<'_> { + #[inline] + fn drop(&mut self) { + *self.len =3D self.local_len; + } +} --=20 2.35.1 From nobody Tue Sep 9 12:15:46 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1CE8C6FA99 for ; Fri, 24 Feb 2023 09:12:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229830AbjBXJMO (ORCPT ); Fri, 24 Feb 2023 04:12:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229689AbjBXJMJ (ORCPT ); Fri, 24 Feb 2023 04:12:09 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E544765CDB; Fri, 24 Feb 2023 01:12:07 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id E58264247C; Fri, 24 Feb 2023 09:12:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677229926; bh=aEnf3Yi6W7s32UBEQhPMTbXySskKZPdQMXcNDxihEz0=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=aq+DnANaXmRdkfeWfOIHDk/XU/UrjeHhFYVdtIKu5egVbFN12LN9vWxZBvAXAav6k sOz0sOzcVA3lM4+8CzVqCT+IyWL8nxsJznfkH5EigOR9HSE9v+SpfRWg2pw2zThu3f PGSnyW/YQA/l3oGEEFnunZOtMXdvRiGozGcTk8NcB0hn01RSlz2KbaHkML/FAADRis 6jgjkJIV4u4kmZTuy2KI5MrtAEA3tBMSxQEMoDSGLU/yl8F2DJ7oifZJauUCnAzcQJ 5R+bHCtq0eW9Q3CD4HfBIu/geA5VX5BskkTuK+LAIQXYPQkZzqB2t43lfMDoRt/jep pAmiXv89FdAvw== From: Asahi Lina Date: Fri, 24 Feb 2023 18:11:48 +0900 Subject: [PATCH 2/4] rust: Import upstream `alloc::vec::spec_extend` module MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20230224-rust-vec-v1-2-733b5b5a57c5@asahilina.net> References: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> In-Reply-To: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677229917; l=3800; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=aEnf3Yi6W7s32UBEQhPMTbXySskKZPdQMXcNDxihEz0=; b=g5G05vV5FAJKNC2CQVVFo0gberglSfKhbAQEz33O9+FHYNCX8NT77Z0NrrJRm4nipKklHn4o6 YHpmy1B6hvuCVQnVWkckoagSMkhGg9xHkrDIcEtJt+KIyZ1FYPaTxi+ X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is a subset of the Rust standard library `alloc` crate, version 1.66.0, licensed under "Apache-2.0 OR MIT", from: https://github.com/rust-lang/rust/tree/1.66.0/library/alloc/src The file is copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers). For copyright details, please see: https://github.com/rust-lang/rust/blob/1.66.0/COPYRIGHT Signed-off-by: Asahi Lina --- rust/alloc/vec/spec_extend.rs | 87 +++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 87 insertions(+) diff --git a/rust/alloc/vec/spec_extend.rs b/rust/alloc/vec/spec_extend.rs new file mode 100644 index 000000000000..1ea9c827afd7 --- /dev/null +++ b/rust/alloc/vec/spec_extend.rs @@ -0,0 +1,87 @@ +use crate::alloc::Allocator; +use core::iter::TrustedLen; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{IntoIter, SetLenOnDrop, Vec}; + +// Specialization trait used for Vec::extend +pub(super) trait SpecExtend { + fn spec_extend(&mut self, iter: I); +} + +impl SpecExtend for Vec +where + I: Iterator, +{ + default fn spec_extend(&mut self, iter: I) { + self.extend_desugared(iter) + } +} + +impl SpecExtend for Vec +where + I: TrustedLen, +{ + default fn spec_extend(&mut self, iterator: I) { + // This is the case for a TrustedLen iterator. + let (low, high) =3D iterator.size_hint(); + if let Some(additional) =3D high { + debug_assert_eq!( + low, + additional, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + self.reserve(additional); + unsafe { + let mut ptr =3D self.as_mut_ptr().add(self.len()); + let mut local_len =3D SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr, element); + ptr =3D ptr.add(1); + // Since the loop executes user code which can panic w= e have to bump the pointer + // after each step. + // 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 whi= ch would eventually + // panic anyway. + panic!("capacity overflow"); + } + } +} + +impl SpecExtend> for Vec { + 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 + 'a> SpecExtend<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.cloned()) + } +} + +impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> f= or Vec +where + T: Copy, +{ + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + let slice =3D iterator.as_slice(); + unsafe { self.append_elements(slice) }; + } +} --=20 2.35.1 From nobody Tue Sep 9 12:15:46 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7133C678DB for ; Fri, 24 Feb 2023 09:12:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229888AbjBXJMQ (ORCPT ); Fri, 24 Feb 2023 04:12:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54100 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229686AbjBXJMM (ORCPT ); Fri, 24 Feb 2023 04:12:12 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 15CF465CCF; Fri, 24 Feb 2023 01:12:11 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id 0F3054248B; Fri, 24 Feb 2023 09:12:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677229929; bh=3rLQhx6pCgCH1nt/kKBODlV9KyK5V5WnU4JttIrGeaE=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=JTqSOOWDObGQl6SbhPGAyeB+uQ6O8lswUeHi8xkPbyWkLEUUfcZFBPvNo/f+DoLiy sAa07F42ncojNb88ZTr45LPoq6on1cAE58HI5xknUe2jMu0SXPly0nmxYoEYk79fin 0vWydqfZyx98WSLAqAE1kcuravP5WFg0fB3e1erHAHPpx2ohZ0oh6zEunuOTzFInkz 1WekJMKq/zA+sAQySxW8CNOWOCA90cppSHkYo7ZCbj55yP+wviGAUdbm/toY8pXoOd zHTjO5RWL0EtKCTS0HkFxPpUCSFDyaKDtDLwRP9WCbKiC0lf7zwYdHGB9BJzAfSDOm vwYhHEN9DMc7Q== From: Asahi Lina Date: Fri, 24 Feb 2023 18:11:49 +0900 Subject: [PATCH 3/4] rust: Add SPDX headers to alloc::vec::{spec_extend, set_len_on_drop} MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20230224-rust-vec-v1-3-733b5b5a57c5@asahilina.net> References: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> In-Reply-To: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677229917; l=1258; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=3rLQhx6pCgCH1nt/kKBODlV9KyK5V5WnU4JttIrGeaE=; b=3Pem8NAkc0rGVxf2HfFKgkGSnKln0elEZpuaR/nwYWv/BNMPKncJaYFvU+c2iaRu2aDyaZdpd PgNNhZHrs9cCgbw7w67GdEMTE9b0Ofk5Gt3C6dqoMglyLeTHQLfOA02 X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add the missing SPDX headers to these modules, which were just imported from the Rust stdlib. Doing this in a separate commit makes it easier to audit that the files have not been modified in the original import. See the precending two commits for attribution and licensing details. Signed-off-by: Asahi Lina --- rust/alloc/vec/set_len_on_drop.rs | 2 ++ rust/alloc/vec/spec_extend.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/rust/alloc/vec/set_len_on_drop.rs b/rust/alloc/vec/set_len_on_= drop.rs index 8b66bc812129..448bf5076a0b 100644 --- a/rust/alloc/vec/set_len_on_drop.rs +++ b/rust/alloc/vec/set_len_on_drop.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + // Set the length of the vec when the `SetLenOnDrop` value goes out of sco= pe. // // The idea is: The length field in SetLenOnDrop is a local variable diff --git a/rust/alloc/vec/spec_extend.rs b/rust/alloc/vec/spec_extend.rs index 1ea9c827afd7..ade317ab96b2 100644 --- a/rust/alloc/vec/spec_extend.rs +++ b/rust/alloc/vec/spec_extend.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + use crate::alloc::Allocator; use core::iter::TrustedLen; use core::ptr::{self}; --=20 2.35.1 From nobody Tue Sep 9 12:15:46 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BBEF6C678DB for ; Fri, 24 Feb 2023 09:12:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229780AbjBXJM1 (ORCPT ); Fri, 24 Feb 2023 04:12:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54310 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229810AbjBXJMR (ORCPT ); Fri, 24 Feb 2023 04:12:17 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A210965CFD; Fri, 24 Feb 2023 01:12:14 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id 2D2ED3FA55; Fri, 24 Feb 2023 09:12:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677229933; bh=rySOe8C+EOHBcINSIJX8QO1nEpuKvnx7nO+s+ewSOfE=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=UQisdBOXr/aBVNREW1ajga0fx1kylmLydkZ1A6SEte7+DuX+CrAhj86MBg8ziguPN tlSD413VcSsYZSOzp8cuguz+Q7VF3FJ8Aizf6x+KaegXXEe6CX2M7mZGbBMJPnAZv2 M1FuONlXRamn5MOLK5/GKKnUUAI7KrYamU1I9knhfTdMjr6HpgvpRvBbcmq1QJ5Qmw uscO69ncOFWcw3aBaQa7uc8ma1Kta1viLwIjr7uWrzAT7Tpy38OqM1WXxDVupQctH3 kG3zAef3n5Lpym14EiG6jhPh2ZlhVPd4+D6Kf5yBEUZYHi6v5o+Xe9GHtwcglvRd7i QXioyjHFpZP3g== From: Asahi Lina Date: Fri, 24 Feb 2023 18:11:50 +0900 Subject: [PATCH 4/4] rust: alloc: vec: Add some try_* methods we need MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20230224-rust-vec-v1-4-733b5b5a57c5@asahilina.net> References: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> In-Reply-To: <20230224-rust-vec-v1-0-733b5b5a57c5@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677229917; l=12257; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=D79jXdo5FTKXLLha+LXra032tDEtF09O0Gra2CyUwtA=; b=ESmxTKHa/YudfQcXi8DOpmJs4uMj/rvNEuScGm/xTEWyhQ0wLGK2y+uj+btCcNtUVBCPaSh1Y u/gx1Ds7UTZBnoVDTkvg1G0w/0yaf5as1qym/tCZHf4GL56awYC/Z4Z X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Miguel Ojeda Add some missing fallible methods that we need. They are all marked as: #[stable(feature =3D "kernel", since =3D "1.0.0")] for easy identification. Lina: Extracted from commit 487d7578bd03 ("rust: alloc: add some `try_*` methods we need") in rust-for-linux/rust. Signed-off-by: Miguel Ojeda Signed-off-by: Asahi Lina --- rust/alloc/vec/mod.rs | 137 ++++++++++++++++++++++++++++++++++++++= +++- rust/alloc/vec/spec_extend.rs | 83 +++++++++++++++++++++++++ 2 files changed, 217 insertions(+), 3 deletions(-) diff --git a/rust/alloc/vec/mod.rs b/rust/alloc/vec/mod.rs index f77c7368d534..feb9262b5029 100644 --- a/rust/alloc/vec/mod.rs +++ b/rust/alloc/vec/mod.rs @@ -122,10 +122,8 @@ use self::spec_from_elem::SpecFromElem; #[cfg(not(no_global_oom_handling))] mod spec_from_elem; =20 -#[cfg(not(no_global_oom_handling))] use self::set_len_on_drop::SetLenOnDrop; =20 -#[cfg(not(no_global_oom_handling))] mod set_len_on_drop; =20 #[cfg(not(no_global_oom_handling))] @@ -149,7 +147,8 @@ mod spec_from_iter; #[cfg(not(no_global_oom_handling))] use self::spec_extend::SpecExtend; =20 -#[cfg(not(no_global_oom_handling))] +use self::spec_extend::TrySpecExtend; + mod spec_extend; =20 /// A contiguous growable array type, written as `Vec`, short for 'vect= or'. @@ -1919,6 +1918,17 @@ impl Vec { self.len +=3D count; } =20 + /// Tries to append elements to `self` from other buffer. + #[inline] + unsafe fn try_append_elements(&mut self, other: *const [T]) -> Result<= (), TryReserveError> { + let count =3D unsafe { (*other).len() }; + self.try_reserve(count)?; + let len =3D self.len(); + unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_p= tr().add(len), count) }; + self.len +=3D count; + Ok(()) + } + /// 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. @@ -2340,6 +2350,45 @@ impl Vec { } } =20 + /// Tries to resize 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`] inste= ad of + /// [`Clone`]), use [`Vec::resize_with`]. + /// If you only need to resize to a smaller size, use [`Vec::truncate`= ]. + /// + /// # Examples + /// + /// ``` + /// let mut vec =3D vec!["hello"]; + /// vec.try_resize(3, "world").unwrap(); + /// assert_eq!(vec, ["hello", "world", "world"]); + /// + /// let mut vec =3D vec![1, 2, 3, 4]; + /// vec.try_resize(2, 0).unwrap(); + /// assert_eq!(vec, [1, 2]); + /// + /// let mut vec =3D vec![42]; + /// let result =3D vec.try_resize(usize::MAX, 0); + /// assert!(result.is_err()); + /// ``` + #[stable(feature =3D "kernel", since =3D "1.0.0")] + pub fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), T= ryReserveError> { + let len =3D self.len(); + + if new_len > len { + self.try_extend_with(new_len - len, ExtendElement(value)) + } else { + self.truncate(new_len); + Ok(()) + } + } + /// Clones and appends all elements in a slice to the `Vec`. /// /// Iterates over the slice `other`, clones each element, and then app= ends @@ -2365,6 +2414,30 @@ impl Vec { self.spec_extend(other.iter()) } =20 + /// Tries to clone and append all elements in a slice to the `Vec`. + /// + /// Iterates over the slice `other`, clones each element, and then app= ends + /// 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 =3D vec![1]; + /// vec.try_extend_from_slice(&[2, 3, 4]).unwrap(); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// [`extend`]: Vec::extend + #[stable(feature =3D "kernel", since =3D "1.0.0")] + pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), Try= ReserveError> { + self.try_spec_extend(other.iter()) + } + /// Copies elements from `src` range to the end of the vector. /// /// # Panics @@ -2504,6 +2577,36 @@ impl Vec { // len set by scope guard } } + + /// Try to extend the vector by `n` values, using the given generator. + fn try_extend_with>(&mut self, n: usize, mut value: E= ) -> Result<(), TryReserveError> { + self.try_reserve(n)?; + + unsafe { + let mut ptr =3D 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 =3D SetLenOnDrop::new(&mut self.len); + + // Write all elements except the last one + for _ in 1..n { + ptr::write(ptr, value.next()); + ptr =3D ptr.add(1); + // Increment the length in every step in case next() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning = needlessly + ptr::write(ptr, value.last()); + local_len.increment_len(1); + } + + // len set by scope guard + Ok(()) + } + } } =20 impl Vec { @@ -2838,6 +2941,34 @@ impl Vec { } } =20 + // leaf method to which various SpecFrom/SpecExtend implementations de= legate when + // they have no further optimizations to apply + fn try_extend_desugared>(&mut self, mut iterat= or: I) -> Result<(), TryReserveError> { + // 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) =3D iterator.next() { + let len =3D self.len(); + if len =3D=3D self.capacity() { + let (lower, _) =3D iterator.size_hint(); + self.try_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); + } + } + + Ok(()) + } + /// Creates a splicing iterator that replaces the specified range in t= he vector /// with the given `replace_with` iterator and yields the removed item= s. /// `replace_with` does not need to be the same length as `range`. diff --git a/rust/alloc/vec/spec_extend.rs b/rust/alloc/vec/spec_extend.rs index ade317ab96b2..94d3722b01a1 100644 --- a/rust/alloc/vec/spec_extend.rs +++ b/rust/alloc/vec/spec_extend.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT =20 use crate::alloc::Allocator; +use crate::collections::{TryReserveError, TryReserveErrorKind}; use core::iter::TrustedLen; use core::ptr::{self}; use core::slice::{self}; @@ -8,10 +9,17 @@ use core::slice::{self}; use super::{IntoIter, SetLenOnDrop, Vec}; =20 // Specialization trait used for Vec::extend +#[cfg(not(no_global_oom_handling))] pub(super) trait SpecExtend { fn spec_extend(&mut self, iter: I); } =20 +// Specialization trait used for Vec::try_extend +pub(super) trait TrySpecExtend { + fn try_spec_extend(&mut self, iter: I) -> Result<(), TryReserveError>; +} + +#[cfg(not(no_global_oom_handling))] impl SpecExtend for Vec where I: Iterator, @@ -21,6 +29,16 @@ where } } =20 +impl TrySpecExtend for Vec +where + I: Iterator, +{ + default fn try_spec_extend(&mut self, iter: I) -> Result<(), TryReserv= eError> { + self.try_extend_desugared(iter) + } +} + +#[cfg(not(no_global_oom_handling))] impl SpecExtend for Vec where I: TrustedLen, @@ -59,6 +77,39 @@ where } } =20 +impl TrySpecExtend for Vec +where + I: TrustedLen, +{ + default fn try_spec_extend(&mut self, iterator: I) -> Result<(), TryRe= serveError> { + // This is the case for a TrustedLen iterator. + let (low, high) =3D iterator.size_hint(); + if let Some(additional) =3D high { + debug_assert_eq!( + low, + additional, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + self.try_reserve(additional)?; + unsafe { + let mut ptr =3D self.as_mut_ptr().add(self.len()); + let mut local_len =3D SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr, element); + ptr =3D ptr.offset(1); + // NB can't overflow since we would have had to alloc = the address space + local_len.increment_len(1); + }); + } + Ok(()) + } else { + Err(TryReserveErrorKind::CapacityOverflow.into()) + } + } +} + +#[cfg(not(no_global_oom_handling))] impl SpecExtend> for Vec { fn spec_extend(&mut self, mut iterator: IntoIter) { unsafe { @@ -68,6 +119,17 @@ impl SpecExtend> for Ve= c { } } =20 +impl TrySpecExtend> for Vec { + fn try_spec_extend(&mut self, mut iterator: IntoIter) -> Result<(),= TryReserveError> { + unsafe { + self.try_append_elements(iterator.as_slice() as _)?; + } + iterator.ptr =3D iterator.end; + Ok(()) + } +} + +#[cfg(not(no_global_oom_handling))] impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec where I: Iterator, @@ -78,6 +140,17 @@ where } } =20 +impl<'a, T: 'a, I, A: Allocator + 'a> TrySpecExtend<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn try_spec_extend(&mut self, iterator: I) -> Result<(), TryRe= serveError> { + self.try_spec_extend(iterator.cloned()) + } +} + +#[cfg(not(no_global_oom_handling))] impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> f= or Vec where T: Copy, @@ -87,3 +160,13 @@ where unsafe { self.append_elements(slice) }; } } + +impl<'a, T: 'a, A: Allocator + 'a> TrySpecExtend<&'a T, slice::Iter<'a, T>= > for Vec +where + T: Copy, +{ + fn try_spec_extend(&mut self, iterator: slice::Iter<'a, T>) -> Result<= (), TryReserveError> { + let slice =3D iterator.as_slice(); + unsafe { self.try_append_elements(slice) } + } +} --=20 2.35.1