From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 533CE21A0B; Wed, 27 Mar 2024 02:35:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506955; cv=none; b=sn5KhMHQ4wqYqBJt/dokxywB3IO4WcJ7H8TAM3OnPCqfaHhyKokA3ieCTFDGLVbjqHhATeMB+gIv7cviDxZJFOs7SqIx4NvYS1THa8yg5/60caSLbgGPKUfB1tu3VB9qj+XqP+b21RZIsxe8hITd+B2B6U02zBABMQQYmj5OK/A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506955; c=relaxed/simple; bh=NFBI89hBxJyJdmj/crSHiXYAE5GVZ0Qr9b1Phi95F0A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=R2H/zsGwcPOqeeoXfT9stGIXev3IJ9LN6OJKfwCU5Q1K9ctZa8tnwdoo7qJN5mx0B583n7ibds06ywE+j0jVo9e15tmns0yNzTN5PaiyHRqq5T+6HL6mO26zo6ePRabogfCxusOramx/uSU1ZDxAFSzzFQTk1XczFYM8HgDPx60= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mhZkIM7s; arc=none smtp.client-ip=209.85.210.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mhZkIM7s" Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-6e6b54a28d0so4187307b3a.2; Tue, 26 Mar 2024 19:35:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506953; x=1712111753; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Zwgi78elLsZLyoWMFT63z+tSr2IF4Xl0SkbNI7is8B0=; b=mhZkIM7sOXsvZo3o5j+OgiP22YxFXtvt90ZgXrBH3nDatoBhiFXMCHuYw9KK0/HGoS iJGgs9nqPatzXyjp1NZtuwWEXbj6Ciegj3n5Rg5FTHwxiGJtU0POf88Ab2ptlubn0i+C gkerO0ydJ6v6ciVvkYBkqW5h2hCF4BKhHhTb4W85Me8Gw6DE95iHu6ZthETzIEbe7Qt+ Jfwb3++KW97M1MExsy0C6/Mh5ismlYn5wjS+kQGMAgpEwutTRgcLQyytPRDIQfzz1Htx 4jEupeFZ9rDX7FCNZLjZt/o2Deb8A8E6tzpUC+xQ7dk9utL6hmK42amICeYlZ+hmoM9R 01Sg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506953; x=1712111753; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Zwgi78elLsZLyoWMFT63z+tSr2IF4Xl0SkbNI7is8B0=; b=vj0jx0uIggMby7hyPWh4Cxlp1XEU6JHkxgegPOvdsMo7Psp0bhDTsZ8+SkQgB/4pRv FnK88H+y5ZRVoPybdYjG08nwgIzuoWOwlUNPPTIFRLPmhj12JPHfzk3rTXrtb2MFGz0A bOUlEyy08nXRrYRgR8JbGCY04Roy2wnRNV9aWVcmZ+e4u77oHHQdb0XrM1ax7m5cGPyR XQZoUBOmyDi2VEJxrD9HcnFSf3h6cys/l5Sdpc2rTRJM5MdUM+YCOdyKe/J1gse1OPDI uSnke8OyTKcpJ+WHd9qJUTIOC8qHpiiN/FROpIr8SNdeluvEgO5orI/DPdlDvhrG/wed vK6Q== X-Forwarded-Encrypted: i=1; AJvYcCVMYeP9bk2aY8KM4z96hKfr59AgdiHz0vhjhJCOL5tfg5U6fC67c6FuWRXXC1tIpf4x+enFHsRHBGswI1Om6IHr9b/dL6bFSaZReh4O X-Gm-Message-State: AOJu0YzXlc4NskKtMDbuMXHwnhrgnNPXyS6vwBK4HSKk8hz0/IZw0iFP lijJXpAg1Tni6YLbUMR+m34bQiMVYPKGxNyCPAjdV6uNtb52x9zGnEiIOWJP X-Google-Smtp-Source: AGHT+IEzXziZSAC2AxHRimyV/t+hft4H78E2N2hO1aHrQSqmJWODH4Kj0Xma9E2d1IuOBCckc34+5A== X-Received: by 2002:a05:6a20:f03:b0:1a3:638f:4fbe with SMTP id fl3-20020a056a200f0300b001a3638f4fbemr1251552pzb.42.1711506953609; Tue, 26 Mar 2024 19:35:53 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.35.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:35:53 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 01/10] rust: kernel: move `allocator` module under `alloc` Date: Tue, 26 Mar 2024 23:35:22 -0300 Message-Id: <20240327023531.187880-2-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho We will add more to the `alloc` module in subsequent patches (e.g., allocation flags and extension traits). Reviewed-by: Benno Lossin Signed-off-by: Wedson Almeida Filho --- rust/kernel/alloc.rs | 7 +++++++ rust/kernel/{ =3D> alloc}/allocator.rs | 0 rust/kernel/lib.rs | 4 +--- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 rust/kernel/alloc.rs rename rust/kernel/{ =3D> alloc}/allocator.rs (100%) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs new file mode 100644 index 000000000000..9aa5077d4a4c --- /dev/null +++ b/rust/kernel/alloc.rs @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Extensions to the [`alloc`] crate. + +#[cfg(not(test))] +#[cfg(not(testlib))] +mod allocator; diff --git a/rust/kernel/allocator.rs b/rust/kernel/alloc/allocator.rs similarity index 100% rename from rust/kernel/allocator.rs rename to rust/kernel/alloc/allocator.rs diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index be68d5e567b1..51f30e55bd00 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -28,9 +28,7 @@ // Allow proc-macros to refer to `::kernel` inside the `kernel` crate (thi= s crate). extern crate self as kernel; =20 -#[cfg(not(test))] -#[cfg(not(testlib))] -mod allocator; +pub mod alloc; mod build_assert; pub mod error; pub mod init; --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pg1-f170.google.com (mail-pg1-f170.google.com [209.85.215.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7830722EFD; Wed, 27 Mar 2024 02:36:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506961; cv=none; b=d8k7GQ5SBZ8Wx17dDR7DdpxTHxRl2Zg/GRXFM8uphJb8pfZc2/kV3hLGGQhndQeWcFqU+LxN7BzbGrpkQ23W1OYf9ABFjbobvoEJ2P5riq/QEX+cGLVNQz1g0WQY/k1hXZl0zFrgI0vawgNPmMPxFMQMFgJgXm0+TdI7hG4pVjg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506961; c=relaxed/simple; bh=IilFXnlIHDAkkessE/SpSvQi2ra6lRcyKZ3Q/fq1hX0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=V6Tu6qjfcNwBF6pUeF9zaJvr02s3prJFzNpXSFgrqixSy9oHEy8OaEE25Xb2Pgld7XgswfzyGmzSGtWEywIP//0DNaOE5MYt0vrWkSdysfGA9aHuYPnFSmGg/HbKAg2KLi2ufYcI6Jz/QwDtIQaSv26tDTIFaGXiP9oJ7TkPQPw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=R3bs4OtK; arc=none smtp.client-ip=209.85.215.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="R3bs4OtK" Received: by mail-pg1-f170.google.com with SMTP id 41be03b00d2f7-5bdbe2de25fso4350095a12.3; Tue, 26 Mar 2024 19:36:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506960; x=1712111760; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=is4/ykqJO1ReAP6DDSEum2VHbIujlrPWTW7BeyLRLts=; b=R3bs4OtKpAtY8YI34qjEgzfPmLTEoNgygLf9r9OKRgphrUnHmrnjWiMV0t7NuWd5sw sfxMUHp5BUDWg42fguJYDgGUtS2xcQsk5aQgbBXf+WxHl1A+vBmr2fP+K8I7uvSMoZxl pOJG+d/honceI4D7P3ZAzHZmPrPTdxW9ERdTvHIT/aBccamIfTq/sDqwcWsRu6gbp9A3 boYHnQulv/ldPMlFatoQWVRXdcopEYTx8AXT2ad/blakLIWCCUErO15TPFcta0+oZIvu khKV1qTFw5SgNi/Ztp5Zp/mTx1os2iDYTJaTpnmSm9jh+hLXCq6A2FvJlGYFcMPylbkY XR9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506960; x=1712111760; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=is4/ykqJO1ReAP6DDSEum2VHbIujlrPWTW7BeyLRLts=; b=StOTSKXeH+EtgvBgHRGEeJXIOoa3Cm379jLiA2PoUnMMED/paVSbzIcyf/zFvNWY88 qk1m35B6abY0s4j72fuOEEz+bjx7mkLrUrUguFHQflGJFUl7gS2YXzJrbVNID7UXwopK KMhLRu06MzSdeY8rcHZXGfyzES3cwNHXuTNWpq/rzttsy9bipn+hA6PcrLLYNxWmh/74 OcRhqpwyF4vd5uk3xT1HAfrAbJQ9zvUKiGcwq/BTtGZdvG49Ub5zdzB+0v3I49p+93eJ 1shsEGvkpUXWXTRCTsItjIsIEeisHeMcDjB8Djk0yJ85EU9ev6irlyMzo4aZc8iSbAq+ VJVg== X-Forwarded-Encrypted: i=1; AJvYcCW1lI16jvBU2/Bdg9XaD/w3ChULgO5M5LOkWbOiip+L3l9PGFy1PbrqNHYEb9ifTYLUFwkiN+kxacUxeFLbKysoBcmgQ5KkzoWljjok X-Gm-Message-State: AOJu0YytC13MKnX46d2/AF0TZ2xIBm5dc5T1jmvPcCJhG8R+xLIa3+/N XNHphgNHn2NLrXnnrFat50sWM3GNZay+oLcGoknlCe4pi8javnWbrXmkReOx X-Google-Smtp-Source: AGHT+IEJXNOeGrC8fG7Cyu7MnghCQVLD62lXIUCTJ9s6vTvre02JD899xlD345D1lqGBbelHHPI5Ng== X-Received: by 2002:a05:6a20:548c:b0:1a3:c4c2:b016 with SMTP id i12-20020a056a20548c00b001a3c4c2b016mr1645069pzk.45.1711506959786; Tue, 26 Mar 2024 19:35:59 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.35.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:35:59 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 02/10] rust: alloc: introduce the `VecExt` trait Date: Tue, 26 Mar 2024 23:35:23 -0300 Message-Id: <20240327023531.187880-3-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho Make `try_with_capacity`, `try_push`, and `try_extend_from_slice` methods available in `Vec` even though it doesn't implement them. It is implemented with `try_reserve` and `push_within_capacity`. This is in preparation for switching to the upstream `alloc` crate. Suggested-by: Gary Guo Signed-off-by: Wedson Almeida Filho Reviewed-by: Benno Lossin --- rust/kernel/alloc.rs | 1 + rust/kernel/alloc/vec_ext.rs | 48 ++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + rust/kernel/prelude.rs | 2 ++ 4 files changed, 52 insertions(+) create mode 100644 rust/kernel/alloc/vec_ext.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 9aa5077d4a4c..2c99635f9fd3 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -5,3 +5,4 @@ #[cfg(not(test))] #[cfg(not(testlib))] mod allocator; +pub mod vec_ext; diff --git a/rust/kernel/alloc/vec_ext.rs b/rust/kernel/alloc/vec_ext.rs new file mode 100644 index 000000000000..311e62cc5784 --- /dev/null +++ b/rust/kernel/alloc/vec_ext.rs @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Extensions to [`Vec`] for fallible allocations. + +use alloc::{collections::TryReserveError, vec::Vec}; +use core::result::Result; + +/// Extensions to [`Vec`]. +pub trait VecExt: Sized { + /// Creates a new [`Vec`] instance with at least the given capacity. + fn try_with_capacity(capacity: usize) -> Result; + + /// Appends an element to the back of the [`Vec`] instance. + fn try_push(&mut self, v: T) -> Result<(), TryReserveError>; + + /// Pushes clones of the elements of slice into the [`Vec`] instance. + fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryRese= rveError> + where + T: Clone; +} + +impl VecExt for Vec { + fn try_with_capacity(capacity: usize) -> Result= { + let mut v =3D Vec::new(); + v.try_reserve(capacity)?; + Ok(v) + } + + fn try_push(&mut self, v: T) -> Result<(), TryReserveError> { + if let Err(retry) =3D self.push_within_capacity(v) { + self.try_reserve(1)?; + let _ =3D self.push_within_capacity(retry); + } + Ok(()) + } + + fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryRese= rveError> + where + T: Clone, + { + self.try_reserve(other.len())?; + for item in other { + self.try_push(item.clone())?; + } + + Ok(()) + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 51f30e55bd00..7f2841a18d05 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -19,6 +19,7 @@ #![feature(offset_of)] #![feature(receiver_trait)] #![feature(unsize)] +#![feature(vec_push_within_capacity)] =20 // Ensure conditional compilation based on the kernel configuration works; // otherwise we may silently break things like initcall handling. diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index ae21600970b3..c85b5972c0d3 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,6 +14,8 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 +pub use crate::alloc::vec_ext::VecExt; + #[doc(no_inline)] pub use alloc::{boxed::Box, vec::Vec}; =20 --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pj1-f41.google.com (mail-pj1-f41.google.com [209.85.216.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B45A23765; Wed, 27 Mar 2024 02:36:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506967; cv=none; b=elviScFVJyeXsTs5oT3391Zz1ZI5gx0UbWPurgGw60huCML88A2abn7+QHyQ1nUE1kXZCjw3fxdj9Ojt4NyHQeL1wZQEocT1NrjTrp58GEth6uJEOGBgdEpksjY6jjvXluAwcn7ZqVT9ac3u35pXxzTveSeP8XeCb4DTfpbMy6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506967; c=relaxed/simple; bh=7wD4DM+4/wzThQxX9DjrVUP87VCiEPT5n1Fjkm+x31E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GUwjY4vYOqKE84hFPQOsvv5qtjSq8Slnu6EPQVEbUt5lf4bAT8RU3QrA/7HhsF+tcLUFsM+6Uyc5XHmyv+zBYvM6XUCHuU9kJFEjjexd0ceAXTKo//EyabCPP2s6yf91+fHW/GbB9X7DnB4NSlpgIWCxC2/XJ7NFMIczl7XR03o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RdkdCsvy; arc=none smtp.client-ip=209.85.216.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RdkdCsvy" Received: by mail-pj1-f41.google.com with SMTP id 98e67ed59e1d1-2a0292c4df5so4270439a91.0; Tue, 26 Mar 2024 19:36:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506965; x=1712111765; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sQ7ZlPJAei2sngbAQRg4mA5E6Q2U7TFS5UlJWvZjxqs=; b=RdkdCsvyZFru7jR7MsJkd365Q9QIr0Bw0H7M9a/ch3pMWhsMXuA1f/c8JKplnL6ay4 +ck/ijmIreUHVD3ZhmDFl45mNGRy88ISTz/YGF0glqiQWRgXl0oIojUKJXBU7b7qjFzg yBqotflrIxmmuRcNXPs7BQrSVuA+xZxa+s1G21nypJOENqYrmKXJ457GVyXcWQ/qP/vA cldXAOkjrMZqDR6wg2ruEFeDqy9x5rvBLieOjXm+mgGyqhRP+jPITrEKIMBVGNQadfQS n9h6bNiw+QaMjiFmaKqKUvNFfRmDvVTbZs3suONYMeey4AQpSzKzMfDeeQIIxtddX/25 oZcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506965; x=1712111765; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sQ7ZlPJAei2sngbAQRg4mA5E6Q2U7TFS5UlJWvZjxqs=; b=sW3h+sOIIt1l8WRxYmLpnE5hVcA+jsJ6roa7/hpoAj8h2fDX6zHbZPXkcW889AVzZy ULC1OjA+Aav4wsCZtDdGHpxiHMpLJFbPxDYbVMNdQkpnl7oTLqN78Sn5QT6vUhutJsRl ZBxkeElNqp8jLUgvHjOZJwynVXOUd6NsApiws1jvu7cnVbLHetifIKzfKNAiDOtnbz/t W3DnioRlvrgX8Nf94WxwUF1t+dGIRTMryXUnaQWzhnQLc++mitQQqC2+hZP8sbkZUDgK /RDCLd6pQcZDYvpTPTXCclY9qaxYWC3YcLoA4N+LVC9gjaMaE7i5uvgXqT1CdjbjzQwF BPgQ== X-Forwarded-Encrypted: i=1; AJvYcCVaFWoqIK94fUbLUNVqS+/vqZYOvS1hH/1ZUMYlL+duJ4FYAiQ/whgc7JpoOnh4XMrb4Mvco90ydk/UgJy6ovqIt/hlte57BfZ5Ix/f X-Gm-Message-State: AOJu0YzKj3lnKhDcxktR1U00yGO1qrYFyTPFNxyzyaEW9p2AlBihVcF/ T7VqMlg+D9b4gMWIA1WL6gHWuk7MDXm+dHat0XE0H9ddvE0Kdj5/QacFZd1/ X-Google-Smtp-Source: AGHT+IEoJIjv2zM0t7CuTJ8eCRCoVAfh3GqOnH39zBCcYOD3DN0m6YXtS/cqfHRCbDNFqAjL+02YMA== X-Received: by 2002:a17:90b:4f42:b0:2a1:2506:b937 with SMTP id pj2-20020a17090b4f4200b002a12506b937mr331891pjb.23.1711506964800; Tue, 26 Mar 2024 19:36:04 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:04 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 03/10] kbuild: use the upstream `alloc` crate Date: Tue, 26 Mar 2024 23:35:24 -0300 Message-Id: <20240327023531.187880-4-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho Switch away from our fork of the `alloc` crate. We remove it altogether in the next commit. Signed-off-by: Wedson Almeida Filho --- rust/Makefile | 16 +++------------- rust/kernel/str.rs | 1 + scripts/generate_rust_analyzer.py | 2 +- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/rust/Makefile b/rust/Makefile index a78fcf4004b0..fcb26b53880b 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -61,15 +61,9 @@ core-cfgs =3D \ --cfg no_fp_fmt_parse =20 alloc-cfgs =3D \ - --cfg no_borrow \ - --cfg no_fmt \ --cfg no_global_oom_handling \ - --cfg no_macros \ --cfg no_rc \ - --cfg no_str \ - --cfg no_string \ - --cfg no_sync \ - --cfg no_thin + --cfg no_sync =20 quiet_cmd_rustdoc =3D RUSTDOC $(if $(rustdoc_host),H, ) $< cmd_rustdoc =3D \ @@ -123,7 +117,7 @@ rustdoc-compiler_builtins: $(src)/compiler_builtins.rs = rustdoc-core FORCE # due to things that are "configured out" vs. entirely non-existing ones. rustdoc-alloc: private rustc_target_flags =3D $(alloc-cfgs) \ -Arustdoc::broken_intra_doc_links -rustdoc-alloc: $(src)/alloc/lib.rs rustdoc-core rustdoc-compiler_builtins = FORCE +rustdoc-alloc: $(RUST_LIB_SRC)/alloc/src/lib.rs rustdoc-core rustdoc-compi= ler_builtins FORCE +$(call if_changed,rustdoc) =20 rustdoc-kernel: private rustc_target_flags =3D --extern alloc \ @@ -219,8 +213,6 @@ rusttest: rusttest-macros rusttest-kernel # - `cargo` only considers the use case of building the standard library # to use it in a given package. Thus we need to create a dummy package # and pick the generated libraries from there. -# - Since we only keep a subset of upstream `alloc` in-tree, we need -# to recreate it on the fly by putting our sources on top. # - The usual ways of modifying the dependency graph in `cargo` do not s= eem # to apply for the `-Zbuild-std` steps, thus we have to mislead it # by modifying the sources in the sysroot. @@ -239,8 +231,6 @@ quiet_cmd_rustsysroot =3D RUSTSYSROOT rm -rf $(objtree)/$(obj)/test; \ mkdir -p $(objtree)/$(obj)/test; \ cp -a $(rustc_sysroot) $(objtree)/$(obj)/test/sysroot; \ - cp -r $(srctree)/$(src)/alloc/* \ - $(objtree)/$(obj)/test/sysroot/lib/rustlib/src/rust/library/alloc/src; \ echo '\#!/bin/sh' > $(objtree)/$(obj)/test/rustc_sysroot; \ echo "$(RUSTC) --sysroot=3D$(abspath $(objtree)/$(obj)/test/sysroot) \"\$= $@\"" \ >> $(objtree)/$(obj)/test/rustc_sysroot; \ @@ -444,7 +434,7 @@ $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs= $(obj)/core.o FORCE $(obj)/alloc.o: private skip_clippy =3D 1 $(obj)/alloc.o: private skip_flags =3D -Dunreachable_pub $(obj)/alloc.o: private rustc_target_flags =3D $(alloc-cfgs) -$(obj)/alloc.o: $(src)/alloc/lib.rs $(obj)/compiler_builtins.o FORCE +$(obj)/alloc.o: $(RUST_LIB_SRC)/alloc/src/lib.rs $(obj)/compiler_builtins.= o FORCE +$(call if_changed_dep,rustc_library) =20 $(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FOR= CE diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 925ced8fdc61..e1be6c5e72a9 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -2,6 +2,7 @@ =20 //! String representations. =20 +use crate::alloc::vec_ext::VecExt; use alloc::alloc::AllocError; use alloc::vec::Vec; use core::fmt::{self, Write}; diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_anal= yzer.py index fc52bc41d3e7..f270c7b0cf34 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -66,7 +66,7 @@ def generate_crates(srctree, objtree, sysroot_src, extern= al_src, cfgs): =20 append_crate( "alloc", - srctree / "rust" / "alloc" / "lib.rs", + sysroot_src / "alloc" / "src" / "lib.rs", ["core", "compiler_builtins"], cfg=3Dcrates_cfgs.get("alloc", []), ) --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3382C24B29; Wed, 27 Mar 2024 02:36:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506987; cv=none; b=UvSKNYZenZFQ1sw76ckWyoS2rGL9/S6110gmBioabGpwXOM5zoOpWAFLtYT1J5AcNact6QPmuok4xvcoC21+eELiMmWEJvpP/0LFy8QQZbOhuMqIuk+84herwTIrSCHXxc12GThE4aYperbKwVb8rH0cx+IPBrciIxTyvd+l6FA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506987; c=relaxed/simple; bh=fis8vyGDl1Lr5NA3P0dTa5/D1jbV3OsgRe1KvQ5qlWE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Wb1OPwwd1RaiAjFrtfIlJ2lxnruwEMPzl51jKeEPRtfWsXMRBpoh/q2TNnJj+cT5ZnY+vXPDwYepU+WF6rpERDPbSis7fJqOT24HkPD02PgEnFV4IwPYIgYrLA0+D1KOOqSE5pIHvIRTWIGuVYOYcIoq9DFlBFg6cBQKImPNmZk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ItSOaSkU; arc=none smtp.client-ip=209.85.215.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ItSOaSkU" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-5dbcfa0eb5dso4776096a12.3; Tue, 26 Mar 2024 19:36:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506973; x=1712111773; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lxe4PPezRQcx87AiCc5/rpMEDR2kwnCRXITrqzveac0=; b=ItSOaSkU6ZMoao4eBYKKxt4cRqt3k02k8OrvivwYtzWpzvz6w4/ArElJo1K1Zkl7t6 XRCBOZ6hpaY9qCPZqu+g+f9MUWhhhwhtZb+UiRjqGh6/g5m+QWgrYlaQLcEW9JX0B353 oC3DbJF+sCNU36cmy/LKpmxYrEorN2aBWGOpEuD+0hAlh7Cwl3mAMBE9YtsvatSVywHJ k/+bjEHc2HxthtrY1HHTwxDfbnAlQXm/kwR8Azb8UDKZRXO1wjQQ8+xwfPZ82L8Mas8/ ezdKUQi4xmeH+EDfG4MTBLWS1atHL3rGNrrKDUj9wmwmiMa2fP3jT7EnHJQuZKT/GBa0 Uk2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506973; x=1712111773; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lxe4PPezRQcx87AiCc5/rpMEDR2kwnCRXITrqzveac0=; b=mWAxbYwuoeZFPoFwhIBBn3yr4a3m30d5YLDqIP+eMmh1q8yf+yQSc0lucpGFJGnos9 y2x1PUb3TSHiviFsjMi2FNV3Lo9y4ygHHYHCxcoOwyXxQpH9QdXeu9pAj7a/zxTTHzwn 5MDuk/OqDwK4BnTwURq8KehhLBL7RafnXkHEdzl/TI66McqpphmvrCY80cbM6zp1/5Ge ZtAObZZgek3fBqDs/Q0VxHQl58+76PUsxGqa90FkircOTy3bKSyDmHbaqZIMX0GtiHoQ Fax2YXRMca3tRaaDPYWqQIx8wvwiWlA/u2UEY8cOHNXDcTyHmMDsqBlffWEXV9wrtGaA AMPQ== X-Forwarded-Encrypted: i=1; AJvYcCXL4xyhWSET2PMyIDN1ljMkTEIp8bHQHJ/pKwgVS/r80o1IrNSB7/gNKh2edeIvW+MG7LEV314DcKJCN6bko0UFnIYYE3jUQPlATe8/ X-Gm-Message-State: AOJu0Ywh88cAwZFxVxwGWEGyQ+p4cetGxMl2bHRPHLeHfvKDCkjIwfvE WT1ttDQ3ixTyOTiRbt0ND+GGBZdDk7+w9jKRS0+PwICkCufF5hv+ewlUxEfa X-Google-Smtp-Source: AGHT+IFGGCAIDsbqqeptA6x34Xd4dqzc/inHqAAlNmczZfJ+7kZcQVvaRROzqYeRr21zsMKE95SG+A== X-Received: by 2002:a17:90a:4803:b0:29c:7544:54df with SMTP id a3-20020a17090a480300b0029c754454dfmr4700592pjh.23.1711506972106; Tue, 26 Mar 2024 19:36:12 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:11 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 04/10] rust: alloc: remove our fork of the `alloc` crate Date: Tue, 26 Mar 2024 23:35:25 -0300 Message-Id: <20240327023531.187880-5-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Wedson Almeida Filho It is not used anymore as `VecExt` now provides the functionality we depend on. Reviewed-by: Benno Lossin Signed-off-by: Wedson Almeida Filho --- rust/alloc/README.md | 36 - rust/alloc/alloc.rs | 452 ---- rust/alloc/boxed.rs | 2463 ------------------- rust/alloc/collections/mod.rs | 160 -- rust/alloc/lib.rs | 288 --- rust/alloc/raw_vec.rs | 611 ----- rust/alloc/slice.rs | 890 ------- rust/alloc/vec/drain.rs | 255 -- rust/alloc/vec/extract_if.rs | 115 - rust/alloc/vec/into_iter.rs | 454 ---- rust/alloc/vec/is_zero.rs | 204 -- rust/alloc/vec/mod.rs | 3683 ----------------------------- rust/alloc/vec/partial_eq.rs | 49 - rust/alloc/vec/set_len_on_drop.rs | 35 - rust/alloc/vec/spec_extend.rs | 119 - 15 files changed, 9814 deletions(-) delete mode 100644 rust/alloc/README.md delete mode 100644 rust/alloc/alloc.rs delete mode 100644 rust/alloc/boxed.rs delete mode 100644 rust/alloc/collections/mod.rs delete mode 100644 rust/alloc/lib.rs delete mode 100644 rust/alloc/raw_vec.rs delete mode 100644 rust/alloc/slice.rs delete mode 100644 rust/alloc/vec/drain.rs delete mode 100644 rust/alloc/vec/extract_if.rs delete mode 100644 rust/alloc/vec/into_iter.rs delete mode 100644 rust/alloc/vec/is_zero.rs delete mode 100644 rust/alloc/vec/mod.rs delete mode 100644 rust/alloc/vec/partial_eq.rs delete mode 100644 rust/alloc/vec/set_len_on_drop.rs delete mode 100644 rust/alloc/vec/spec_extend.rs diff --git a/rust/alloc/README.md b/rust/alloc/README.md deleted file mode 100644 index eb6f22e94ebf..000000000000 --- a/rust/alloc/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# `alloc` - -These source files come from the Rust standard library, hosted in -the repository, licensed under -"Apache-2.0 OR MIT" and adapted for kernel use. For copyright details, -see . - -Please note that these files should be kept as close as possible to -upstream. In general, only additions should be performed (e.g. new -methods). Eventually, changes should make it into upstream so that, -at some point, this fork can be dropped from the kernel tree. - -The Rust upstream version on top of which these files are based matches -the output of `scripts/min-tool-version.sh rustc`. - - -## Rationale - -On one hand, kernel folks wanted to keep `alloc` in-tree to have more -freedom in both workflow and actual features if actually needed -(e.g. receiver types if we ended up using them), which is reasonable. - -On the other hand, Rust folks wanted to keep `alloc` as close as -upstream as possible and avoid as much divergence as possible, which -is also reasonable. - -We agreed on a middle-ground: we would keep a subset of `alloc` -in-tree that would be as small and as close as possible to upstream. -Then, upstream can start adding the functions that we add to `alloc` -etc., until we reach a point where the kernel already knows exactly -what it needs in `alloc` and all the new methods are merged into -upstream, so that we can drop `alloc` from the kernel tree and go back -to using the upstream one. - -By doing this, the kernel can go a bit faster now, and Rust can -slowly incorporate and discuss the changes as needed. diff --git a/rust/alloc/alloc.rs b/rust/alloc/alloc.rs deleted file mode 100644 index abb791cc2371..000000000000 --- a/rust/alloc/alloc.rs +++ /dev/null @@ -1,452 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -//! Memory allocation APIs - -#![stable(feature =3D "alloc_module", since =3D "1.28.0")] - -#[cfg(not(test))] -use core::intrinsics; - -#[cfg(not(test))] -use core::ptr::{self, NonNull}; - -#[stable(feature =3D "alloc_module", since =3D "1.28.0")] -#[doc(inline)] -pub use core::alloc::*; - -#[cfg(test)] -mod tests; - -extern "Rust" { - // These are the magic symbols to call the global allocator. rustc gen= erates - // 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 func= tion 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_siz= e: 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=E2=80=99s default. -/// -/// Note: while this type is unstable, the functionality it provides can be -/// accessed through the [free functions in `alloc`](self#functions). -#[unstable(feature =3D "allocator_api", issue =3D "32838")] -#[derive(Copy, Clone, Default, Debug)] -#[cfg(not(test))] -pub struct Global; - -#[cfg(test)] -pub use std::alloc::Global; - -/// Allocate 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=E2=80=99s default. -/// -/// This function is expected to be deprecated in favor of the `alloc` met= hod -/// of the [`Global`] type when it and the [`Allocator`] trait become stab= le. -/// -/// # Safety -/// -/// See [`GlobalAlloc::alloc`]. -/// -/// # Examples -/// -/// ``` -/// use std::alloc::{alloc, dealloc, handle_alloc_error, Layout}; -/// -/// unsafe { -/// let layout =3D Layout::new::(); -/// let ptr =3D alloc(layout); -/// if ptr.is_null() { -/// handle_alloc_error(layout); -/// } -/// -/// *(ptr as *mut u16) =3D 42; -/// assert_eq!(*(ptr as *mut u16), 42); -/// -/// dealloc(ptr, layout); -/// } -/// ``` -#[stable(feature =3D "global_alloc", since =3D "1.28.0")] -#[must_use =3D "losing the pointer will leak memory"] -#[inline] -pub unsafe fn alloc(layout: Layout) -> *mut u8 { - unsafe { - // Make sure we don't accidentally allow omitting the allocator sh= im in - // stable code until it is actually stabilized. - core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable); - - __rust_alloc(layout.size(), layout.align()) - } -} - -/// Deallocate 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=E2=80=99s default. -/// -/// This function is expected to be deprecated in favor of the `dealloc` m= ethod -/// of the [`Global`] type when it and the [`Allocator`] trait become stab= le. -/// -/// # Safety -/// -/// See [`GlobalAlloc::dealloc`]. -#[stable(feature =3D "global_alloc", since =3D "1.28.0")] -#[inline] -pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { - unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } -} - -/// Reallocate 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=E2=80=99s default. -/// -/// This function is expected to be deprecated in favor of the `realloc` m= ethod -/// of the [`Global`] type when it and the [`Allocator`] trait become stab= le. -/// -/// # Safety -/// -/// See [`GlobalAlloc::realloc`]. -#[stable(feature =3D "global_alloc", since =3D "1.28.0")] -#[must_use =3D "losing the pointer will leak memory"] -#[inline] -pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *m= ut u8 { - unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } -} - -/// Allocate zero-initialized memory with the global allocator. -/// -/// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] meth= od -/// of the allocator registered with the `#[global_allocator]` attribute -/// if there is one, or the `std` crate=E2=80=99s default. -/// -/// This function is expected to be deprecated in favor of the `alloc_zero= ed` method -/// of the [`Global`] type when it and the [`Allocator`] trait become stab= le. -/// -/// # Safety -/// -/// See [`GlobalAlloc::alloc_zeroed`]. -/// -/// # Examples -/// -/// ``` -/// use std::alloc::{alloc_zeroed, dealloc, Layout}; -/// -/// unsafe { -/// let layout =3D Layout::new::(); -/// let ptr =3D alloc_zeroed(layout); -/// -/// assert_eq!(*(ptr as *mut u16), 0); -/// -/// dealloc(ptr, layout); -/// } -/// ``` -#[stable(feature =3D "global_alloc", since =3D "1.28.0")] -#[must_use =3D "losing the pointer will leak memory"] -#[inline] -pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { - unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) } -} - -#[cfg(not(test))] -impl Global { - #[inline] - fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result, AllocError> { - match layout.size() { - 0 =3D> Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), - // SAFETY: `layout` is non-zero in size, - size =3D> unsafe { - let raw_ptr =3D if zeroed { alloc_zeroed(layout) } else { = alloc(layout) }; - let ptr =3D NonNull::new(raw_ptr).ok_or(AllocError)?; - Ok(NonNull::slice_from_raw_parts(ptr, size)) - }, - } - } - - // SAFETY: Same as `Allocator::grow` - #[inline] - unsafe fn grow_impl( - &self, - ptr: NonNull, - old_layout: Layout, - new_layout: Layout, - zeroed: bool, - ) -> Result, AllocError> { - debug_assert!( - new_layout.size() >=3D old_layout.size(), - "`new_layout.size()` must be greater than or equal to `old_lay= out.size()`" - ); - - match old_layout.size() { - 0 =3D> self.alloc_impl(new_layout, zeroed), - - // SAFETY: `new_size` is non-zero as `old_size` is greater tha= n or equal to `new_size` - // as required by safety conditions. Other conditions must be = upheld by the caller - old_size if old_layout.align() =3D=3D new_layout.align() =3D> = unsafe { - let new_size =3D new_layout.size(); - - // `realloc` probably checks for `new_size >=3D old_layout= .size()` or something similar. - intrinsics::assume(new_size >=3D old_layout.size()); - - let raw_ptr =3D realloc(ptr.as_ptr(), old_layout, new_size= ); - let ptr =3D NonNull::new(raw_ptr).ok_or(AllocError)?; - if zeroed { - raw_ptr.add(old_size).write_bytes(0, new_size - old_si= ze); - } - 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 dealloca= ted, 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 =3D> unsafe { - let new_ptr =3D 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 =3D "allocator_api", issue =3D "32838")] -#[cfg(not(test))] -unsafe impl Allocator for Global { - #[inline] - fn allocate(&self, layout: Layout) -> Result, AllocError= > { - self.alloc_impl(layout, false) - } - - #[inline] - fn allocate_zeroed(&self, layout: Layout) -> Result, All= ocError> { - self.alloc_impl(layout, true) - } - - #[inline] - unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { - if layout.size() !=3D 0 { - // SAFETY: `layout` is non-zero in size, - // other conditions must be upheld by the caller - unsafe { dealloc(ptr.as_ptr(), layout) } - } - } - - #[inline] - 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] - 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] - unsafe fn shrink( - &self, - ptr: NonNull, - old_layout: Layout, - new_layout: Layout, - ) -> Result, AllocError> { - debug_assert!( - new_layout.size() <=3D old_layout.size(), - "`new_layout.size()` must be smaller than or equal to `old_lay= out.size()`" - ); - - match new_layout.size() { - // SAFETY: conditions must be upheld by the caller - 0 =3D> 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 up= held by the caller - new_size if old_layout.align() =3D=3D new_layout.align() =3D> = unsafe { - // `realloc` probably checks for `new_size <=3D old_layout= .size()` or something similar. - intrinsics::assume(new_size <=3D old_layout.size()); - - let raw_ptr =3D realloc(ptr.as_ptr(), old_layout, new_size= ); - let ptr =3D 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 dealloca= ted, 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 =3D> unsafe { - let new_ptr =3D 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 =3D "exchange_malloc"] -#[inline] -unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { - let layout =3D unsafe { Layout::from_size_align_unchecked(size, align)= }; - match Global.allocate(layout) { - Ok(ptr) =3D> ptr.as_mut_ptr(), - Err(_) =3D> 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. ru= stc 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) -> !; -} - -/// Signal a memory allocation error. -/// -/// Callers of memory allocation APIs wishing to cease execution -/// in response to an allocation error are encouraged to call this functio= n, -/// rather than directly invoking [`panic!`] or similar. -/// -/// This function is guaranteed to diverge (not return normally with a val= ue), but depending on -/// global configuration, it may either panic (resulting in unwinding or a= borting 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 [`ta= ke_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 mar= ked -/// [`#![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.ht= ml -/// [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 =3D "global_alloc", since =3D "1.28.0")] -#[rustc_const_unstable(feature =3D "const_alloc_error", issue =3D "92523")] -#[cfg(all(not(no_global_oom_handling), not(test)))] -#[cold] -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 =3D "panic_immediate_abort"))] - unsafe { - core::intrinsics::const_eval_select((layout,), ct_error, rt_error) - } - - #[cfg(feature =3D "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 =3D "alloc_internals", issue =3D "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=3D{panic,abort} compiler opt= ion. - static __rust_alloc_error_handler_should_panic: u8; - } - - if unsafe { __rust_alloc_error_handler_should_panic !=3D 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, - ) - } - } -} - -#[cfg(not(no_global_oom_handling))] -/// Specialize clones into pre-allocated, uninitialized memory. -/// Used by `Box::clone` and `Rc`/`Arc::make_mut`. -pub(crate) trait WriteCloneIntoRaw: Sized { - unsafe fn write_clone_into_raw(&self, target: *mut Self); -} - -#[cfg(not(no_global_oom_handling))] -impl WriteCloneIntoRaw for T { - #[inline] - default unsafe fn write_clone_into_raw(&self, target: *mut Self) { - // Having allocated *first* may allow the optimizer to create - // the cloned value in-place, skipping the local and move. - unsafe { target.write(self.clone()) }; - } -} - -#[cfg(not(no_global_oom_handling))] -impl WriteCloneIntoRaw for T { - #[inline] - unsafe fn write_clone_into_raw(&self, target: *mut Self) { - // We can always copy in-place, without ever involving a local val= ue. - unsafe { target.copy_from_nonoverlapping(self, 1) }; - } -} diff --git a/rust/alloc/boxed.rs b/rust/alloc/boxed.rs deleted file mode 100644 index c93a22a5c97f..000000000000 --- a/rust/alloc/boxed.rs +++ /dev/null @@ -1,2463 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -//! The `Box` type for heap allocation. -//! -//! [`Box`], casually referred to as a 'box', provides the simplest for= m 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 =3D 5; -//! let boxed: Box =3D Box::new(val); -//! ``` -//! -//! Move a value from a [`Box`] back to the stack by [dereferencing]: -//! -//! ``` -//! let boxed: Box =3D Box::new(5); -//! let val: u8 =3D *boxed; -//! ``` -//! -//! Creating a recursive data structure: -//! -//! ``` -//! #[derive(Debug)] -//! enum List { -//! Cons(T, Box>), -//! Nil, -//! } -//! -//! let list: List =3D 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 allo= cate -//! for a `Cons`. By introducing a [`Box`], which has a defined size, w= e 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. More preci= sely, -//! 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 still has to be [valid] for r= eads -//! and writes and sufficiently aligned. In particular, casting any aligned -//! non-zero integer literal to a raw pointer produces a valid pointer, bu= t a -//! pointer pointing into previously allocated memory that since got freed= is -//! not valid. The recommended way to build a Box to a ZST if `Box::new` c= annot -//! be used is to use [`ptr::NonNull::dangling`]. -//! -//! 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<= Foo>` -//! 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 poin= ter, -//! this does not mean that you can convert an arbitrary `T*` into a `Box<= T>` -//! and expect things to work. `Box` values will always be fully aligne= d, -//! 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, pos= sibly -//! 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]. -//! -//! -//! [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 =3D "rust1", since =3D "1.0.0")] - -use core::any::Any; -use core::async_iter::AsyncIterator; -use core::borrow; -use core::cmp::Ordering; -use core::error::Error; -use core::fmt; -use core::future::Future; -use core::hash::{Hash, Hasher}; -use core::iter::FusedIterator; -use core::marker::Tuple; -use core::marker::Unsize; -use core::mem::{self, SizedTypeProperties}; -use core::ops::{ - CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DispatchFro= mDyn, Receiver, -}; -use core::pin::Pin; -use core::ptr::{self, NonNull, Unique}; -use core::task::{Context, Poll}; - -#[cfg(not(no_global_oom_handling))] -use crate::alloc::{handle_alloc_error, WriteCloneIntoRaw}; -use crate::alloc::{AllocError, Allocator, Global, Layout}; -#[cfg(not(no_global_oom_handling))] -use crate::borrow::Cow; -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_thin))] -#[unstable(feature =3D "thin_box", issue =3D "92791")] -pub use thin::ThinBox; - -#[cfg(not(no_thin))] -mod thin; - -/// A pointer type that uniquely owns a heap allocation of type `T`. -/// -/// See the [module-level documentation](../../std/boxed/index.html) for m= ore. -#[lang =3D "owned_box"] -#[fundamental] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -// The declaration of the `Box` struct must be kept in sync with the -// `alloc::alloc::box_free` function or ICEs will happen. See the comment -// on `box_free` for more details. -pub struct Box< - T: ?Sized, - #[unstable(feature =3D "allocator_api", issue =3D "32838")] A: Allocat= or =3D 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 =3D Box::new(5); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline(always)] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - #[must_use] - #[rustc_diagnostic_item =3D "box_new"] - pub fn new(x: T) -> Self { - #[rustc_box] - Box::new(x) - } - - /// Constructs a new box with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// - /// let mut five =3D Box::::new_uninit(); - /// - /// let five =3D unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; - /// - /// assert_eq!(*five, 5) - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[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 in= correct usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// - /// let zero =3D Box::::new_zeroed(); - /// let zero =3D unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[cfg(not(no_global_oom_handling))] - #[inline] - #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[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 step= s: `Box::pin(x)` - /// does the same as [Box::into_pin]\([Box::new]\(x)). Co= nsider 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 =3D "pin", since =3D "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 =3D Box::try_new(5)?; - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature =3D "allocator_api", issue =3D "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, new_uninit)] - /// - /// let mut five =3D Box::::try_new_uninit()?; - /// - /// let five =3D unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; - /// - /// assert_eq!(*five, 5); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - // #[unstable(feature =3D "new_uninit", issue =3D "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 in= correct usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// let zero =3D Box::::try_new_zeroed()?; - /// let zero =3D unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - // #[unstable(feature =3D "new_uninit", issue =3D "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 =3D Box::new_in(5, System); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - #[must_use] - #[inline] - pub fn new_in(x: T, alloc: A) -> Self - where - A: Allocator, - { - let mut boxed =3D 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 =3D Box::try_new_in(5, System)?; - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - #[inline] - pub fn try_new_in(x: T, alloc: A) -> Result - where - A: Allocator, - { - let mut boxed =3D 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 a= llocator. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// use std::alloc::System; - /// - /// let mut five =3D Box::::new_uninit_in(System); - /// - /// let five =3D unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; - /// - /// assert_eq!(*five, 5) - /// ``` - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - #[cfg(not(no_global_oom_handling))] - #[must_use] - // #[unstable(feature =3D "new_uninit", issue =3D "63291")] - pub fn new_uninit_in(alloc: A) -> Box, A> - where - A: Allocator, - { - let layout =3D 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) =3D> m, - Err(_) =3D> handle_alloc_error(layout), - } - } - - /// Constructs a new box with uninitialized contents in the provided a= llocator, - /// returning an error if the allocation fails - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// use std::alloc::System; - /// - /// let mut five =3D Box::::try_new_uninit_in(System)?; - /// - /// let five =3D unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; - /// - /// assert_eq!(*five, 5); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - // #[unstable(feature =3D "new_uninit", issue =3D "63291")] - pub fn try_new_uninit_in(alloc: A) -> Result, = A>, AllocError> - where - A: Allocator, - { - let ptr =3D if T::IS_ZST { - NonNull::dangling() - } else { - let layout =3D 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 in= correct usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// use std::alloc::System; - /// - /// let zero =3D Box::::new_zeroed_in(System); - /// let zero =3D unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - #[cfg(not(no_global_oom_handling))] - // #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[must_use] - pub fn new_zeroed_in(alloc: A) -> Box, A> - where - A: Allocator, - { - let layout =3D 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) =3D> m, - Err(_) =3D> 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 in= correct usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// use std::alloc::System; - /// - /// let zero =3D Box::::try_new_zeroed_in(System)?; - /// let zero =3D unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - // #[unstable(feature =3D "new_uninit", issue =3D "63291")] - pub fn try_new_zeroed_in(alloc: A) -> Result, = A>, AllocError> - where - A: Allocator, - { - let ptr =3D if T::IS_ZST { - NonNull::dangling() - } else { - let layout =3D 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 [`Unp= in`], then - /// `x` will be pinned in memory and unable to be moved. - /// - /// Constructing and pinning of the `Box` can also be done in two step= s: `Box::pin_in(x, alloc)` - /// does the same as [Box::into_pin]\([Box::new_in]\(x, alloc))<= /code>. 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 =3D "allocator_api", issue =3D "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 =3D "box_into_boxed_slice", issue =3D "71582")] - pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { - let (raw, alloc) =3D 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 =3D Box::new(5); - /// - /// assert_eq!(Box::into_inner(c), 5); - /// ``` - #[unstable(feature =3D "box_into_inner", issue =3D "80437")] - #[inline] - pub fn into_inner(boxed: Self) -> T { - *boxed - } -} - -impl Box<[T]> { - /// Constructs a new boxed slice with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// - /// let mut values =3D Box::<[u32]>::new_uninit_slice(3); - /// - /// let values =3D 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 =3D "new_uninit", issue =3D "63291")] - #[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 in= correct usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// - /// let values =3D Box::<[u32]>::new_zeroed_slice(3); - /// let values =3D unsafe { values.assume_init() }; - /// - /// assert_eq!(*values, [0, 0, 0]) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[cfg(not(no_global_oom_handling))] - #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[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, new_uninit)] - /// - /// let mut values =3D Box::<[u32]>::try_new_uninit_slice(3)?; - /// let values =3D 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 =3D "allocator_api", issue =3D "32838")] - #[inline] - pub fn try_new_uninit_slice(len: usize) -> Result]>, AllocError> { - let ptr =3D if T::IS_ZST || len =3D=3D 0 { - NonNull::dangling() - } else { - let layout =3D match Layout::array::>(len)= { - Ok(l) =3D> l, - Err(_) =3D> return Err(AllocError), - }; - Global.allocate(layout)?.cast() - }; - unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).i= nto_box(len)) } - } - - /// Constructs a new boxed slice with uninitialized contents, with the= memory - /// being filled with `0` bytes. Returns an error if the allocation fa= ils - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and in= correct usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// let values =3D Box::<[u32]>::try_new_zeroed_slice(3)?; - /// let values =3D unsafe { values.assume_init() }; - /// - /// assert_eq!(*values, [0, 0, 0]); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - #[inline] - pub fn try_new_zeroed_slice(len: usize) -> Result]>, AllocError> { - let ptr =3D if T::IS_ZST || len =3D=3D 0 { - NonNull::dangling() - } else { - let layout =3D match Layout::array::>(len)= { - Ok(l) =3D> l, - Err(_) =3D> return Err(AllocError), - }; - Global.allocate_zeroed(layout)?.cast() - }; - unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).i= nto_box(len)) } - } -} - -impl Box<[T], A> { - /// Constructs a new boxed slice with uninitialized contents in the pr= ovided allocator. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// use std::alloc::System; - /// - /// let mut values =3D Box::<[u32], _>::new_uninit_slice_in(3, System); - /// - /// let values =3D 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 =3D "allocator_api", issue =3D "32838")] - // #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[must_use] - pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUni= nit], A> { - unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } - } - - /// Constructs a new boxed slice with uninitialized contents in the pr= ovided allocator, - /// with the memory being filled with `0` bytes. - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and in= correct usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// - /// use std::alloc::System; - /// - /// let values =3D Box::<[u32], _>::new_zeroed_slice_in(3, System); - /// let values =3D unsafe { values.assume_init() }; - /// - /// assert_eq!(*values, [0, 0, 0]) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[cfg(not(no_global_oom_handling))] - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - // #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[must_use] - pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUni= nit], A> { - unsafe { RawVec::with_capacity_zeroed_in(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 - /// - /// ``` - /// #![feature(new_uninit)] - /// - /// let mut five =3D Box::::new_uninit(); - /// - /// let five: Box =3D unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; - /// - /// assert_eq!(*five, 5) - /// ``` - #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[inline] - pub unsafe fn assume_init(self) -> Box { - let (raw, alloc) =3D 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 becau= se - /// the compiler may be able to optimize copying from stack. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// - /// let big_box =3D Box::<[usize; 1024]>::new_uninit(); - /// - /// let mut array =3D [0; 1024]; - /// for (i, place) in array.iter_mut().enumerate() { - /// *place =3D i; - /// } - /// - /// // The optimizer may be able to elide this copy, so previous code = writes - /// // to heap directly. - /// let big_box =3D Box::write(big_box, array); - /// - /// for (i, x) in big_box.iter().enumerate() { - /// assert_eq!(*x, i); - /// } - /// ``` - #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[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 - /// - /// ``` - /// #![feature(new_uninit)] - /// - /// let mut values =3D Box::<[u32]>::new_uninit_slice(3); - /// - /// let values =3D 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]) - /// ``` - #[unstable(feature =3D "new_uninit", issue =3D "63291")] - #[inline] - pub unsafe fn assume_init(self) -> Box<[T], A> { - let (raw, alloc) =3D 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 =3D Box::new(5); - /// let ptr =3D Box::into_raw(x); - /// let x =3D unsafe { Box::from_raw(ptr) }; - /// ``` - /// Manually create a `Box` from scratch by using the global allocator: - /// ``` - /// use std::alloc::{alloc, Layout}; - /// - /// unsafe { - /// let ptr =3D alloc(Layout::new::()) as *mut i32; - /// // In general .write is required to avoid attempting to destru= ct - /// // the (uninitialized) previous contents of `ptr`, though for = this - /// // simple example `*ptr =3D 5` would have worked as well. - /// ptr.write(5); - /// let x =3D Box::from_raw(ptr); - /// } - /// ``` - /// - /// [memory layout]: self#memory-layout - /// [`Layout`]: crate::Layout - #[stable(feature =3D "box_raw", since =3D "1.4.0")] - #[inline] - #[must_use =3D "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) } - } -} - -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 =3D Box::new_in(5, System); - /// let (ptr, alloc) =3D Box::into_raw_with_allocator(x); - /// let x =3D 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 =3D System.allocate(Layout::new::())?.as_mut_ptr(= ) as *mut i32; - /// // In general .write is required to avoid attempting to destru= ct - /// // the (uninitialized) previous contents of `ptr`, though for = this - /// // simple example `*ptr =3D 5` would have worked as well. - /// ptr.write(5); - /// let x =3D Box::from_raw_in(ptr, System); - /// } - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [memory layout]: self#memory-layout - /// [`Layout`]: crate::Layout - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - #[rustc_const_unstable(feature =3D "const_box", issue =3D "92521")] - #[inline] - pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { - Box(unsafe { Unique::new_unchecked(raw) }, 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 perfo= rm - /// 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 =3D Box::new(String::from("Hello")); - /// let ptr =3D Box::into_raw(x); - /// let x =3D unsafe { Box::from_raw(ptr) }; - /// ``` - /// Manual cleanup by explicitly running the destructor and deallocati= ng - /// the memory: - /// ``` - /// use std::alloc::{dealloc, Layout}; - /// use std::ptr; - /// - /// let x =3D Box::new(String::from("Hello")); - /// let ptr =3D 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 =3D Box::new(String::from("Hello")); - /// let ptr =3D Box::into_raw(x); - /// unsafe { - /// drop(Box::from_raw(ptr)); - /// } - /// ``` - /// - /// [memory layout]: self#memory-layout - #[stable(feature =3D "box_raw", since =3D "1.4.0")] - #[inline] - pub fn into_raw(b: Self) -> *mut T { - Self::into_raw_with_allocator(b).0 - } - - /// Consumes the `Box`, returning a wrapped raw pointer and the alloca= tor. - /// - /// 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 pe= rform - /// 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 =3D Box::new_in(String::from("Hello"), System); - /// let (ptr, alloc) =3D Box::into_raw_with_allocator(x); - /// let x =3D unsafe { Box::from_raw_in(ptr, alloc) }; - /// ``` - /// Manual cleanup by explicitly running the destructor and deallocati= ng - /// the memory: - /// ``` - /// #![feature(allocator_api)] - /// - /// use std::alloc::{Allocator, Layout, System}; - /// use std::ptr::{self, NonNull}; - /// - /// let x =3D Box::new_in(String::from("Hello"), System); - /// let (ptr, alloc) =3D Box::into_raw_with_allocator(x); - /// unsafe { - /// ptr::drop_in_place(ptr); - /// let non_null =3D NonNull::new_unchecked(ptr); - /// alloc.deallocate(non_null.cast(), Layout::new::()); - /// } - /// ``` - /// - /// [memory layout]: self#memory-layout - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - #[inline] - pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { - let (leaked, alloc) =3D Box::into_unique(b); - (leaked.as_ptr(), alloc) - } - - #[unstable( - feature =3D "ptr_internals", - issue =3D "none", - reason =3D "use `Box::leak(b).into()` or `Unique::from(Box::leak(b= ))` instead" - )] - #[inline] - #[doc(hidden)] - pub fn into_unique(b: Self) -> (Unique, A) { - // Box is recognized as a "unique pointer" by Stacked Borrows, but= internally it is a - // raw pointer for the type system. Turning it directly into a raw= pointer would not be - // recognized as "releasing" the unique pointer to permit aliased = raw accesses, - // so all raw pointer methods have to go through `Box::leak`. Turn= ing *that* to a raw pointer - // behaves correctly. - let alloc =3D unsafe { ptr::read(&b.1) }; - (Unique::from(Box::leak(b)), alloc) - } - - /// 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 =3D "allocator_api", issue =3D "32838")] - #[rustc_const_unstable(feature =3D "const_box", issue =3D "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 lifeti= me - /// `'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 remaind= er of - /// the program's life. Dropping the returned reference will cause a m= emory - /// leak. If this is not acceptable, the reference should first be wra= pped - /// 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 =3D Box::new(41); - /// let static_ref: &'static mut usize =3D Box::leak(x); - /// *static_ref +=3D 1; - /// assert_eq!(*static_ref, 42); - /// ``` - /// - /// Unsized data: - /// - /// ``` - /// let x =3D vec![1, 2, 3].into_boxed_slice(); - /// let static_ref =3D Box::leak(x); - /// static_ref[0] =3D 4; - /// assert_eq!(*static_ref, [4, 2, 3]); - /// ``` - #[stable(feature =3D "box_leak", since =3D "1.26.0")] - #[inline] - pub fn leak<'a>(b: Self) -> &'a mut T - where - A: 'a, - { - unsafe { &mut *mem::ManuallyDrop::new(b).0.as_ptr() } - } - - /// Converts a `Box` into a `Pin>`. If `T` does not implemen= t [`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::ne= w]\(x)) - /// can also be written more concisely using [Box::pin]\(x). - /// This `into_pin` method is useful if you already have a `Box`, o= r 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> fo= r 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 =3D Box::new(()); - /// let bar =3D Pin::from(foo); - /// ``` - #[stable(feature =3D "box_into_pin", since =3D "1.63.0")] - #[rustc_const_unstable(feature =3D "const_box", issue =3D "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 =3D "rust1", since =3D "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 destruct= or is run - - let ptr =3D self.0; - - unsafe { - let layout =3D Layout::for_value_raw(ptr.as_ptr()); - if layout.size() !=3D 0 { - self.1.deallocate(From::from(ptr.cast()), layout); - } - } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Default for Box { - /// Creates a `Box`, with the `Default` value for T. - #[inline] - fn default() -> Self { - Box::new(T::default()) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Default for Box<[T]> { - #[inline] - fn default() -> Self { - let ptr: Unique<[T]> =3D Unique::<[T; 0]>::dangling(); - Box(ptr, Global) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "default_box_extra", since =3D "1.17.0")] -impl Default for Box { - #[inline] - fn default() -> Self { - // SAFETY: This is the same as `Unique::cast` but with an unsiz= ed `U =3D str`. - let ptr: Unique =3D unsafe { - let bytes: Unique<[u8]> =3D Unique::<[u8; 0]>::dangling(); - Unique::new_unchecked(bytes.as_ptr() as *mut str) - }; - Box(ptr, Global) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Clone for Box { - /// Returns a new box with a `clone()` of this box's contents. - /// - /// # Examples - /// - /// ``` - /// let x =3D Box::new(5); - /// let y =3D 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 =3D Self::new_uninit_in(self.1.clone()); - unsafe { - (**self).write_clone_into_raw(boxed.as_mut_ptr()); - boxed.assume_init() - } - } - - /// Copies `source`'s contents into `self` without creating a new allo= cation. - /// - /// # Examples - /// - /// ``` - /// let x =3D Box::new(5); - /// let mut y =3D Box::new(10); - /// let yp: *const i32 =3D &*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 =3D "box_slice_clone", since =3D "1.3.0")] -impl Clone for Box { - fn clone(&self) -> Self { - // this makes a copy of the data - let buf: Box<[u8]> =3D self.as_bytes().into(); - unsafe { from_boxed_utf8_unchecked(buf) } - } -} - -#[stable(feature =3D "rust1", since =3D "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 =3D "rust1", since =3D "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 =3D "rust1", since =3D "1.0.0")] -impl Ord for Box { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - Ord::cmp(&**self, &**other) - } -} -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Eq for Box {} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Hash for Box { - fn hash(&self, state: &mut H) { - (**self).hash(state); - } -} - -#[stable(feature =3D "indirect_hasher_impl", since =3D "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) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "from_for_ptrs", since =3D "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 =3D 5; - /// let boxed =3D Box::new(5); - /// - /// assert_eq!(Box::from(x), boxed); - /// ``` - fn from(t: T) -> Self { - Box::new(t) - } -} - -#[stable(feature =3D "pin", since =3D "1.33.0")] -impl From> for Pin> -where - A: 'static, -{ - /// Converts a `Box` into a `Pin>`. If `T` does not implemen= t [`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 =3D slice.len(); - let buf =3D 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 =3D "box_from_slice", since =3D "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] =3D &[104, 101, 108, 108, 111]; - /// let boxed_slice: Box<[u8]> =3D Box::from(slice); - /// - /// println!("{boxed_slice:?}"); - /// ``` - #[inline] - fn from(slice: &[T]) -> Box<[T]> { - >::from_slice(slice) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "box_from_cow", since =3D "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) =3D> Box::from(slice), - Cow::Owned(slice) =3D> Box::from(slice), - } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "box_from_slice", since =3D "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 =3D 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 =3D "box_from_cow", since =3D "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 =3D Cow::Borrowed("hello"); - /// let boxed: Box =3D Box::from(unboxed); - /// println!("{boxed}"); - /// ``` - /// - /// ```rust - /// # use std::borrow::Cow; - /// let unboxed =3D Cow::Owned("hello".to_string()); - /// let boxed: Box =3D Box::from(unboxed); - /// println!("{boxed}"); - /// ``` - #[inline] - fn from(cow: Cow<'_, str>) -> Box { - match cow { - Cow::Borrowed(s) =3D> Box::from(s), - Cow::Owned(s) =3D> Box::from(s), - } - } -} - -#[stable(feature =3D "boxed_str_conv", since =3D "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 =3D Box::from("hello"); - /// let boxed_str: Box<[u8]> =3D Box::from(boxed); - /// - /// // create a &[u8] which will be used to create a Box<[u8]> - /// let slice: &[u8] =3D &[104, 101, 108, 108, 111]; - /// let boxed_slice =3D Box::from(slice); - /// - /// assert_eq!(boxed_slice, boxed_str); - /// ``` - #[inline] - fn from(s: Box) -> Self { - let (raw, alloc) =3D Box::into_raw_with_allocator(s); - unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "box_from_array", since =3D "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]> =3D 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) =3D 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 =3D "boxed_slice_try_from", since =3D "1.43.0")] -impl TryFrom> for Box<[T; N]> { - type Error =3D 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() =3D=3D N { - Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) - } else { - Err(boxed_slice) - } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "boxed_array_try_from_vec", since =3D "1.66.0")] -impl TryFrom> for Box<[T; N]> { - type Error =3D Vec; - - /// Attempts to convert a `Vec` into a `Box<[T; N]>`. - /// - /// Like [`Vec::into_boxed_slice`], this is in-place if `vec.capacity(= ) =3D=3D 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]> =3D vec![1.0; 100].try_into().unwrap(); - /// assert_eq!(state.len(), 100); - /// ``` - fn try_from(vec: Vec) -> Result { - if vec.len() =3D=3D N { - let boxed_slice =3D vec.into_boxed_slice(); - Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) - } else { - Err(vec) - } - } -} - -impl Box { - /// Attempt to downcast the box to a concrete type. - /// - /// # Examples - /// - /// ``` - /// use std::any::Any; - /// - /// fn print_if_string(value: Box) { - /// if let Ok(string) =3D value.downcast::() { - /// println!("String ({}): {}", string.len(), string); - /// } - /// } - /// - /// let my_string =3D "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// ``` - #[inline] - #[stable(feature =3D "rust1", since =3D "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 =3D 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 =3D "downcast_unchecked", issue =3D "90850")] - pub unsafe fn downcast_unchecked(self) -> Box { - debug_assert!(self.is::()); - unsafe { - let (raw, alloc): (*mut dyn Any, _) =3D Box::into_raw_with_all= ocator(self); - Box::from_raw_in(raw as *mut T, alloc) - } - } -} - -impl Box { - /// Attempt to downcast the box to a concrete type. - /// - /// # Examples - /// - /// ``` - /// use std::any::Any; - /// - /// fn print_if_string(value: Box) { - /// if let Ok(string) =3D value.downcast::() { - /// println!("String ({}): {}", string.len(), string); - /// } - /// } - /// - /// let my_string =3D "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// ``` - #[inline] - #[stable(feature =3D "rust1", since =3D "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 =3D 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 =3D "downcast_unchecked", issue =3D "90850")] - pub unsafe fn downcast_unchecked(self) -> Box { - debug_assert!(self.is::()); - unsafe { - let (raw, alloc): (*mut (dyn Any + Send), _) =3D Box::into_raw= _with_allocator(self); - Box::from_raw_in(raw as *mut T, alloc) - } - } -} - -impl Box { - /// Attempt to downcast the box to a concrete type. - /// - /// # Examples - /// - /// ``` - /// use std::any::Any; - /// - /// fn print_if_string(value: Box) { - /// if let Ok(string) =3D value.downcast::() { - /// println!("String ({}): {}", string.len(), string); - /// } - /// } - /// - /// let my_string =3D "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// ``` - #[inline] - #[stable(feature =3D "box_send_sync_any_downcast", since =3D "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 =3D 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 =3D "downcast_unchecked", issue =3D "90850")] - pub unsafe fn downcast_unchecked(self) -> Box { - debug_assert!(self.is::()); - unsafe { - let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =3D - Box::into_raw_with_allocator(self); - Box::from_raw_in(raw as *mut T, alloc) - } - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl fmt::Display for Box { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl fmt::Debug for Box { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[stable(feature =3D "rust1", since =3D "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 B= ox, - // instead we cast it to a *const which aliases the Unique - let ptr: *const T =3D &**self; - fmt::Pointer::fmt(&ptr, f) - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Deref for Box { - type Target =3D T; - - fn deref(&self) -> &T { - &**self - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl DerefMut for Box { - fn deref_mut(&mut self) -> &mut T { - &mut **self - } -} - -#[unstable(feature =3D "receiver_trait", issue =3D "none")] -impl Receiver for Box {} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Iterator for Box { - type Item =3D 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 =3D 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 =3D "rust1", since =3D "1.0.0")] -impl BoxIter for Box { - fn last(self) -> Option { - (*self).last() - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl DoubleEndedIterator fo= r Box { - fn next_back(&mut self) -> Option { - (**self).next_back() - } - fn nth_back(&mut self, n: usize) -> Option { - (**self).nth_back(n) - } -} -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl ExactSizeIterator for Bo= x { - fn len(&self) -> usize { - (**self).len() - } - fn is_empty(&self) -> bool { - (**self).is_empty() - } -} - -#[stable(feature =3D "fused", since =3D "1.26.0")] -impl FusedIterator for Box = {} - -#[stable(feature =3D "boxed_closure_impls", since =3D "1.35.0")] -impl + ?Sized, A: Allocator> FnOnce for= Box { - type Output =3D >::Output; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output { - >::call_once(*self, args) - } -} - -#[stable(feature =3D "boxed_closure_impls", since =3D "1.35.0")] -impl + ?Sized, A: Allocator> FnMut for B= ox { - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { - >::call_mut(self, args) - } -} - -#[stable(feature =3D "boxed_closure_impls", since =3D "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 =3D "coerce_unsized", issue =3D "18598")] -impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} - -#[unstable(feature =3D "dispatch_from_dyn", issue =3D "none")] -impl, U: ?Sized> DispatchFromDyn> for Box {} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "boxed_slice_from_iter", since =3D "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 =3D "box_slice_clone", since =3D "1.3.0")] -impl Clone for Box<[T], A> { - fn clone(&self) -> Self { - let alloc =3D Box::allocator(self).clone(); - self.to_vec_in(alloc).into_boxed_slice() - } - - fn clone_from(&mut self, other: &Self) { - if self.len() =3D=3D other.len() { - self.clone_from_slice(&other); - } else { - *self =3D other.clone(); - } - } -} - -#[stable(feature =3D "box_borrow", since =3D "1.1.0")] -impl borrow::Borrow for Box { - fn borrow(&self) -> &T { - &**self - } -} - -#[stable(feature =3D "box_borrow", since =3D "1.1.0")] -impl borrow::BorrowMut for Box { - fn borrow_mut(&mut self) -> &mut T { - &mut **self - } -} - -#[stable(since =3D "1.5.0", feature =3D "smart_ptr_as_ref")] -impl AsRef for Box { - fn as_ref(&self) -> &T { - &**self - } -} - -#[stable(since =3D "1.5.0", feature =3D "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 =3D "pin", since =3D "1.33.0")] -impl Unpin for Box where A: 'static {} - -#[unstable(feature =3D "coroutine_trait", issue =3D "43122")] -impl + Unpin, R, A: Allocator> Coroutine for B= ox -where - A: 'static, -{ - type Yield =3D G::Yield; - type Return =3D G::Return; - - fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { - G::resume(Pin::new(&mut *self), arg) - } -} - -#[unstable(feature =3D "coroutine_trait", issue =3D "43122")] -impl, R, A: Allocator> Coroutine for Pin> -where - A: 'static, -{ - type Yield =3D G::Yield; - type Return =3D G::Return; - - fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { - G::resume((*self).as_mut(), arg) - } -} - -#[stable(feature =3D "futures_api", since =3D "1.36.0")] -impl Future for Box -where - A: 'static, -{ - type Output =3D F::Output; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - F::poll(Pin::new(&mut *self), cx) - } -} - -#[unstable(feature =3D "async_iterator", issue =3D "79024")] -impl AsyncIterator for Box { - type Item =3D 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() - } -} - -impl dyn Error { - #[inline] - #[stable(feature =3D "error_downcast", since =3D "1.3.0")] - #[rustc_allow_incoherent_impl] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result,= Box> { - if self.is::() { - unsafe { - let raw: *mut dyn Error =3D Box::into_raw(self); - Ok(Box::from_raw(raw as *mut T)) - } - } else { - Err(self) - } - } -} - -impl dyn Error + Send { - #[inline] - #[stable(feature =3D "error_downcast", since =3D "1.3.0")] - #[rustc_allow_incoherent_impl] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result,= Box> { - let err: Box =3D self; - ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send` marker. - Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send)) - }) - } -} - -impl dyn Error + Send + Sync { - #[inline] - #[stable(feature =3D "error_downcast", since =3D "1.3.0")] - #[rustc_allow_incoherent_impl] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result,= Box> { - let err: Box =3D self; - ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send + Sync` marker. - Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send + Syn= c)) - }) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "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 =3D AnError; - /// assert!(0 =3D=3D mem::size_of_val(&an_error)); - /// let a_boxed_error =3D Box::::from(an_error); - /// assert!(mem::size_of::>() =3D=3D mem::size_of_val(&= a_boxed_error)) - /// ``` - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "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 =3D AnError; - /// assert!(0 =3D=3D mem::size_of_val(&an_error)); - /// let a_boxed_error =3D Box::::from(an_erro= r); - /// assert!( - /// mem::size_of::>() =3D=3D mem::siz= e_of_val(&a_boxed_error)) - /// ``` - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl From for Box { - /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`S= ync`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_string_error =3D "a string error".to_string(); - /// let a_boxed_error =3D Box::::from(a_strin= g_error); - /// assert!( - /// mem::size_of::>() =3D=3D mem::siz= e_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 =3D "string_box_error", since =3D "1.6.0")] -impl From for Box { - /// Converts a [`String`] into a box of dyn [`Error`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_string_error =3D "a string error".to_string(); - /// let a_boxed_error =3D Box::::from(a_string_error); - /// assert!(mem::size_of::>() =3D=3D mem::size_of_val(&= a_boxed_error)) - /// ``` - fn from(str_err: String) -> Box { - let err1: Box =3D From::from(str_err); - let err2: Box =3D err1; - err2 - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "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 =3D "a str error"; - /// let a_boxed_error =3D Box::::from(a_str_e= rror); - /// assert!( - /// mem::size_of::>() =3D=3D mem::siz= e_of_val(&a_boxed_error)) - /// ``` - #[inline] - fn from(err: &str) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "string_box_error", since =3D "1.6.0")] -impl 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 =3D "a str error"; - /// let a_boxed_error =3D Box::::from(a_str_error); - /// assert!(mem::size_of::>() =3D=3D 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 =3D "cow_box_error", since =3D "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 =3D Cow::from("a str error"); - /// let a_boxed_error =3D Box::::from(a_cow_s= tr_error); - /// assert!( - /// mem::size_of::>() =3D=3D mem::siz= e_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 =3D "cow_box_error", since =3D "1.22.0")] -impl<'a> 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 =3D Cow::from("a str error"); - /// let a_boxed_error =3D Box::::from(a_cow_str_error); - /// assert!(mem::size_of::>() =3D=3D mem::size_of_val(&= a_boxed_error)) - /// ``` - fn from(err: Cow<'a, str>) -> Box { - From::from(String::from(err)) - } -} - -#[stable(feature =3D "box_error", since =3D "1.8.0")] -impl core::error::Error for Box { - #[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<'b>(&'b self, request: &mut core::error::Request<'b>) { - core::error::Error::provide(&**self, request); - } -} diff --git a/rust/alloc/collections/mod.rs b/rust/alloc/collections/mod.rs deleted file mode 100644 index 00ffb3b97365..000000000000 --- a/rust/alloc/collections/mod.rs +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -//! Collection types. - -#![stable(feature =3D "rust1", since =3D "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 =3D "rust1", since =3D "1.0.0")] -pub mod btree_map { - //! An ordered map based on a B-Tree. - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub use super::btree::map::*; -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -pub mod btree_set { - //! An ordered set based on a B-Tree. - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub use super::btree::set::*; -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[doc(no_inline)] -pub use binary_heap::BinaryHeap; - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[doc(no_inline)] -pub use btree_map::BTreeMap; - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[doc(no_inline)] -pub use btree_set::BTreeSet; - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[doc(no_inline)] -pub use linked_list::LinkedList; - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[doc(no_inline)] -pub use vec_deque::VecDeque; - -use crate::alloc::{Layout, LayoutError}; -use core::fmt::Display; - -/// The error type for `try_reserve` methods. -#[derive(Clone, PartialEq, Eq, Debug)] -#[stable(feature =3D "try_reserve", since =3D "1.57.0")] -pub struct TryReserveError { - kind: TryReserveErrorKind, -} - -impl TryReserveError { - /// Details about the allocation that caused the error - #[inline] - #[must_use] - #[unstable( - feature =3D "try_reserve_kind", - reason =3D "Uncertain how much info should be exposed", - issue =3D "48043" - )] - pub fn kind(&self) -> TryReserveErrorKind { - self.kind.clone() - } -} - -/// Details of the allocation that caused a `TryReserveError` -#[derive(Clone, PartialEq, Eq, Debug)] -#[unstable( - feature =3D "try_reserve_kind", - reason =3D "Uncertain how much info should be exposed", - issue =3D "48043" -)] -pub enum TryReserveErrorKind { - /// Error due to the computed capacity exceeding the collection's maxi= mum - /// (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 =3D "container_error_extra", - issue =3D "none", - reason =3D "\ - Enable exposing the allocator=E2=80=99s 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 =3D "try_reserve_kind", - reason =3D "Uncertain how much info should be exposed", - issue =3D "48043" -)] -impl From for TryReserveError { - #[inline] - fn from(kind: TryReserveErrorKind) -> Self { - Self { kind } - } -} - -#[unstable(feature =3D "try_reserve_kind", reason =3D "new API", issue =3D= "48043")] -impl From for TryReserveErrorKind { - /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`]. - #[inline] - fn from(_: LayoutError) -> Self { - TryReserveErrorKind::CapacityOverflow - } -} - -#[stable(feature =3D "try_reserve", since =3D "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 =3D match self.kind { - TryReserveErrorKind::CapacityOverflow =3D> { - " because the computed capacity exceeded the collection's = maximum" - } - TryReserveErrorKind::AllocError { .. } =3D> { - " 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 =3D "try_reserve", since =3D "1.57.0")] -impl core::error::Error for TryReserveError {} diff --git a/rust/alloc/lib.rs b/rust/alloc/lib.rs deleted file mode 100644 index 36f79c075593..000000000000 --- a/rust/alloc/lib.rs +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -//! # 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=E2=80=99t need to be used dire= ctly -//! since its contents are re-exported in the [`std` crate](../std/index.h= tml). -//! Crates that use the `#![no_std]` attribute however will typically -//! not depend on `std`, so they=E2=80=99d 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 o= n 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 int= ended -//! 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 it= self -//! 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 mutati= on 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 - -// To run alloc tests without x.py without ending up with two copies of al= loc, Miri needs to be -// able to "empty" this crate. See . -// rustc itself never sets the feature, so this line has no effect there. -#![cfg(any(not(feature =3D "miri-test-libstd"), test, doctest))] -// -#![allow(unused_attributes)] -#![stable(feature =3D "alloc", since =3D "1.36.0")] -#![doc( - html_playground_url =3D "https://play.rust-lang.org/", - issue_tracker_base_url =3D "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)), - any(not(feature =3D "miri-test-libstd"), test, doctest), - no_global_oom_handling, - not(no_global_oom_handling), - not(no_rc), - not(no_sync), - target_has_atomic =3D "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)] -// -// 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(allocator_api)] -#![feature(array_chunks)] -#![feature(array_into_iter_constructors)] -#![feature(array_methods)] -#![feature(array_windows)] -#![feature(ascii_char)] -#![feature(assert_matches)] -#![feature(async_iterator)] -#![feature(coerce_unsized)] -#![feature(const_align_of_val)] -#![feature(const_box)] -#![cfg_attr(not(no_borrow), feature(const_cow_is_borrowed))] -#![feature(const_eval_select)] -#![feature(const_maybe_uninit_as_mut_ptr)] -#![feature(const_maybe_uninit_write)] -#![feature(const_pin)] -#![feature(const_refs_to_cell)] -#![feature(const_size_of_val)] -#![feature(const_waker)] -#![feature(core_intrinsics)] -#![feature(core_panic)] -#![feature(deprecated_suggestion)] -#![feature(dispatch_from_dyn)] -#![feature(error_generic_member_access)] -#![feature(error_in_core)] -#![feature(exact_size_is_empty)] -#![feature(extend_one)] -#![feature(fmt_internals)] -#![feature(fn_traits)] -#![feature(hasher_prefixfree_extras)] -#![feature(inline_const)] -#![feature(inplace_iteration)] -#![feature(iter_advance_by)] -#![feature(iter_next_chunk)] -#![feature(iter_repeat_n)] -#![feature(layout_for_ptr)] -#![feature(maybe_uninit_slice)] -#![feature(maybe_uninit_uninit_array)] -#![feature(maybe_uninit_uninit_array_transpose)] -#![feature(pattern)] -#![feature(ptr_internals)] -#![feature(ptr_metadata)] -#![feature(ptr_sub_ptr)] -#![feature(receiver_trait)] -#![feature(set_ptr_value)] -#![feature(sized_type_properties)] -#![feature(slice_from_ptr_range)] -#![feature(slice_group_by)] -#![feature(slice_ptr_get)] -#![feature(slice_ptr_len)] -#![feature(slice_range)] -#![feature(std_internals)] -#![feature(str_internals)] -#![feature(strict_provenance)] -#![feature(trusted_fused)] -#![feature(trusted_len)] -#![feature(trusted_random_access)] -#![feature(try_trait_v2)] -#![feature(tuple_trait)] -#![feature(unchecked_math)] -#![feature(unicode_internals)] -#![feature(unsize)] -#![feature(utf8_chunks)] -// 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(associated_type_bounds)] -#![feature(c_unwind)] -#![feature(cfg_sanitize)] -#![feature(const_mut_refs)] -#![feature(const_precise_live_drops)] -#![feature(const_ptr_write)] -#![feature(const_trait_impl)] -#![feature(const_try)] -#![feature(dropck_eyepatch)] -#![feature(exclusive_range_pattern)] -#![feature(fundamental)] -#![feature(hashmap_internals)] -#![feature(lang_items)] -#![feature(min_specialization)] -#![feature(multiple_supertrait_upcastable)] -#![feature(negative_impls)] -#![feature(never_type)] -#![feature(pointer_is_aligned)] -#![feature(rustc_allow_const_fn_unstable)] -#![feature(rustc_attrs)] -#![feature(slice_internals)] -#![feature(staged_api)] -#![feature(stmt_expr_attributes)] -#![feature(unboxed_closures)] -#![feature(unsized_fn_params)] -#![feature(with_negative_coherence)] -// tidy-alphabetical-end -// -// Rustdoc features: -#![feature(doc_cfg)] -#![feature(doc_cfg_hide)] -// Technically, this is a bug in rustdoc: rustdoc sees the documentation o= n `#[lang =3D slice_alloc]` -// blocks is for `&[T]`, which also has documentation using this feature i= n `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 do= esn'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). -#[cfg(not(no_macros))] -#[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; -} -#[cfg(not(no_borrow))] -pub mod borrow; -pub mod collections; -#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))] -pub mod ffi; -#[cfg(not(no_fmt))] -pub mod fmt; -#[cfg(not(no_rc))] -pub mod rc; -pub mod slice; -#[cfg(not(no_str))] -pub mod str; -#[cfg(not(no_string))] -pub mod string; -#[cfg(all(not(no_rc), not(no_sync), target_has_atomic =3D "ptr"))] -pub mod sync; -#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync), target_ha= s_atomic =3D "ptr"))] -pub mod task; -#[cfg(test)] -mod tests; -pub mod vec; - -#[doc(hidden)] -#[unstable(feature =3D "liballoc_internals", issue =3D "none", reason =3D = "implementation detail")] -pub mod __export { - pub use core::format_args; -} - -#[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 =3D std::hash::RandomState::new().build_hasher(); - std::panic::Location::caller().hash(&mut hasher); - let hc64 =3D hasher.finish(); - let seed_vec =3D - hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); - let seed: [u8; 16] =3D seed_vec.as_slice().try_into().unwrap(); - rand::SeedableRng::from_seed(seed) - } -} diff --git a/rust/alloc/raw_vec.rs b/rust/alloc/raw_vec.rs deleted file mode 100644 index 98b6abf30af6..000000000000 --- a/rust/alloc/raw_vec.rs +++ /dev/null @@ -1,611 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -#![unstable(feature =3D "raw_vec_internals", reason =3D "unstable const wa= rnings", issue =3D "none")] - -use core::alloc::LayoutError; -use core::cmp; -use core::intrinsics; -use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; -use core::ptr::{self, NonNull, Unique}; -use core::slice; - -#[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; - -enum AllocInit { - /// The contents of the new memory are uninitialized. - Uninitialized, - /// The new memory is guaranteed to be zeroed. - #[allow(dead_code)] - Zeroed, -} - -#[repr(transparent)] -#[cfg_attr(target_pointer_width =3D "16", rustc_layout_scalar_valid_range_= end(0x7fff))] -#[cfg_attr(target_pointer_width =3D "32", rustc_layout_scalar_valid_range_= end(0x7fff_ffff))] -#[cfg_attr(target_pointer_width =3D "64", rustc_layout_scalar_valid_range_= end(0x7fff_ffff_ffff_ffff))] -struct Cap(usize); - -impl Cap { - const ZERO: Cap =3D unsafe { Cap(0) }; -} - -/// A low-level utility for more ergonomically allocating, reallocating, a= nd deallocating -/// a buffer of memory on the heap without having to worry about all the c= orner 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 "ca= pacity 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 b= enefits. -/// * Uses the excess returned from the allocator to use the largest avail= able 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 `cap= acity()` always returns -/// `usize::MAX`. This means that you need to be careful when round-trippi= ng this type with a -/// `Box<[T]>`, since `capacity()` won't yield the length. -#[allow(missing_debug_implementations)] -pub(crate) struct RawVec { - 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..=3Disize::MAX` range. - cap: Cap, - alloc: A, -} - -impl RawVec { - /// HACK(Centril): This exists because stable `const fn` can only call= stable `const fn`, so - /// they cannot call `Self::new()`. - /// - /// If you change `RawVec::new` or dependencies, please take care t= o not introduce anything - /// that would truly const-call something unstable. - pub const NEW: Self =3D Self::new(); - - /// 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. - /// - /// # 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] - pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) - } - - /// Like `with_capacity`, but guarantees the buffer is zeroed. - #[cfg(not(any(no_global_oom_handling, test)))] - #[must_use] - #[inline] - pub fn with_capacity_zeroed(capacity: usize) -> Self { - Self::with_capacity_zeroed_in(capacity, Global) - } -} - -impl RawVec { - // 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 (<=3D 1 KiB). - // - 1 otherwise, to avoid wasting too much space for very short Vecs. - pub(crate) const MIN_NON_ZERO_CAP: usize =3D if mem::size_of::() = =3D=3D 1 { - 8 - } else if mem::size_of::() <=3D 1024 { - 4 - } else { - 1 - }; - - /// Like `new`, but parameterized over the choice of allocator for - /// the returned `RawVec`. - pub const fn new_in(alloc: A) -> Self { - // `cap: 0` means "unallocated". zero-sized types are ignored. - Self { ptr: Unique::dangling(), cap: Cap::ZERO, alloc } - } - - /// Like `with_capacity`, but parameterized over the choice of - /// allocator for the returned `RawVec`. - #[cfg(not(no_global_oom_handling))] - #[inline] - pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - Self::allocate_in(capacity, AllocInit::Uninitialized, alloc) - } - - /// 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 { - Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc) - } - - /// Like `with_capacity_zeroed`, but parameterized over the choice - /// of allocator for the returned `RawVec`. - #[cfg(not(no_global_oom_handling))] - #[inline] - pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { - Self::allocate_in(capacity, AllocInit::Zeroed, alloc) - } - - /// Converts the entire buffer into `Box<[MaybeUninit]>` with the s= pecified `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 request= ed capacity, and - /// * `len` must be less than or equal to `self.capacity()`. - /// - /// Note, that the requested capacity and `self.capacity()` could diff= er, 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 chec= k the other half). - debug_assert!( - len <=3D self.capacity(), - "`len` must be smaller than or equal to `self.capacity()`" - ); - - let me =3D ManuallyDrop::new(self); - unsafe { - let slice =3D slice::from_raw_parts_mut(me.ptr() as *mut Maybe= Uninit, len); - Box::from_raw_in(slice, ptr::read(&me.alloc)) - } - } - - #[cfg(not(no_global_oom_handling))] - fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { - // Don't allocate here because `Drop` will not deallocate when `ca= pacity` is 0. - if T::IS_ZST || capacity =3D=3D 0 { - Self::new_in(alloc) - } else { - // We avoid `unwrap_or_else` here because it bloats the amount= of - // LLVM IR generated. - let layout =3D match Layout::array::(capacity) { - Ok(layout) =3D> layout, - Err(_) =3D> capacity_overflow(), - }; - match alloc_guard(layout.size()) { - Ok(_) =3D> {} - Err(_) =3D> capacity_overflow(), - } - let result =3D match init { - AllocInit::Uninitialized =3D> alloc.allocate(layout), - AllocInit::Zeroed =3D> alloc.allocate_zeroed(layout), - }; - let ptr =3D match result { - Ok(ptr) =3D> ptr, - Err(_) =3D> handle_alloc_error(layout), - }; - - // Allocators currently return a `NonNull<[u8]>` whose length - // matches the size requested. If that ever changes, the capac= ity - // here should change to `ptr.len() / mem::size_of::()`. - Self { - ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: unsafe { Cap(capacity) }, - alloc, - } - } - } - - fn try_allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Resu= lt { - // Don't allocate here because `Drop` will not deallocate when `ca= pacity` is 0. - if T::IS_ZST || capacity =3D=3D 0 { - return Ok(Self::new_in(alloc)); - } - - let layout =3D Layout::array::(capacity).map_err(|_| CapacityOv= erflow)?; - alloc_guard(layout.size())?; - let result =3D match init { - AllocInit::Uninitialized =3D> alloc.allocate(layout), - AllocInit::Zeroed =3D> alloc.allocate_zeroed(layout), - }; - let ptr =3D result.map_err(|_| AllocError { layout, non_exhaustive= : () })?; - - // 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: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: unsafe { Cap(capacity) }, - 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 `allo= c`, then this is - /// guaranteed. - #[inline] - pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A= ) -> Self { - let cap =3D if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacit= y) } }; - Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } - } - - /// Gets a raw pointer to the start of the allocation. Note that this = is - /// `Unique::dangling()` if `capacity =3D=3D 0` or `T` is zero-sized. = In the former case, you must - /// be careful. - #[inline] - pub fn ptr(&self) -> *mut T { - self.ptr.as_ptr() - } - - /// Gets the capacity of the allocation. - /// - /// This will always be `usize::MAX` if `T` is zero-sized. - #[inline(always)] - pub fn capacity(&self) -> usize { - if T::IS_ZST { usize::MAX } else { self.cap.0 } - } - - /// Returns a shared reference to the allocator backing this `RawVec`. - pub fn allocator(&self) -> &A { - &self.alloc - } - - fn current_memory(&self) -> Option<(NonNull, Layout)> { - if T::IS_ZST || self.cap.0 =3D=3D 0 { - None - } else { - // We could use Layout::array here which ensures the absence o= f 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 ch= ecks and avoid an unwrap. - let _: () =3D const { assert!(mem::size_of::() % mem::align= _of::() =3D=3D 0) }; - unsafe { - let align =3D mem::align_of::(); - let size =3D mem::size_of::().unchecked_mul(self.cap.0); - let layout =3D Layout::from_size_align_unchecked(size, ali= gn); - Some((self.ptr.cast().into(), layout)) - } - } - } - - /// Ensures that the buffer contains at least enough space to hold `le= n + - /// additional` elements. If it doesn't already have enough capacity, = will - /// reallocate enough space plus comfortable slack space to get amorti= zed - /// *O*(1) behavior. Will limit this behavior if it would needlessly c= ause - /// itself to panic. - /// - /// If `len` exceeds `self.capacity()`, this may fail to actually allo= cate - /// 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] - pub fn reserve(&mut self, len: usize, additional: usize) { - // Callers expect this function to be very cheap when there is alr= eady sufficient capacity. - // Therefore, we move all the resizing and error-handling logic fr= om grow_amortized and - // handle_reserve behind a call, while making sure that this funct= ion is likely to be - // inlined as just a comparison and a call if the comparison fails. - #[cold] - fn do_reserve_and_handle( - slf: &mut RawVec, - len: usize, - additional: usize, - ) { - handle_reserve(slf.grow_amortized(len, additional)); - } - - if self.needs_to_grow(len, additional) { - do_reserve_and_handle(self, len, additional); - } - } - - /// A specialized version of `reserve()` used only by the hot and - /// oft-instantiated `Vec::push()`, which does its own capacity check. - #[cfg(not(no_global_oom_handling))] - #[inline(never)] - pub fn reserve_for_push(&mut self, len: usize) { - handle_reserve(self.grow_amortized(len, 1)); - } - - /// 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> { - if self.needs_to_grow(len, additional) { - self.grow_amortized(len, additional)?; - } - unsafe { - // Inform the optimizer that the reservation has succeeded or = wasn't needed - core::intrinsics::assume(!self.needs_to_grow(len, additional)); - } - Ok(()) - } - - /// The same as `reserve_for_push`, but returns on errors instead of p= anicking or aborting. - #[inline(never)] - pub fn try_reserve_for_push(&mut self, len: usize) -> Result<(), TryRe= serveError> { - self.grow_amortized(len, 1) - } - - /// Ensures that the buffer contains at least enough space to hold `le= n + - /// 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 alloc= ator - /// is free to give back more than we asked for. - /// - /// If `len` exceeds `self.capacity()`, this may fail to actually allo= cate - /// 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))] - pub fn reserve_exact(&mut self, len: usize, additional: usize) { - handle_reserve(self.try_reserve_exact(len, additional)); - } - - /// The same as `reserve_exact`, but returns on errors instead of pani= cking or aborting. - pub fn try_reserve_exact( - &mut self, - len: usize, - additional: usize, - ) -> Result<(), TryReserveError> { - if self.needs_to_grow(len, additional) { - self.grow_exact(len, additional)?; - } - unsafe { - // Inform the optimizer that the reservation has succeeded or = wasn't needed - core::intrinsics::assume(!self.needs_to_grow(len, additional)); - } - Ok(()) - } - - /// Shrinks the buffer down to the specified capacity. If the given am= ount - /// 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))] - pub fn shrink_to_fit(&mut self, cap: usize) { - handle_reserve(self.shrink(cap)); - } -} - -impl RawVec { - /// Returns if the buffer needs to grow to fulfill the needed extra ca= pacity. - /// Mainly used to make inlining reserve-calls possible without inlini= ng `grow`. - fn needs_to_grow(&self, len: usize, additional: usize) -> bool { - additional > self.capacity().wrapping_sub(len) - } - - /// # Safety: - /// - /// `cap` must not exceed `isize::MAX`. - unsafe fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) { - // Allocators currently return a `NonNull<[u8]>` whose length matc= hes - // the size requested. If that ever changes, the capacity here sho= uld - // change to `ptr.len() / mem::size_of::()`. - self.ptr =3D unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; - self.cap =3D unsafe { Cap(cap) }; - } - - // This method is usually instantiated many times. So we want it to be= as - // small as possible, to improve compile times. But we also want as mu= ch of - // its contents to be statically computable as possible, to make the - // generated code run faster. Therefore, this method is carefully writ= ten - // so that all of the code that depends on `T` is within it, while as = much - // of the code that doesn't depend on `T` as possible is in functions = that - // are non-generic over `T`. - fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<= (), TryReserveError> { - // This is ensured by the calling contexts. - debug_assert!(additional > 0); - - if T::IS_ZST { - // Since we return a capacity of `usize::MAX` when `elem_size`= is - // 0, getting to here necessarily means the `RawVec` is overfu= ll. - return Err(CapacityOverflow.into()); - } - - // Nothing we can really do about these checks, sadly. - let required_cap =3D len.checked_add(additional).ok_or(CapacityOve= rflow)?; - - // This guarantees exponential growth. The doubling cannot overflow - // because `cap <=3D isize::MAX` and the type of `cap` is `usize`. - let cap =3D cmp::max(self.cap.0 * 2, required_cap); - let cap =3D cmp::max(Self::MIN_NON_ZERO_CAP, cap); - - let new_layout =3D Layout::array::(cap); - - // `finish_grow` is non-generic over `T`. - let ptr =3D finish_grow(new_layout, self.current_memory(), &mut se= lf.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(()) - } - - // The constraints on this method are much the same as those on - // `grow_amortized`, but this method is usually instantiated less ofte= n so - // it's less critical. - fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), = TryReserveError> { - if T::IS_ZST { - // Since we return a capacity of `usize::MAX` when the type si= ze is - // 0, getting to here necessarily means the `RawVec` is overfu= ll. - return Err(CapacityOverflow.into()); - } - - let cap =3D len.checked_add(additional).ok_or(CapacityOverflow)?; - let new_layout =3D Layout::array::(cap); - - // `finish_grow` is non-generic over `T`. - let ptr =3D finish_grow(new_layout, self.current_memory(), &mut se= lf.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))] - fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> { - assert!(cap <=3D self.capacity(), "Tried to shrink to a larger cap= acity"); - - let (ptr, layout) =3D if let Some(mem) =3D self.current_memory() {= mem } else { return Ok(()) }; - // See current_memory() why this assert is here - let _: () =3D const { assert!(mem::size_of::() % mem::align_of:= :() =3D=3D 0) }; - - // If shrinking to 0, deallocate the buffer. We don't reach this p= oint - // for the T::IS_ZST case since current_memory() will have returned - // None. - if cap =3D=3D 0 { - unsafe { self.alloc.deallocate(ptr, layout) }; - self.ptr =3D Unique::dangling(); - self.cap =3D Cap::ZERO; - } else { - let ptr =3D unsafe { - // `Layout::array` cannot overflow here because it would h= ave - // overflowed earlier when capacity was larger. - let new_size =3D mem::size_of::().unchecked_mul(cap); - let new_layout =3D Layout::from_size_align_unchecked(new_s= ize, layout.align()); - self.alloc - .shrink(ptr, layout, new_layout) - .map_err(|_| AllocError { layout: new_layout, non_exha= ustive: () })? - }; - // SAFETY: if the allocation is valid, then the capacity is too - unsafe { - self.set_ptr_and_cap(ptr, cap); - } - } - Ok(()) - } -} - -// This function is outside `RawVec` to minimize compile times. See the co= mment -// above `RawVec::grow_amortized` for details. (The `A` parameter isn't -// significant, because the number of different `A` types seen in practice= is -// much smaller than the number of `T` types.) -#[inline(never)] -fn finish_grow( - new_layout: Result, - current_memory: Option<(NonNull, Layout)>, - alloc: &mut A, -) -> Result, TryReserveError> -where - A: Allocator, -{ - // Check for the error here to minimize the size of `RawVec::grow_*`. - let new_layout =3D new_layout.map_err(|_| CapacityOverflow)?; - - alloc_guard(new_layout.size())?; - - let memory =3D if let Some((ptr, old_layout)) =3D current_memory { - debug_assert_eq!(old_layout.align(), new_layout.align()); - unsafe { - // The allocator checks for alignment equality - intrinsics::assume(old_layout.align() =3D=3D 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()) -} - -unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { - /// Frees the memory owned by the `RawVec` *without* trying to drop it= s contents. - fn drop(&mut self) { - if let Some((ptr, layout)) =3D self.current_memory() { - unsafe { self.alloc.deallocate(ptr, layout) } - } - } -} - -// Central function for reserve error handling. -#[cfg(not(no_global_oom_handling))] -#[inline] -fn handle_reserve(result: Result<(), TryReserveError>) { - match result.map_err(|e| e.kind()) { - Err(CapacityOverflow) =3D> capacity_overflow(), - Err(AllocError { layout, .. }) =3D> handle_alloc_error(layout), - Ok(()) =3D> { /* yay */ } - } -} - -// 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 u= se -// 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(()) - } -} - -// One central function responsible for reporting capacity overflows. This= 'll -// ensure that the code generation related to these panics is minimal as t= here's -// only one location which panics rather than a bunch throughout the modul= e. -#[cfg(not(no_global_oom_handling))] -#[cfg_attr(not(feature =3D "panic_immediate_abort"), inline(never))] -fn capacity_overflow() -> ! { - panic!("capacity overflow"); -} diff --git a/rust/alloc/slice.rs b/rust/alloc/slice.rs deleted file mode 100644 index 1181836da5f4..000000000000 --- a/rust/alloc/slice.rs +++ /dev/null @@ -1,890 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -//! 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 b= e 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 =3D "rust1", since =3D "1.0.0")] -// Many of the usings in this module are only used in the test configurati= on. -// It's cleaner to just turn off the unused_imports warning than to fix th= em. -#![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, SizedTypeProperties}; -#[cfg(not(no_global_oom_handling))] -use core::ptr; -#[cfg(not(no_global_oom_handling))] -use core::slice::sort; - -use crate::alloc::Allocator; -#[cfg(not(no_global_oom_handling))] -use crate::alloc::{self, Global}; -#[cfg(not(no_global_oom_handling))] -use crate::borrow::ToOwned; -use crate::boxed::Box; -use crate::vec::Vec; - -#[cfg(test)] -mod tests; - -#[unstable(feature =3D "slice_range", issue =3D "76393")] -pub use core::slice::range; -#[unstable(feature =3D "array_chunks", issue =3D "74985")] -pub use core::slice::ArrayChunks; -#[unstable(feature =3D "array_chunks", issue =3D "74985")] -pub use core::slice::ArrayChunksMut; -#[unstable(feature =3D "array_windows", issue =3D "75027")] -pub use core::slice::ArrayWindows; -#[stable(feature =3D "inherent_ascii_escape", since =3D "1.60.0")] -pub use core::slice::EscapeAscii; -#[stable(feature =3D "slice_get_slice", since =3D "1.28.0")] -pub use core::slice::SliceIndex; -#[stable(feature =3D "from_ref", since =3D "1.28.0")] -pub use core::slice::{from_mut, from_ref}; -#[unstable(feature =3D "slice_from_ptr_range", issue =3D "89792")] -pub use core::slice::{from_mut_ptr_range, from_ptr_range}; -#[stable(feature =3D "rust1", since =3D "1.0.0")] -pub use core::slice::{from_raw_parts, from_raw_parts_mut}; -#[stable(feature =3D "rust1", since =3D "1.0.0")] -pub use core::slice::{Chunks, Windows}; -#[stable(feature =3D "chunks_exact", since =3D "1.31.0")] -pub use core::slice::{ChunksExact, ChunksExactMut}; -#[stable(feature =3D "rust1", since =3D "1.0.0")] -pub use core::slice::{ChunksMut, Split, SplitMut}; -#[unstable(feature =3D "slice_group_by", issue =3D "80552")] -pub use core::slice::{GroupBy, GroupByMut}; -#[stable(feature =3D "rust1", since =3D "1.0.0")] -pub use core::slice::{Iter, IterMut}; -#[stable(feature =3D "rchunks", since =3D "1.31.0")] -pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; -#[stable(feature =3D "slice_rsplit", since =3D "1.27.0")] -pub use core::slice::{RSplit, RSplitMut}; -#[stable(feature =3D "rust1", since =3D "1.0.0")] -pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; -#[stable(feature =3D "split_inclusive", since =3D "1.51.0")] -pub use core::slice::{SplitInclusive, SplitInclusiveMut}; - -//////////////////////////////////////////////////////////////////////////= ////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////= ////// - -// HACK(japaric) needed for the implementation of `vec!` macro during test= ing -// 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 test= ing -// N.B., see the `hack` module in this file for more details. -#[cfg(test)] -pub use hack::to_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. - pub fn into_vec(b: Box<[T], A>) -> Vec { - unsafe { - let len =3D b.len(); - let (b, alloc) =3D Box::into_raw_with_allocator(b); - Vec::from_raw_parts_in(b as *mut T, len, len, alloc) - } - } - - #[cfg(not(no_global_oom_handling))] - #[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 =3D Vec::with_capacity_in(s.len(), alloc); - let mut guard =3D DropGuard { vec: &mut vec, num_init: 0 }; - let slots =3D guard.vec.spare_capacity_mut(); - // .take(slots.len()) is necessary for LLVM to remove bounds c= hecks - // and has better codegen than zip. - for (i, b) in s.iter().enumerate().take(slots.len()) { - guard.num_init =3D i; - slots[i].write(b.clone()); - } - core::mem::forget(guard); - // SAFETY: - // the vec was allocated and initialized above to at least thi= s 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 =3D 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. - /// - /// This sort is stable (i.e., does not reorder equal elements) and *O= *(*n* \* log(*n*)) worst-case. - /// - /// When applicable, unstable sorting is preferred because it is gener= ally faster than stable - /// sorting and it doesn't allocate auxiliary memory. - /// See [`sort_unstable`](slice::sort_unstable). - /// - /// # Current implementation - /// - /// The current algorithm is an adaptive, iterative merge sort inspire= d by - /// [timsort](https://en.wikipedia.org/wiki/Timsort). - /// It is designed to be very fast in cases where the slice is nearly = sorted, or consists of - /// two or more sorted sequences concatenated one after another. - /// - /// Also, it allocates temporary storage half the size of `self`, but = for short slices a - /// non-allocating insertion sort is used instead. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D [-5, 4, 1, -3, 2]; - /// - /// v.sort(); - /// assert!(v =3D=3D [-5, -3, 1, 2, 4]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[rustc_allow_incoherent_impl] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - #[inline] - pub fn sort(&mut self) - where - T: Ord, - { - stable_sort(self, T::lt); - } - - /// Sorts the slice with a comparator function. - /// - /// This sort is stable (i.e., does not reorder equal elements) and *O= *(*n* \* log(*n*)) worst-case. - /// - /// The comparator function must define a total ordering for the eleme= nts in the slice. If - /// the ordering is not total, the order of the elements is unspecifie= d. An order is a - /// total order if it is (for all `a`, `b` and `c`): - /// - /// * total and antisymmetric: exactly one of `a < b`, `a =3D=3D b` or= `a > b` is true, and - /// * transitive, `a < b` and `b < c` implies `a < c`. The same must h= old for both `=3D=3D` and `>`. - /// - /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN = !=3D NaN`, we can use - /// `partial_cmp` as our sort function when we know the slice doesn't = contain a `NaN`. - /// - /// ``` - /// let mut floats =3D [5f64, 4.0, 1.0, 3.0, 2.0]; - /// floats.sort_by(|a, b| a.partial_cmp(b).unwrap()); - /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); - /// ``` - /// - /// When applicable, unstable sorting is preferred because it is gener= ally faster than stable - /// sorting and it doesn't allocate auxiliary memory. - /// See [`sort_unstable_by`](slice::sort_unstable_by). - /// - /// # Current implementation - /// - /// The current algorithm is an adaptive, iterative merge sort inspire= d by - /// [timsort](https://en.wikipedia.org/wiki/Timsort). - /// It is designed to be very fast in cases where the slice is nearly = sorted, or consists of - /// two or more sorted sequences concatenated one after another. - /// - /// Also, it allocates temporary storage half the size of `self`, but = for short slices a - /// non-allocating insertion sort is used instead. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D [5, 4, 1, 3, 2]; - /// v.sort_by(|a, b| a.cmp(b)); - /// assert!(v =3D=3D [1, 2, 3, 4, 5]); - /// - /// // reverse sorting - /// v.sort_by(|a, b| b.cmp(a)); - /// assert!(v =3D=3D [5, 4, 3, 2, 1]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[rustc_allow_incoherent_impl] - #[stable(feature =3D "rust1", since =3D "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) =3D=3D Less); - } - - /// Sorts the slice with a key extraction function. - /// - /// 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*). - /// - /// For expensive key functions (e.g. functions that are not simple pr= operty accesses or - /// basic operations), [`sort_by_cached_key`](slice::sort_by_cached_ke= y) is likely to be - /// significantly faster, as it does not recompute element keys. - /// - /// When applicable, unstable sorting is preferred because it is gener= ally faster than stable - /// sorting and it doesn't allocate auxiliary memory. - /// See [`sort_unstable_by_key`](slice::sort_unstable_by_key). - /// - /// # Current implementation - /// - /// The current algorithm is an adaptive, iterative merge sort inspire= d by - /// [timsort](https://en.wikipedia.org/wiki/Timsort). - /// It is designed to be very fast in cases where the slice is nearly = sorted, or consists of - /// two or more sorted sequences concatenated one after another. - /// - /// Also, it allocates temporary storage half the size of `self`, but = for short slices a - /// non-allocating insertion sort is used instead. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D [-5i32, 4, 1, -3, 2]; - /// - /// v.sort_by_key(|k| k.abs()); - /// assert!(v =3D=3D [1, 2, -3, 4, -5]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[rustc_allow_incoherent_impl] - #[stable(feature =3D "slice_sort_by_key", since =3D "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. - /// - /// During sorting, the key function is called at most once per elemen= t, by using - /// temporary storage to remember the results of key evaluation. - /// The order of calls to the key function is unspecified and may chan= ge in future versions - /// of the standard library. - /// - /// 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*). - /// - /// For simple key functions (e.g., functions that are property access= es or - /// basic operations), [`sort_by_key`](slice::sort_by_key) is likely t= o be - /// faster. - /// - /// # Current implementation - /// - /// The current algorithm is based on [pattern-defeating quicksort][pd= qsort] by Orson Peters, - /// which combines the fast average case of randomized quicksort with = the fast worst case of - /// heapsort, while achieving linear time on slices with certain patte= rns. It uses some - /// randomization to avoid degenerate cases, but with a fixed seed to = always provide - /// deterministic behavior. - /// - /// In the worst case, the algorithm allocates temporary storage in a = `Vec<(K, usize)>` the - /// length of the slice. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D [-5i32, 4, 32, -3, 2]; - /// - /// v.sort_by_cached_key(|k| k.to_string()); - /// assert!(v =3D=3D [-3, -5, 2, 32, 4]); - /// ``` - /// - /// [pdqsort]: https://github.com/orlp/pdqsort - #[cfg(not(no_global_oom_handling))] - #[rustc_allow_incoherent_impl] - #[stable(feature =3D "slice_sort_by_cached_key", since =3D "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 t= ype, to reduce allocation. - macro_rules! sort_by_key { - ($t:ty, $slice:ident, $f:ident) =3D> {{ - let mut indices: Vec<_> =3D - $slice.iter().map($f).enumerate().map(|(i, k)| (k, i a= s $t)).collect(); - // The elements of `indices` are unique, as they are index= ed, so any sort will be - // stable with respect to the original slice. We use `sort= _unstable` here because - // it requires less memory allocation. - indices.sort_unstable(); - for i in 0..$slice.len() { - let mut index =3D indices[i].1; - while (index as usize) < i { - index =3D indices[index as usize].1; - } - indices[i].1 =3D index; - $slice.swap(i, index as usize); - } - }}; - } - - let sz_u8 =3D mem::size_of::<(K, u8)>(); - let sz_u16 =3D mem::size_of::<(K, u16)>(); - let sz_u32 =3D mem::size_of::<(K, u32)>(); - let sz_usize =3D mem::size_of::<(K, usize)>(); - - let len =3D self.len(); - if len < 2 { - return; - } - if sz_u8 < sz_u16 && len <=3D (u8::MAX as usize) { - return sort_by_key!(u8, self, f); - } - if sz_u16 < sz_u32 && len <=3D (u16::MAX as usize) { - return sort_by_key!(u16, self, f); - } - if sz_u32 < sz_usize && len <=3D (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 =3D [10, 40, 30]; - /// let x =3D 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 =3D "rust1", since =3D "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 =3D [10, 40, 30]; - /// let x =3D 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 =3D "allocator_api", issue =3D "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]> =3D Box::new([10, 40, 30]); - /// let x =3D 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 =3D "rust1", since =3D "1.0.0")] - #[inline] - 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 =3D "repeat_generic_slice", since =3D "1.40.0")] - pub fn repeat(&self, n: usize) -> Vec - where - T: Copy, - { - if n =3D=3D 0 { - return Vec::new(); - } - - // If `n` is larger than zero, it can be split as - // `n =3D 2^expn + rem (2^expn > rem, expn >=3D 0, rem >=3D 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 =3D self.len().checked_mul(n).expect("capacity overfl= ow"); - let mut buf =3D Vec::with_capacity(capacity); - - // `2^expn` repetition is done by doubling `buf` `expn`-times. - buf.extend(self); - { - let mut m =3D 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() as *mut T).add(buf.len()), - buf.len(), - ); - // `buf` has capacity of `self.len() * n`. - let buf_len =3D buf.len(); - buf.set_len(buf_len * 2); - } - - m >>=3D 1; - } - } - - // `rem` (`=3D n - 2^expn`) repetition is done by copying - // first `rem` repetitions from `buf` itself. - let rem_len =3D 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() as *mut T).add(buf.len()), - rem_len, - ); - // `buf.len() + rem_len` equals to `buf.capacity()` (`=3D = 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 =3D "rust1", since =3D "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`, placin= g 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 =3D "rename_connect_to_join", since =3D "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`, placin= g 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 =3D "rust1", since =3D "1.0.0")] - #[deprecated(since =3D "1.3.0", note =3D "renamed to join", suggestion= =3D "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 =3D "this returns the uppercase bytes as a new Vec, \ - without modifying the original"] - #[stable(feature =3D "ascii_methods_on_intrinsics", since =3D "1.23.0"= )] - #[inline] - pub fn to_ascii_uppercase(&self) -> Vec { - let mut me =3D 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 =3D "this returns the lowercase bytes as a new Vec, \ - without modifying the original"] - #[stable(feature =3D "ascii_methods_on_intrinsics", since =3D "1.23.0"= )] - #[inline] - pub fn to_ascii_lowercase(&self) -> Vec { - let mut me =3D 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 tr= ait, 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 =3D "slice_concat_trait", issue =3D "27747")] -pub trait Concat { - #[unstable(feature =3D "slice_concat_trait", issue =3D "27747")] - /// The resulting type after concatenation - type Output; - - /// Implementation of [`[T]::concat`](slice::concat) - #[unstable(feature =3D "slice_concat_trait", issue =3D "27747")] - fn concat(slice: &Self) -> Self::Output; -} - -/// Helper trait for [`[T]::join`](slice::join) -#[unstable(feature =3D "slice_concat_trait", issue =3D "27747")] -pub trait Join { - #[unstable(feature =3D "slice_concat_trait", issue =3D "27747")] - /// The resulting type after concatenation - type Output; - - /// Implementation of [`[T]::join`](slice::join) - #[unstable(feature =3D "slice_concat_trait", issue =3D "27747")] - fn join(slice: &Self, sep: Separator) -> Self::Output; -} - -#[cfg(not(no_global_oom_handling))] -#[unstable(feature =3D "slice_concat_ext", issue =3D "27747")] -impl> Concat for [V] { - type Output =3D Vec; - - fn concat(slice: &Self) -> Vec { - let size =3D slice.iter().map(|slice| slice.borrow().len()).sum(); - let mut result =3D Vec::with_capacity(size); - for v in slice { - result.extend_from_slice(v.borrow()) - } - result - } -} - -#[cfg(not(no_global_oom_handling))] -#[unstable(feature =3D "slice_concat_ext", issue =3D "27747")] -impl> Join<&T> for [V] { - type Output =3D Vec; - - fn join(slice: &Self, sep: &T) -> Vec { - let mut iter =3D slice.iter(); - let first =3D match iter.next() { - Some(first) =3D> first, - None =3D> return vec![], - }; - let size =3D slice.iter().map(|v| v.borrow().len()).sum::()= + slice.len() - 1; - let mut result =3D 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 =3D "slice_concat_ext", issue =3D "27747")] -impl> Join<&[T]> for [V] { - type Output =3D Vec; - - fn join(slice: &Self, sep: &[T]) -> Vec { - let mut iter =3D slice.iter(); - let first =3D match iter.next() { - Some(first) =3D> first, - None =3D> return vec![], - }; - let size =3D - slice.iter().map(|v| v.borrow().len()).sum::() + sep.le= n() * (slice.len() - 1); - let mut result =3D 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 =3D "rust1", since =3D "1.0.0")] -impl Borrow<[T]> for Vec { - fn borrow(&self) -> &[T] { - &self[..] - } -} - -#[stable(feature =3D "rust1", since =3D "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 <=3D self.len due to the truncate above, so the - // slices here are always in-bounds. - let (init, tail) =3D 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 =3D "rust1", since =3D "1.0.0")] -impl ToOwned for [T] { - type Owned =3D 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, -{ - if T::IS_ZST { - // Sorting has no meaningful behavior on zero-sized types. Do noth= ing. - return; - } - - let elem_alloc_fn =3D |len: usize| -> *mut T { - // SAFETY: Creating the layout is safe as long as merge_sort never= calls this with len > - // v.len(). Alloc in general will only be used as 'shadow-region' = to store temporary swap - // elements. - unsafe { alloc::alloc(alloc::Layout::array::(len).unwrap_unchec= ked()) as *mut T } - }; - - let elem_dealloc_fn =3D |buf_ptr: *mut T, len: usize| { - // SAFETY: Creating the layout is safe as long as merge_sort never= calls this with len > - // v.len(). The caller must ensure that buf_ptr was created by ele= m_alloc_fn with the same - // len. - unsafe { - alloc::dealloc(buf_ptr as *mut u8, alloc::Layout::array::(l= en).unwrap_unchecked()); - } - }; - - let run_alloc_fn =3D |len: usize| -> *mut sort::TimSortRun { - // SAFETY: Creating the layout is safe as long as merge_sort never= calls this with an - // obscene length or 0. - unsafe { - alloc::alloc(alloc::Layout::array::(len).unw= rap_unchecked()) - as *mut sort::TimSortRun - } - }; - - let run_dealloc_fn =3D |buf_ptr: *mut sort::TimSortRun, len: usize| { - // SAFETY: The caller must ensure that buf_ptr was created by elem= _alloc_fn with the same - // len. - unsafe { - alloc::dealloc( - buf_ptr as *mut u8, - alloc::Layout::array::(len).unwrap_unche= cked(), - ); - } - }; - - sort::merge_sort(v, &mut is_less, elem_alloc_fn, elem_dealloc_fn, run_= alloc_fn, run_dealloc_fn); -} diff --git a/rust/alloc/vec/drain.rs b/rust/alloc/vec/drain.rs deleted file mode 100644 index 78177a9e2ad0..000000000000 --- a/rust/alloc/vec/drain.rs +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -use crate::alloc::{Allocator, Global}; -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; - -/// A draining iterator for `Vec`. -/// -/// This `struct` is created by [`Vec::drain`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// let mut v =3D vec![0, 1, 2]; -/// let iter: std::vec::Drain<'_, _> =3D v.drain(..); -/// ``` -#[stable(feature =3D "drain", since =3D "1.6.0")] -pub struct Drain< - 'a, - T: 'a, - #[unstable(feature =3D "allocator_api", issue =3D "32838")] A: Allocat= or + 'a =3D 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 =3D "collection_debug", since =3D "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 =3D vec!['a', 'b', 'c']; - /// let mut drain =3D vec.drain(..); - /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); - /// let _ =3D drain.next().unwrap(); - /// assert_eq!(drain.as_slice(), &['b', 'c']); - /// ``` - #[must_use] - #[stable(feature =3D "vec_drain_as_slice", since =3D "1.46.0")] - pub fn as_slice(&self) -> &[T] { - self.iter.as_slice() - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature =3D "allocator_api", issue =3D "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 =3D vec!['a', 'b', 'c']; - /// let mut drain =3D 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 =3D "drain_keep_rest", issue =3D "101122")] - pub fn keep_rest(self) { - // At this moment layout looks like this: - // - // [head] [yielded by next] [unyielded] [yielded by next_back] [ta= il] - // ^-- 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(unyiel= ded) + 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 sta= te already, there is nothing to do - let mut this =3D ManuallyDrop::new(self); - - unsafe { - let source_vec =3D this.vec.as_mut(); - - let start =3D source_vec.len(); - let tail =3D this.tail_start; - - let unyielded_len =3D this.iter.len(); - let unyielded_ptr =3D 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 =3D source_vec.as_mut_ptr().add(start); - - // memmove back unyielded elements - if unyielded_ptr !=3D start_ptr { - let src =3D unyielded_ptr; - let dst =3D start_ptr; - - ptr::copy(src, dst, unyielded_len); - } - - // memmove back untouched tail - if tail !=3D (start + unyielded_len) { - let src =3D source_vec.as_ptr().add(tail); - let dst =3D start_ptr.add(unyielded_len); - ptr::copy(src, dst, this.tail_len); - } - } - - source_vec.set_len(start + unyielded_len + this.tail_len); - } - } -} - -#[stable(feature =3D "vec_drain_as_slice", since =3D "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 =3D "drain", since =3D "1.6.0")] -unsafe impl Sync for Drain<'_, T, A> {} -#[stable(feature =3D "drain", since =3D "1.6.0")] -unsafe impl Send for Drain<'_, T, A> {} - -#[stable(feature =3D "drain", since =3D "1.6.0")] -impl Iterator for Drain<'_, T, A> { - type Item =3D 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 =3D "drain", since =3D "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 =3D "drain", since =3D "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 =3D self.0.vec.as_mut(); - // memmove back untouched tail, update to new leng= th - let start =3D source_vec.len(); - let tail =3D self.0.tail_start; - if tail !=3D start { - let src =3D source_vec.as_ptr().add(tail); - let dst =3D 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 =3D mem::take(&mut self.iter); - let drop_len =3D iter.len(); - - let mut vec =3D 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 =3D vec.as_mut(); - let old_len =3D 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, e= ven when drop_in_place panics - let _guard =3D DropGuard(self); - - if drop_len =3D=3D 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 da= ngling pointer - // which would make it and the vec pointer point to different allo= cations which would - // lead to invalid pointer arithmetic below. - let drop_ptr =3D 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 w= e 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 =3D vec.as_mut().as_mut_ptr(); - let drop_offset =3D drop_ptr.sub_ptr(vec_ptr); - let to_drop =3D ptr::slice_from_raw_parts_mut(vec_ptr.add(drop= _offset), drop_len); - ptr::drop_in_place(to_drop); - } - } -} - -#[stable(feature =3D "drain", since =3D "1.6.0")] -impl ExactSizeIterator for Drain<'_, T, A> { - fn is_empty(&self) -> bool { - self.iter.is_empty() - } -} - -#[unstable(feature =3D "trusted_len", issue =3D "37572")] -unsafe impl TrustedLen for Drain<'_, T, A> {} - -#[stable(feature =3D "fused", since =3D "1.26.0")] -impl FusedIterator for Drain<'_, T, A> {} diff --git a/rust/alloc/vec/extract_if.rs b/rust/alloc/vec/extract_if.rs deleted file mode 100644 index f314a51d4d3d..000000000000 --- a/rust/alloc/vec/extract_if.rs +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -use crate::alloc::{Allocator, Global}; -use core::ptr; -use core::slice; - -use super::Vec; - -/// 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 =3D vec![0, 1, 2]; -/// let iter: std::vec::ExtractIf<'_, _, _> =3D v.extract_if(|x| *x % 2 = =3D=3D 0); -/// ``` -#[unstable(feature =3D "extract_if", reason =3D "recently added", issue = =3D "43244")] -#[derive(Debug)] -#[must_use =3D "iterators are lazy and do nothing unless consumed"] -pub struct ExtractIf< - 'a, - T, - F, - #[unstable(feature =3D "allocator_api", issue =3D "32838")] A: Allocat= or =3D 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 =3D "allocator_api", issue =3D "32838")] - #[inline] - pub fn allocator(&self) -> &A { - self.vec.allocator() - } -} - -#[unstable(feature =3D "extract_if", reason =3D "recently added", issue = =3D "43244")] -impl Iterator for ExtractIf<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - type Item =3D T; - - fn next(&mut self) -> Option { - unsafe { - while self.idx < self.old_len { - let i =3D self.idx; - let v =3D slice::from_raw_parts_mut(self.vec.as_mut_ptr(),= self.old_len); - let drained =3D (self.pred)(&mut v[i]); - // Update the index *after* the predicate is called. If th= e index - // is updated prior and the predicate panics, the element = at this - // index would be leaked. - self.idx +=3D 1; - if drained { - self.del +=3D 1; - return Some(ptr::read(&v[i])); - } else if self.del > 0 { - let del =3D self.del; - let src: *const T =3D &v[i]; - let dst: *mut T =3D &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 =3D "extract_if", reason =3D "recently added", issue = =3D "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 reall= y an - // obviously right thing to do. We don't want to keep tryi= ng - // to execute `pred`, so we just backshift all the unproce= ssed - // elements and tell the vec that they still exist. The ba= ckshift - // is required to prevent a double-drop of the last succes= sfully - // drained item prior to a panic in the predicate. - let ptr =3D self.vec.as_mut_ptr(); - let src =3D ptr.add(self.idx); - let dst =3D src.sub(self.del); - let tail_len =3D self.old_len - self.idx; - src.copy_to(dst, tail_len); - } - self.vec.set_len(self.old_len - self.del); - } - } -} diff --git a/rust/alloc/vec/into_iter.rs b/rust/alloc/vec/into_iter.rs deleted file mode 100644 index 136bfe94af6c..000000000000 --- a/rust/alloc/vec/into_iter.rs +++ /dev/null @@ -1,454 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -#[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; -use core::array; -use core::fmt; -use core::iter::{ - FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen, - TrustedRandomAccessNoCoerce, -}; -use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; -use core::num::NonZeroUsize; -#[cfg(not(no_global_oom_handling))] -use core::ops::Deref; -use core::ptr::{self, NonNull}; -use core::slice::{self}; - -/// An iterator that moves out of a vector. -/// -/// This `struct` is created by the `into_iter` method on [`Vec`](super::V= ec) -/// (provided by the [`IntoIterator`] trait). -/// -/// # Example -/// -/// ``` -/// let v =3D vec![0, 1, 2]; -/// let iter: std::vec::IntoIter<_> =3D v.into_iter(); -/// ``` -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[rustc_insignificant_dtor] -pub struct IntoIter< - T, - #[unstable(feature =3D "allocator_api", issue =3D "32838")] A: Allocat= or =3D 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 Manua= llyDrop - pub(super) alloc: ManuallyDrop, - pub(super) ptr: *const T, - pub(super) end: *const T, // If T is a ZST, this is actually ptr+len. = This encoding is picked so that - // ptr =3D=3D end is a quick test for the It= erator being empty, that works - // for both ZST and non-ZST. -} - -#[stable(feature =3D "vec_intoiter_debug", since =3D "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 =3D vec!['a', 'b', 'c']; - /// let mut into_iter =3D vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// let _ =3D into_iter.next().unwrap(); - /// assert_eq!(into_iter.as_slice(), &['b', 'c']); - /// ``` - #[stable(feature =3D "vec_into_iter_as_slice", since =3D "1.15.0")] - pub fn as_slice(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.ptr, self.len()) } - } - - /// Returns the remaining items of this iterator as a mutable slice. - /// - /// # Examples - /// - /// ``` - /// let vec =3D vec!['a', 'b', 'c']; - /// let mut into_iter =3D vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// into_iter.as_mut_slice()[2] =3D 'z'; - /// assert_eq!(into_iter.next().unwrap(), 'a'); - /// assert_eq!(into_iter.next().unwrap(), 'b'); - /// assert_eq!(into_iter.next().unwrap(), 'z'); - /// ``` - #[stable(feature =3D "vec_into_iter_as_slice", since =3D "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 =3D "allocator_api", issue =3D "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 *mut T, 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 into_iter =3D Vec::::with_capacity(10).into_iter(); - /// let mut into_iter =3D std::mem::replace(&mut into_iter, Vec::new()= .into_iter()); - /// (&mut into_iter).for_each(drop); - /// std::mem::forget(into_iter); - /// ``` - /// - /// This method is used by in-place iteration, refer to the vec::in_pl= ace_collect - /// documentation for an overview. - #[cfg(not(no_global_oom_handling))] - pub(super) fn forget_allocation_drop_remaining(&mut self) { - let remaining =3D 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 =3D 0; - self.buf =3D unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; - self.ptr =3D self.buf.as_ptr(); - self.end =3D 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 ba= cking allocation to be freed. - pub(crate) fn forget_remaining_elements(&mut self) { - // For th ZST case, it is crucial that we mutate `end` here, not `= ptr`. - // `ptr` must stay aligned, while `end` may be unaligned. - self.end =3D self.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 allocat= or - let mut this =3D ManuallyDrop::new(self); - - // SAFETY: This allocation originally came from a `Vec`, so it pas= ses - // all those checks. We have `this.buf` =E2=89=A4 `this.ptr` =E2= =89=A4 `this.end`, - // so the `sub_ptr`s below cannot wrap, and will produce a well-fo= rmed - // range. `end` =E2=89=A4 `buf + cap`, so the range will be in-bou= nds. - // Taking `alloc` is ok because nothing else is going to look at i= t, - // since our `Drop` impl isn't going to run so there's no more cod= e. - unsafe { - let buf =3D this.buf.as_ptr(); - let initialized =3D 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 "allocatio= n". - 0..this.len() - } else { - this.ptr.sub_ptr(buf)..this.end.sub_ptr(buf) - }; - let cap =3D this.cap; - let alloc =3D ManuallyDrop::take(&mut this.alloc); - VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, = alloc) - } - } -} - -#[stable(feature =3D "vec_intoiter_as_ref", since =3D "1.46.0")] -impl AsRef<[T]> for IntoIter { - fn as_ref(&self) -> &[T] { - self.as_slice() - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -unsafe impl Send for IntoIter {} -#[stable(feature =3D "rust1", since =3D "1.0.0")] -unsafe impl Sync for IntoIter {} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Iterator for IntoIter { - type Item =3D T; - - #[inline] - fn next(&mut self) -> Option { - if self.ptr =3D=3D self.end { - None - } else if T::IS_ZST { - // `ptr` has to stay where it is to remain aligned, so we redu= ce the length by 1 by - // reducing the `end`. - self.end =3D self.end.wrapping_byte_sub(1); - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - let old =3D self.ptr; - self.ptr =3D unsafe { self.ptr.add(1) }; - - Some(unsafe { ptr::read(old) }) - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let exact =3D if T::IS_ZST { - self.end.addr().wrapping_sub(self.ptr.addr()) - } else { - unsafe { self.end.sub_ptr(self.ptr) } - }; - (exact, Some(exact)) - } - - #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - let step_size =3D self.len().min(n); - let to_drop =3D ptr::slice_from_raw_parts_mut(self.ptr as *mut T, = step_size); - if T::IS_ZST { - // See `next` for why we sub `end` here. - self.end =3D self.end.wrapping_byte_sub(step_size); - } else { - // SAFETY: the min() above ensures that step_size is in bounds - self.ptr =3D unsafe { self.ptr.add(step_size) }; - } - // SAFETY: the min() above ensures that step_size is in bounds - unsafe { - ptr::drop_in_place(to_drop); - } - NonZeroUsize::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 =3D MaybeUninit::uninit_array(); - - let len =3D 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 =3D 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 availab= le and we just checked that - // it fits into the array. - unsafe { - ptr::copy_nonoverlapping(self.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 amoun= t here to fully initialize - // the array. - return unsafe { - ptr::copy_nonoverlapping(self.ptr, raw_ary.as_mut_ptr() as *mu= t T, N); - self.ptr =3D self.ptr.add(N); - Ok(raw_ary.transpose().assume_init()) - }; - } - - 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` req= uires - // that `T: Copy` so reading elements from the buffer doesn't inva= lidate - // them for `Drop`. - unsafe { if T::IS_ZST { mem::zeroed() } else { ptr::read(self.ptr.= add(i)) } } - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { - if self.end =3D=3D self.ptr { - None - } else if T::IS_ZST { - // See above for why 'ptr.offset' isn't used - self.end =3D self.end.wrapping_byte_sub(1); - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - self.end =3D unsafe { self.end.sub(1) }; - - Some(unsafe { ptr::read(self.end) }) - } - } - - #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - let step_size =3D self.len().min(n); - if T::IS_ZST { - // SAFETY: same as for advance_by() - self.end =3D self.end.wrapping_byte_sub(step_size); - } else { - // SAFETY: same as for advance_by() - self.end =3D unsafe { self.end.sub(step_size) }; - } - let to_drop =3D 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); - } - NonZeroUsize::new(n - step_size).map_or(Ok(()), Err) - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl ExactSizeIterator for IntoIter { - fn is_empty(&self) -> bool { - self.ptr =3D=3D self.end - } -} - -#[stable(feature =3D "fused", since =3D "1.26.0")] -impl FusedIterator for IntoIter {} - -#[doc(hidden)] -#[unstable(issue =3D "none", feature =3D "trusted_fused")] -unsafe impl TrustedFused for IntoIter {} - -#[unstable(feature =3D "trusted_len", issue =3D "37572")] -unsafe impl TrustedLen for IntoIter {} - -#[stable(feature =3D "default_iters", since =3D "1.70.0")] -impl Default for IntoIter -where - A: Allocator + Default, -{ - /// Creates an empty `vec::IntoIter`. - /// - /// ``` - /// # use std::vec; - /// let iter: vec::IntoIter =3D 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 =3D "none", feature =3D "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 =3D "none", feature =3D "std_internals")] -impl NonDrop for T {} - -#[doc(hidden)] -#[unstable(issue =3D "none", feature =3D "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 =3D false; -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "vec_into_iter_clone", since =3D "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 =3D "rust1", since =3D "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 an= d will be dropped by RawVec - let alloc =3D ManuallyDrop::take(&mut self.0.alloc); - // RawVec handles deallocation - let _ =3D RawVec::from_raw_parts_in(self.0.buf.as_ptr(= ), self.0.cap, alloc); - } - } - } - - let guard =3D 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 trai= ts -// also refer to the vec::in_place_collect module documentation to get an = overview -#[unstable(issue =3D "none", feature =3D "inplace_iteration")] -#[doc(hidden)] -unsafe impl InPlaceIterable for IntoIter { - const EXPAND_BY: Option =3D NonZeroUsize::new(1); - const MERGE_BY: Option =3D NonZeroUsize::new(1); -} - -#[unstable(issue =3D "none", feature =3D "inplace_iteration")] -#[doc(hidden)] -unsafe impl SourceIter for IntoIter { - type Source =3D 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 =3D T; - - fn as_into_iter(&mut self) -> &mut IntoIter { - self - } -} diff --git a/rust/alloc/vec/is_zero.rs b/rust/alloc/vec/is_zero.rs deleted file mode 100644 index d928dcf90e80..000000000000 --- a/rust/alloc/vec/is_zero.rs +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -use core::num::{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) =3D> { - unsafe impl IsZero for $t { - #[inline] - fn is_zero(&self) -> bool { - $is_zero(*self) - } - } - }; -} - -impl_is_zero!(i8, |x| x =3D=3D 0); // It is needed to impl for arrays and = tuples of i8. -impl_is_zero!(i16, |x| x =3D=3D 0); -impl_is_zero!(i32, |x| x =3D=3D 0); -impl_is_zero!(i64, |x| x =3D=3D 0); -impl_is_zero!(i128, |x| x =3D=3D 0); -impl_is_zero!(isize, |x| x =3D=3D 0); - -impl_is_zero!(u8, |x| x =3D=3D 0); // It is needed to impl for arrays and = tuples of u8. -impl_is_zero!(u16, |x| x =3D=3D 0); -impl_is_zero!(u32, |x| x =3D=3D 0); -impl_is_zero!(u64, |x| x =3D=3D 0); -impl_is_zero!(u128, |x| x =3D=3D 0); -impl_is_zero!(usize, |x| x =3D=3D 0); - -impl_is_zero!(bool, |x| x =3D=3D false); -impl_is_zero!(char, |x| x =3D=3D '\0'); - -impl_is_zero!(f32, |x: f32| x.to_bits() =3D=3D 0); -impl_is_zero!(f64, |x: f64| x.to_bits() =3D=3D 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 L= LVM - // fails to const-fold the check in `vec![[1; 32]; n]` - // See https://github.com/rust-lang/rust/pull/97581#issuecomment-1= 166628022 - // Feel free to tweak if you have better evidence. - - N <=3D 16 && self.iter().all(IsZero::is_zero) - } -} - -// This is recursive macro. -macro_rules! impl_for_tuples { - // Stopper - () =3D> { - // No use for implementing for empty tuple because it is ZST. - }; - ($first_arg:ident $(,$rest:ident)*) =3D> { - 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 na= mes. - #[allow(non_snake_case)] - let ($first_arg, $($rest,)*) =3D self; - - $first_arg.is_zero() - $( && $rest.is_zero() )* - } - } - - impl_for_tuples!($($rest),*); - } -} - -impl_for_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 im= pl 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 t= hat -// they're the same size as the corresponding `u32` type, as well as a gua= rantee -// that transmuting between `NonZeroU32` and `Option` wor= ks. -// 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 zero= s. - -macro_rules! impl_is_zero_option_of_nonzero { - ($($t:ident,)+) =3D> {$( - unsafe impl IsZero for Option { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } - } - )+}; -} - -impl_is_zero_option_of_nonzero!( - NonZeroU8, - NonZeroU16, - NonZeroU32, - NonZeroU64, - NonZeroU128, - NonZeroI8, - NonZeroI16, - NonZeroI32, - NonZeroI64, - NonZeroI128, - NonZeroUsize, - NonZeroIsize, -); - -macro_rules! impl_is_zero_option_of_num { - ($($t:ty,)+) =3D> {$( - unsafe impl IsZero for Option<$t> { - #[inline] - fn is_zero(&self) -> bool { - const { - let none: Self =3D unsafe { core::mem::MaybeUninit::ze= roed().assume_init() }; - assert!(none.is_none()); - } - self.is_none() - } - } - )+}; -} - -impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i1= 28, 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_for_optional_bool { - ($($t:ty,)+) =3D> {$( - 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 - // behaviour that options of bools will be one byte with - // no padding, so long as they're nested less than 254 dee= p. - let raw: u8 =3D unsafe { core::mem::transmute(*self) }; - raw =3D=3D 0 - } - } - )+}; -} -impl_for_optional_bool! { - Option, - Option>, - Option>>, - // Could go further, but not worth the metadata overhead -} diff --git a/rust/alloc/vec/mod.rs b/rust/alloc/vec/mod.rs deleted file mode 100644 index 220fb9d6f45b..000000000000 --- a/rust/alloc/vec/mod.rs +++ /dev/null @@ -1,3683 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -//! 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 =3D Vec::new(); -//! ``` -//! -//! ...or by using the [`vec!`] macro: -//! -//! ``` -//! let v: Vec =3D vec![]; -//! -//! let v =3D vec![1, 2, 3, 4, 5]; -//! -//! let v =3D 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 =3D vec![1, 2]; -//! -//! v.push(3); -//! ``` -//! -//! Popping values works in much the same way: -//! -//! ``` -//! let mut v =3D vec![1, 2]; -//! -//! let two =3D v.pop(); -//! ``` -//! -//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] = traits): -//! -//! ``` -//! let mut v =3D vec![1, 2, 3]; -//! let three =3D v[2]; -//! v[1] =3D v[1] + 5; -//! ``` -//! -//! [`push`]: Vec::push - -#![stable(feature =3D "rust1", since =3D "1.0.0")] - -#[cfg(not(no_global_oom_handling))] -use core::cmp; -use core::cmp::Ordering; -use core::fmt; -use core::hash::{Hash, Hasher}; -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}; - -use crate::alloc::{Allocator, Global}; -#[cfg(not(no_borrow))] -use crate::borrow::{Cow, ToOwned}; -use crate::boxed::Box; -use crate::collections::{TryReserveError, TryReserveErrorKind}; -use crate::raw_vec::RawVec; - -#[unstable(feature =3D "extract_if", reason =3D "recently added", issue = =3D "43244")] -pub use self::extract_if::ExtractIf; - -mod extract_if; - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "vec_splice", since =3D "1.21.0")] -pub use self::splice::Splice; - -#[cfg(not(no_global_oom_handling))] -mod splice; - -#[stable(feature =3D "drain", since =3D "1.6.0")] -pub use self::drain::Drain; - -mod drain; - -#[cfg(not(no_borrow))] -#[cfg(not(no_global_oom_handling))] -mod cow; - -#[cfg(not(no_global_oom_handling))] -pub(crate) use self::in_place_collect::AsVecIntoIter; -#[stable(feature =3D "rust1", since =3D "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; - -use self::set_len_on_drop::SetLenOnDrop; - -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; - -use self::spec_extend::TrySpecExtend; - -mod spec_extend; - -/// A contiguous growable array type, written as `Vec`, short for 'vect= or'. -/// -/// # Examples -/// -/// ``` -/// let mut vec =3D 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] =3D 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 =3D vec![1, 2, 3]; -/// vec1.push(4); -/// let vec2 =3D 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 initializati= on -/// in separate steps, especially when initializing a vector of zeros: -/// -/// ``` -/// let vec =3D vec![0; 5]; -/// assert_eq!(vec, [0, 0, 0, 0, 0]); -/// -/// // The following is equivalent, but potentially slower: -/// let mut vec =3D 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 =3D Vec::new(); -/// -/// stack.push(1); -/// stack.push(2); -/// stack.push(3); -/// -/// while let Some(top) =3D 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 =3D 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 =3D 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 object= s. -/// To get a [slice][prim@slice], use [`&`]. Example: -/// -/// ``` -/// fn read_slice(slice: &[usize]) { -/// // ... -/// } -/// -/// let v =3D vec![0, 1]; -/// read_slice(&v); -/// -/// // ... and that's all! -/// // you can also do it like this: -/// let u: &[usize] =3D &v; -/// // or like this: -/// let u: &[_] =3D &v; -/// ``` -/// -/// In Rust, it's more common to pass slices as arguments rather than vect= ors -/// 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 futu= re -/// elements that will be added onto the vector. This is not to be confuse= d 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 capa= city -/// 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. Ho= wever, -/// 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_cap= acity`] -/// whenever possible to specify how big the vector is expected to get. -/// -/// # Guarantees -/// -/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarant= ees -/// 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 `Ve= c`. -/// If additional type parameters are added (e.g., to support custom alloc= ators), -/// 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 thes= e. -/// 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 [`shrin= k_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 i= f and only -/// if [mem::size_of::\]\() * [capacity]\() > 0. In genera= l, `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 bu= ild your -/// own memory-backed collection), be sure to deallocate this memory by us= ing -/// `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), an= d its -/// pointer points to [`len`] initialized, contiguous elements in order (w= hat -/// you would see if you coerced it to a slice), followed by [capaci= ty] - [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 blo= ck. -/// -/// ```text -/// ptr len capacity -/// +--------+--------+--------+ -/// | 0x0123 | 2 | 4 | -/// +--------+--------+--------+ -/// | -/// v -/// Heap +--------+--------+--------+--------+ -/// | 'a' | 'b' | uninit | uninit | -/// +--------+--------+--------+--------+ -/// ``` -/// -/// - **uninit** represents memory that is not initialized, see [`MaybeUni= nit`]. -/// - 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 act= ually -/// stored on the stack for two reasons: -/// -/// * It would make it more difficult for unsafe code to correctly manipul= ate -/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if i= t were -/// only moved, and it would be more difficult to determine if a `Vec` h= ad -/// 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 capaci= ty is -/// sufficient. [`push`] and [`insert`] *will* (re)allocate if -/// [len] =3D=3D [capacity]. That is, the reported capacity i= s completely -/// accurate, and can be relied on. It can even be used to manually free t= he memory -/// allocated by a `Vec` if desired. Bulk insertion methods *may* realloca= te, even -/// when not necessary. -/// -/// `Vec` does not guarantee any particular growth strategy when reallocat= ing -/// when full, nor when [`reserve`] is called. The current strategy is bas= ic -/// and it may prove desirable to use a non-constant growth factor. Whatev= er -/// 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 `V= ec` -/// with exactly the requested capacity. If [len] =3D=3D [capacity]<= /code>, -/// (as is the case for the [`vec!`] macro), then a `Vec` can be conver= ted to -/// and from a [`Box<[T]>`][owned slice] without reallocating or moving th= e 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 `V= ec`, 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 c= onsider -/// 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 capacit= y, -/// and then increasing the length to match, is always valid. -/// -/// Currently, `Vec` does not guarantee the order in which elements are dr= opped. -/// 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 =3D "rust1", since =3D "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item =3D "Vec")] -#[rustc_insignificant_dtor] -pub struct Vec Self { - Vec { buf: RawVec::NEW, len: 0 } - } - - /// Constructs a new, empty `Vec` with at least the specified capac= ity. - /// - /// The vector will be able to hold at least `capacity` elements witho= ut - /// reallocating. This method is allowed to allocate for more elements= than - /// `capacity`. If `capacity` is 0, 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 allo= cation - /// 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 =3D Vec::with_capacity(10); - /// - /// // The vector contains no items, even though it has capacity for m= ore - /// assert_eq!(vec.len(), 0); - /// assert!(vec.capacity() >=3D 10); - /// - /// // These are all done without reallocating... - /// for i in 0..10 { - /// vec.push(i); - /// } - /// assert_eq!(vec.len(), 10); - /// assert!(vec.capacity() >=3D 10); - /// - /// // ...but this may make the vector reallocate - /// vec.push(11); - /// assert_eq!(vec.len(), 11); - /// assert!(vec.capacity() >=3D 11); - /// - /// // A vector of a zero-sized type will always over-allocate, since = no - /// // allocation is necessary - /// let vec_units =3D Vec::<()>::with_capacity(10); - /// assert_eq!(vec_units.capacity(), usize::MAX); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - #[must_use] - pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) - } - - /// Tries to construct a new, empty `Vec` with at least the specifi= ed capacity. - /// - /// The vector will be able to hold at least `capacity` elements witho= ut - /// reallocating. This method is allowed to allocate for more elements= than - /// `capacity`. If `capacity` is 0, 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 allo= cation - /// and the capacity will always be `usize::MAX`. - /// - /// [Capacity and reallocation]: #capacity-and-reallocation - /// [`capacity`]: Vec::capacity - /// - /// # Examples - /// - /// ``` - /// let mut vec =3D Vec::try_with_capacity(10).unwrap(); - /// - /// // The vector contains no items, even though it has capacity for m= ore - /// assert_eq!(vec.len(), 0); - /// assert!(vec.capacity() >=3D 10); - /// - /// // These are all done without reallocating... - /// for i in 0..10 { - /// vec.push(i); - /// } - /// assert_eq!(vec.len(), 10); - /// assert!(vec.capacity() >=3D 10); - /// - /// // ...but this may make the vector reallocate - /// vec.push(11); - /// assert_eq!(vec.len(), 11); - /// assert!(vec.capacity() >=3D 11); - /// - /// let mut result =3D Vec::try_with_capacity(usize::MAX); - /// assert!(result.is_err()); - /// - /// // A vector of a zero-sized type will always over-allocate, since = no - /// // allocation is necessary - /// let vec_units =3D Vec::<()>::try_with_capacity(10).unwrap(); - /// assert_eq!(vec_units.capacity(), usize::MAX); - /// ``` - #[inline] - #[stable(feature =3D "kernel", since =3D "1.0.0")] - pub fn try_with_capacity(capacity: usize) -> Result { - Self::try_with_capacity_in(capacity, Global) - } - - /// Creates a `Vec` directly from a pointer, a capacity, and a leng= th. - /// - /// # 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 align= ment really - /// needs to be equal to satisfy the [`dealloc`] requirement that me= mory 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 allocat= ed 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 al= located - /// via `Vec`. Other allocation sources are allowed if the invarian= ts 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 allocat= ed 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 usi= ng - /// [`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 =3D 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 =3D mem::ManuallyDrop::new(v); - /// - /// // Pull out the various important pieces of information about `v` - /// let p =3D v.as_mut_ptr(); - /// let len =3D v.len(); - /// let cap =3D 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 =3D 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 =3D Layout::array::(16).expect("overflow canno= t happen"); - /// - /// let vec =3D unsafe { - /// let mem =3D 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 =3D "rust1", since =3D "1.0.0")] - pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usi= ze) -> Self { - unsafe { Self::from_raw_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 =3D Vec::new_in(System); - /// ``` - #[inline] - #[unstable(feature =3D "allocator_api", issue =3D "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 ca= pacity - /// with the provided allocator. - /// - /// The vector will be able to hold at least `capacity` elements witho= ut - /// reallocating. This method is allowed to allocate for more elements= than - /// `capacity`. If `capacity` is 0, 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 a= llocation - /// 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 =3D Vec::with_capacity_in(10, System); - /// - /// // The vector contains no items, even though it has capacity for m= ore - /// assert_eq!(vec.len(), 0); - /// assert!(vec.capacity() >=3D 10); - /// - /// // These are all done without reallocating... - /// for i in 0..10 { - /// vec.push(i); - /// } - /// assert_eq!(vec.len(), 10); - /// assert!(vec.capacity() >=3D 10); - /// - /// // ...but this may make the vector reallocate - /// vec.push(11); - /// assert_eq!(vec.len(), 11); - /// assert!(vec.capacity() >=3D 11); - /// - /// // A vector of a zero-sized type will always over-allocate, since = no - /// // allocation is necessary - /// let vec_units =3D Vec::<(), System>::with_capacity_in(10, System); - /// assert_eq!(vec_units.capacity(), usize::MAX); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } - } - - /// Tries to construct a new, empty `Vec` with at least the spec= ified capacity - /// with the provided allocator. - /// - /// The vector will be able to hold at least `capacity` elements witho= ut - /// reallocating. This method is allowed to allocate for more elements= than - /// `capacity`. If `capacity` is 0, 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 a= llocation - /// and the capacity will always be `usize::MAX`. - /// - /// [Capacity and reallocation]: #capacity-and-reallocation - /// [`capacity`]: Vec::capacity - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api)] - /// - /// use std::alloc::System; - /// - /// let mut vec =3D Vec::try_with_capacity_in(10, System).unwrap(); - /// - /// // The vector contains no items, even though it has capacity for m= ore - /// assert_eq!(vec.len(), 0); - /// assert!(vec.capacity() >=3D 10); - /// - /// // These are all done without reallocating... - /// for i in 0..10 { - /// vec.push(i); - /// } - /// assert_eq!(vec.len(), 10); - /// assert!(vec.capacity() >=3D 10); - /// - /// // ...but this may make the vector reallocate - /// vec.push(11); - /// assert_eq!(vec.len(), 11); - /// assert!(vec.capacity() >=3D 11); - /// - /// let mut result =3D Vec::try_with_capacity_in(usize::MAX, System); - /// assert!(result.is_err()); - /// - /// // A vector of a zero-sized type will always over-allocate, since = no - /// // allocation is necessary - /// let vec_units =3D Vec::<(), System>::try_with_capacity_in(10, Syst= em).unwrap(); - /// assert_eq!(vec_units.capacity(), usize::MAX); - /// ``` - #[inline] - #[stable(feature =3D "kernel", since =3D "1.0.0")] - 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 capacity, a lengt= h, - /// 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 `a= lloc`. - /// * `T` needs to have the same alignment as what `ptr` was allocated= with. - /// (`T` having a less strict alignment is not sufficient, the align= ment really - /// needs to be equal to satisfy the [`dealloc`] requirement that me= mory 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 al= located - /// via `Vec`. Other allocation sources are allowed if the invar= iants 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 lengt= h `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-allocat= ed-memory - /// [*fit*]: crate::alloc::Allocator#memory-fitting - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api)] - /// - /// use std::alloc::System; - /// - /// use std::ptr; - /// use std::mem; - /// - /// let mut v =3D 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 =3D mem::ManuallyDrop::new(v); - /// - /// // Pull out the various important pieces of information about `v` - /// let p =3D v.as_mut_ptr(); - /// let len =3D v.len(); - /// let cap =3D v.capacity(); - /// let alloc =3D 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 =3D Vec::from_raw_parts_in(p, len, cap, alloc.clon= e()); - /// 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 =3D Layout::array::(16).expect("overflow canno= t happen"); - /// - /// let vec =3D unsafe { - /// let mem =3D match Global.allocate(layout) { - /// Ok(mem) =3D> mem.cast::().as_ptr(), - /// Err(AllocError) =3D> 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 =3D "allocator_api", issue =3D "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 } } - } - - /// Decomposes a `Vec` into its raw components. - /// - /// 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 =3D vec![-1, 0, 1]; - /// - /// let (ptr, len, cap) =3D v.into_raw_parts(); - /// - /// let rebuilt =3D unsafe { - /// // We can now make changes to the components, such as - /// // transmuting the raw pointer to a compatible type. - /// let ptr =3D ptr as *mut u32; - /// - /// Vec::from_raw_parts(ptr, len, cap) - /// }; - /// assert_eq!(rebuilt, [4294967295, 0, 1]); - /// ``` - #[unstable(feature =3D "vec_into_raw_parts", reason =3D "new API", iss= ue =3D "65816")] - pub fn into_raw_parts(self) -> (*mut T, usize, usize) { - let mut me =3D ManuallyDrop::new(self); - (me.as_mut_ptr(), me.len(), me.capacity()) - } - - /// Decomposes a `Vec` into its raw components. - /// - /// 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 allocato= r. These are the same - /// arguments in the same order as the arguments to [`from_raw_parts_i= n`]. - /// - /// 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 =3D Vec::new_in(System); - /// v.push(-1); - /// v.push(0); - /// v.push(1); - /// - /// let (ptr, len, cap, alloc) =3D v.into_raw_parts_with_alloc(); - /// - /// let rebuilt =3D unsafe { - /// // We can now make changes to the components, such as - /// // transmuting the raw pointer to a compatible type. - /// let ptr =3D ptr as *mut u32; - /// - /// Vec::from_raw_parts_in(ptr, len, cap, alloc) - /// }; - /// assert_eq!(rebuilt, [4294967295, 0, 1]); - /// ``` - #[unstable(feature =3D "allocator_api", issue =3D "32838")] - // #[unstable(feature =3D "vec_into_raw_parts", reason =3D "new API", = issue =3D "65816")] - pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { - let mut me =3D ManuallyDrop::new(self); - let len =3D me.len(); - let capacity =3D me.capacity(); - let ptr =3D me.as_mut_ptr(); - let alloc =3D unsafe { ptr::read(me.allocator()) }; - (ptr, len, capacity, alloc) - } - - /// Returns the total number of elements the vector can hold without - /// reallocating. - /// - /// # Examples - /// - /// ``` - /// let mut vec: Vec =3D Vec::with_capacity(10); - /// vec.push(42); - /// assert!(vec.capacity() >=3D 10); - /// ``` - #[inline] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn capacity(&self) -> usize { - self.buf.capacity() - } - - /// Reserves capacity for at least `additional` more elements to be in= serted - /// 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 =3D vec![1]; - /// vec.reserve(10); - /// assert!(vec.capacity() >=3D 11); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn reserve(&mut self, additional: usize) { - self.buf.reserve(self.len, additional); - } - - /// Reserves the minimum capacity for at least `additional` more eleme= nts to - /// be inserted in the given `Vec`. Unlike [`reserve`], this will n= ot - /// deliberately over-allocate to speculatively avoid frequent allocat= ions. - /// After calling `reserve_exact`, capacity will be greater than or eq= ual 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 precise= ly - /// 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 =3D vec![1]; - /// vec.reserve_exact(10); - /// assert!(vec.capacity() >=3D 11); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - 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 sp= eculatively 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 met= hod - /// preserves the contents even if an error occurs. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, the= n an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use std::collections::TryReserveError; - /// - /// fn process_data(data: &[u32]) -> Result, TryReserveError>= { - /// let mut output =3D 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 =3D "try_reserve", since =3D "1.57.0")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryRese= rveError> { - 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_reserv= e`], - /// this will not deliberately over-allocate to speculatively avoid fr= equent - /// allocations. After calling `try_reserve_exact`, capacity will be g= reater - /// 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 precise= ly - /// 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, the= n an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use std::collections::TryReserveError; - /// - /// fn process_data(data: &[u32]) -> Result, TryReserveError>= { - /// let mut output =3D 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 =3D "try_reserve", since =3D "1.57.0")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), T= ryReserveError> { - self.buf.try_reserve_exact(self.len, additional) - } - - /// Shrinks the capacity of the vector as much as possible. - /// - /// It will drop down as close as possible to the length but the alloc= ator - /// may still inform the vector that there is space for a few more ele= ments. - /// - /// # Examples - /// - /// ``` - /// let mut vec =3D Vec::with_capacity(10); - /// vec.extend([1, 2, 3]); - /// assert!(vec.capacity() >=3D 10); - /// vec.shrink_to_fit(); - /// assert!(vec.capacity() >=3D 3); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - 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::shri= nk_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 =3D Vec::with_capacity(10); - /// vec.extend([1, 2, 3]); - /// assert!(vec.capacity() >=3D 10); - /// vec.shrink_to(4); - /// assert!(vec.capacity() >=3D 4); - /// vec.shrink_to(0); - /// assert!(vec.capacity() >=3D 3); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "shrink_to", since =3D "1.56.0")] - 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]. - /// - /// If the vector has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. - /// - /// [owned slice]: Box - /// - /// # Examples - /// - /// ``` - /// let v =3D vec![1, 2, 3]; - /// - /// let slice =3D v.into_boxed_slice(); - /// ``` - /// - /// Any excess capacity is removed: - /// - /// ``` - /// let mut vec =3D Vec::with_capacity(10); - /// vec.extend([1, 2, 3]); - /// - /// assert!(vec.capacity() >=3D 10); - /// let slice =3D vec.into_boxed_slice(); - /// assert_eq!(slice.into_vec().capacity(), 3); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn into_boxed_slice(mut self) -> Box<[T], A> { - unsafe { - self.shrink_to_fit(); - let me =3D ManuallyDrop::new(self); - let buf =3D ptr::read(&me.buf); - let len =3D 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 =3D 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 curre= nt - /// length: - /// - /// ``` - /// let mut vec =3D vec![1, 2, 3]; - /// vec.truncate(8); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - /// - /// Truncating when `len =3D=3D 0` is equivalent to calling the [`clea= r`] - /// method. - /// - /// ``` - /// let mut vec =3D vec![1, 2, 3]; - /// vec.truncate(0); - /// assert_eq!(vec, []); - /// ``` - /// - /// [`clear`]: Vec::clear - /// [`drain`]: Vec::drain - #[stable(feature =3D "rust1", since =3D "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_pla= ce`, - // such that no value will be dropped twice in case `drop_in_pla= ce` - // were to panic once (if it panics twice, the program aborts). - unsafe { - // Note: It's intentional that this is `>` and not `>=3D`. - // Changing it to `>=3D` has negative performance - // implications in some cases. See #78884 for more. - if len > self.len { - return; - } - let remaining_len =3D self.len - len; - let s =3D ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(= len), remaining_len); - self.len =3D len; - ptr::drop_in_place(s); - } - } - - /// Extracts a slice containing the entire vector. - /// - /// Equivalent to `&s[..]`. - /// - /// # Examples - /// - /// ``` - /// use std::io::{self, Write}; - /// let buffer =3D vec![1, 2, 3, 5, 8]; - /// io::sink().write(buffer.as_slice()).unwrap(); - /// ``` - #[inline] - #[stable(feature =3D "vec_as_slice", since =3D "1.7.0")] - pub fn as_slice(&self) -> &[T] { - self - } - - /// Extracts a mutable slice of the entire vector. - /// - /// Equivalent to `&mut s[..]`. - /// - /// # Examples - /// - /// ``` - /// use std::io::{self, Read}; - /// let mut buffer =3D vec![0; 3]; - /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap(); - /// ``` - #[inline] - #[stable(feature =3D "vec_as_slice", since =3D "1.7.0")] - pub fn as_mut_slice(&mut self) -> &mut [T] { - self - } - - /// Returns a raw pointer to the vector's buffer, or a dangling raw po= inter - /// 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 pointing to garbage. - /// 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-trans= itively) points to - /// is never written to (except inside an `UnsafeCell`) using this poi= nter 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`] and [`= as_mut_ptr`]. - /// Note that calling other methods that materialize mutable reference= s to the slice, - /// or mutable references to specific elements you are planning on acc= essing through this pointer, - /// as well as writing to those elements, may still invalidate this po= inter. - /// See the second example below for how this guarantee can be used. - /// - /// - /// # Examples - /// - /// ``` - /// let x =3D vec![1, 2, 4]; - /// let x_ptr =3D 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 =3D vec![0, 1, 2]; - /// let ptr1 =3D v.as_ptr(); - /// let _ =3D ptr1.read(); - /// let ptr2 =3D 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 _ =3D ptr1.read(); - /// } - /// ``` - /// - /// [`as_mut_ptr`]: Vec::as_mut_ptr - /// [`as_ptr`]: Vec::as_ptr - #[stable(feature =3D "vec_as_ptr", since =3D "1.37.0")] - #[rustc_never_returns_null_ptr] - #[inline] - pub fn as_ptr(&self) -> *const T { - // We shadow the slice method of the same name to avoid going thro= ugh - // `deref`, which creates an intermediate reference. - self.buf.ptr() - } - - /// Returns an unsafe mutable pointer to the vector's buffer, or a dan= gling - /// raw pointer valid for zero sized reads if the vector didn't alloca= te. - /// - /// The caller must ensure that the vector outlives the pointer this - /// function returns, or else it will end up pointing to garbage. - /// 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`] and [`= as_mut_ptr`]. - /// Note that calling other methods that materialize references to the= slice, - /// or references to specific elements you are planning on accessing t= hrough 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 =3D 4; - /// let mut x: Vec =3D Vec::with_capacity(size); - /// let x_ptr =3D x.as_mut_ptr(); - /// - /// // Initialize elements via raw pointer writes, then set length. - /// unsafe { - /// for i in 0..size { - /// *x_ptr.add(i) =3D 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 =3D vec![0]; - /// let ptr1 =3D v.as_mut_ptr(); - /// ptr1.write(1); - /// let ptr2 =3D 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 - #[stable(feature =3D "vec_as_ptr", since =3D "1.37.0")] - #[rustc_never_returns_null_ptr] - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { - // We shadow the slice method of the same name to avoid going thro= ugh - // `deref_mut`, which creates an intermediate reference. - self.buf.ptr() - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature =3D "allocator_api", issue =3D "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 =3D 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 =3D Vec::with_capacity(32_768); - /// let mut dict_length =3D 0; - /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it hold= s that: - /// // 1. `dict_length` elements were initialized. - /// // 2. `dict_length` <=3D the capacity (32_768) - /// // which makes `set_len` safe to call. - /// unsafe { - /// // Make the FFI call... - /// let r =3D deflateGetDictionary(self.strm, dict.as_mut_ptr(= ), &mut dict_length); - /// if r =3D=3D 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 =3D 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 <=3D capacity` always holds whatever `capacity` is. - /// unsafe { - /// vec.set_len(0); - /// } - /// ``` - /// - /// Normally, here, one would use [`clear`] instead to correctly drop - /// the contents and thus not leak memory. - #[inline] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub unsafe fn set_len(&mut self, new_len: usize) { - debug_assert!(new_len <=3D self.capacity()); - - self.len =3D 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, 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 =3D 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 =3D "rust1", since =3D "1.0.0")] - pub fn swap_remove(&mut self, index: usize) -> T { - #[cold] - #[cfg_attr(not(feature =3D "panic_immediate_abort"), inline(never)= )] - #[track_caller] - fn assert_failed(index: usize, len: usize) -> ! { - panic!("swap_remove index (is {index}) should be < len (is {le= n})"); - } - - let len =3D self.len(); - if index >=3D 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 (w= hich - // can be self[index] itself). - let value =3D ptr::read(self.as_ptr().add(index)); - let base_ptr =3D 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 =3D 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]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn insert(&mut self, index: usize, element: T) { - #[cold] - #[cfg_attr(not(feature =3D "panic_immediate_abort"), inline(never)= )] - #[track_caller] - fn assert_failed(index: usize, len: usize) -> ! { - panic!("insertion index (is {index}) should be <=3D len (is {l= en})"); - } - - let len =3D self.len(); - - // space for the new element - if len =3D=3D self.buf.capacity() { - self.reserve(1); - } - - unsafe { - // infallible - // The spot to put the new value - { - let p =3D self.as_mut_ptr().add(index); - if index < len { - // Shift everything over to make space. (Duplicating t= he - // `index`th element into two consecutive places.) - ptr::copy(p, p.add(1), len - index); - } else if index =3D=3D len { - // No elements need shifting. - } else { - assert_failed(index, len); - } - // 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 vec= tor, - /// 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 rem= ove - /// 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 =3D vec![1, 2, 3]; - /// assert_eq!(v.remove(1), 2); - /// assert_eq!(v, [1, 3]); - /// ``` - #[stable(feature =3D "rust1", since =3D "1.0.0")] - #[track_caller] - pub fn remove(&mut self, index: usize) -> T { - #[cold] - #[cfg_attr(not(feature =3D "panic_immediate_abort"), inline(never)= )] - #[track_caller] - fn assert_failed(index: usize, len: usize) -> ! { - panic!("removal index (is {index}) should be < len (is {len})"= ); - } - - let len =3D self.len(); - if index >=3D len { - assert_failed(index, len); - } - unsafe { - // infallible - let ret; - { - // the place we are taking from. - let ptr =3D 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 =3D 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 =3D vec![1, 2, 3, 4]; - /// vec.retain(|&x| x % 2 =3D=3D 0); - /// assert_eq!(vec, [2, 4]); - /// ``` - /// - /// Because the elements are visited exactly once in the original orde= r, - /// external state may be used to decide which elements to keep. - /// - /// ``` - /// let mut vec =3D vec![1, 2, 3, 4, 5]; - /// let keep =3D [false, true, true, false, true]; - /// let mut iter =3D keep.iter(); - /// vec.retain(|_| *iter.next().unwrap()); - /// assert_eq!(vec, [2, 3, 5]); - /// ``` - #[stable(feature =3D "rust1", since =3D "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 mu= table reference to it. - /// - /// In other words, remove all elements `e` such that `f(&mut e)` retu= rns `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 =3D vec![1, 2, 3, 4]; - /// vec.retain_mut(|x| if *x <=3D 3 { - /// *x +=3D 1; - /// true - /// } else { - /// false - /// }); - /// assert_eq!(vec, [2, 3, 4]); - /// ``` - #[stable(feature =3D "vec_retain_mut", since =3D "1.61.0")] - pub fn retain_mut(&mut self, mut f: F) - where - F: FnMut(&mut T) -> bool, - { - let original_len =3D self.len(); - // 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 ele= ment panicked. - // It shifts unchecked elements to cover holes and `set_len` to th= e correct length. - // In cases when predicate and `drop` never panick, it will be opt= imized 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 sinc= e we never touch them. - unsafe { - ptr::copy( - self.v.as_ptr().add(self.processed_len), - self.v.as_mut_ptr().add(self.processed_len - s= elf.deleted_cnt), - self.original_len - self.processed_len, - ); - } - } - // SAFETY: After filling holes, all items are in contiguou= s memory. - unsafe { - self.v.set_len(self.original_len - self.deleted_cnt); - } - } - } - - let mut g =3D 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 !=3D original_len { - // SAFETY: Unchecked element must be valid. - let cur =3D unsafe { &mut *g.v.as_mut_ptr().add(g.processe= d_len) }; - if !f(cur) { - // Advance early to avoid double drop if `drop_in_plac= e` panicked. - g.processed_len +=3D 1; - g.deleted_cnt +=3D 1; - // SAFETY: We never touch this element again after dro= pped. - 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 no= t overlap with current element. - // We use copy for move, and never touch this element = again. - unsafe { - let hole_slot =3D g.v.as_mut_ptr().add(g.processed= _len - g.deleted_cnt); - ptr::copy_nonoverlapping(cur, hole_slot, 1); - } - } - g.processed_len +=3D 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 L= LVM. - drop(g); - } - - /// Removes all but the first of consecutive elements in the vector th= at resolve to the same - /// key. - /// - /// If the vector is sorted, this removes all duplicates. - /// - /// # Examples - /// - /// ``` - /// let mut vec =3D vec![10, 20, 21, 30, 20]; - /// - /// vec.dedup_by_key(|i| *i / 10); - /// - /// assert_eq!(vec, [10, 20, 30, 20]); - /// ``` - #[stable(feature =3D "dedup_by", since =3D "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) =3D=3D key(b)) - } - - /// Removes all but the first of consecutive elements in the vector sa= tisfying a given equality - /// relation. - /// - /// The `same_bucket` function is passed references to two elements fr= om the vector and - /// must determine if the elements compare equal. The elements are pas= sed 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 =3D 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 =3D "dedup_by", since =3D "1.16.0")] - pub fn dedup_by(&mut self, mut same_bucket: F) - where - F: FnMut(&mut T, &mut T) -> bool, - { - let len =3D self.len(); - if len <=3D 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 anythin= g. - let mut first_duplicate_idx: usize =3D 1; - let start =3D self.as_mut_ptr(); - while first_duplicate_idx !=3D len { - let found_duplicate =3D unsafe { - // SAFETY: first_duplicate always in range [1..len) - // Note that we start iteration from 1 so we never overflo= w. - let prev =3D start.add(first_duplicate_idx.wrapping_sub(1)= ); - let current =3D 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 +=3D 1; - } - // Don't need to remove anything. - // We cannot get bigger than len. - if first_duplicate_idx =3D=3D len { - return; - } - - /* INVARIANT: vec.len() > read > write > write-1 >=3D 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` panicke= d */ - 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 al= ways - * in-bounds. */ - unsafe { - let ptr =3D self.vec.as_mut_ptr(); - let len =3D self.vec.len(); - - /* How many items were left when `same_bucket` panicke= d. - * Basically vec[read..].len() */ - let items_left =3D len.wrapping_sub(self.read); - - /* Pointer to first item in vec[write..write+items_lef= t] slice */ - let dropped_ptr =3D ptr.add(self.write); - /* Pointer to first item in vec[read..] slice */ - let valid_ptr =3D ptr.add(self.read); - - /* Copy `vec[read..]` to `vec[write..write+items_left]= `. - * The slices can overlap, so `copy_nonoverlapping` ca= nnot be used */ - ptr::copy(valid_ptr, dropped_ptr, items_left); - - /* How many items have been already dropped - * Basically vec[read..write].len() */ - let dropped =3D 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 corrupti= on if `T::drop` panics. - let mut gap =3D - FillGapOnDrop { read: first_duplicate_idx + 1, write: first_du= plicate_idx, vec: self }; - unsafe { - // SAFETY: we checked that first_duplicate_idx in bounds befor= e. - // 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 =3D start.add(gap.read); - let prev_ptr =3D start.add(gap.write.wrapping_sub(1)); - - // We explicitly say in docs that references are reversed. - let found_duplicate =3D same_bucket(&mut *read_ptr, &mut *= prev_ptr); - if found_duplicate { - // Increase `gap.read` now since the drop may panic. - gap.read +=3D 1; - /* We have found duplicate, drop it in-place */ - ptr::drop_in_place(read_ptr); - } else { - let write_ptr =3D start.add(gap.write); - - /* read_ptr cannot be equal to write_ptr because at th= is 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 +=3D 1; - gap.read +=3D 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 =3D vec![1, 2]; - /// vec.push(3); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn push(&mut self, value: T) { - // This will panic or abort if we would allocate > isize::MAX bytes - // or if the length increment would overflow for zero-sized types. - if self.len =3D=3D self.buf.capacity() { - self.buf.reserve_for_push(self.len); - } - unsafe { - let end =3D self.as_mut_ptr().add(self.len); - ptr::write(end, value); - self.len +=3D 1; - } - } - - /// Tries to append an element to the back of a collection. - /// - /// # Examples - /// - /// ``` - /// let mut vec =3D vec![1, 2]; - /// vec.try_push(3).unwrap(); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - #[inline] - #[stable(feature =3D "kernel", since =3D "1.0.0")] - pub fn try_push(&mut self, value: T) -> Result<(), TryReserveError> { - if self.len =3D=3D self.buf.capacity() { - self.buf.try_reserve_for_push(self.len)?; - } - unsafe { - let end =3D self.as_mut_ptr().add(self.len); - ptr::write(end, value); - self.len +=3D 1; - } - Ok(()) - } - - /// Appends an element if there is sufficient spare capacity, otherwis= e an error is returned - /// with the element. - /// - /// Unlike [`push`] this method will not reallocate when there's insuf= ficient capacity. - /// The caller should use [`reserve`] or [`try_reserve`] to ensure tha= t 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<= Vec, TryReserveError> { - /// let mut vec =3D Vec::new(); - /// for value in iter { - /// if let Err(value) =3D 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 _ =3D vec.push_within_capacity(value); - /// } - /// } - /// Ok(vec) - /// } - /// assert_eq!(from_iter_fallible(0..100), Ok(Vec::from_iter(0..100))); - /// ``` - #[inline] - #[unstable(feature =3D "vec_push_within_capacity", issue =3D "100486")] - pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> { - if self.len =3D=3D self.buf.capacity() { - return Err(value); - } - unsafe { - let end =3D self.as_mut_ptr().add(self.len); - ptr::write(end, value); - self.len +=3D 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 =3D vec![1, 2, 3]; - /// assert_eq!(vec.pop(), Some(3)); - /// assert_eq!(vec, [1, 2]); - /// ``` - #[inline] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn pop(&mut self) -> Option { - if self.len =3D=3D 0 { - None - } else { - unsafe { - self.len -=3D 1; - core::intrinsics::assume(self.len < self.capacity()); - Some(ptr::read(self.as_ptr().add(self.len()))) - } - } - } - - /// Moves all the elements of `other` into `self`, leaving `other` emp= ty. - /// - /// # Panics - /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. - /// - /// # Examples - /// - /// ``` - /// let mut vec =3D vec![1, 2, 3]; - /// let mut vec2 =3D 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 =3D "append", since =3D "1.4.0")] - 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] - unsafe fn append_elements(&mut self, other: *const [T]) { - let count =3D unsafe { (*other).len() }; - self.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; - } - - /// 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. - /// - /// The returned iterator keeps a mutable borrow on the vector to opti= mize - /// 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 =3D vec![1, 2, 3]; - /// let u: Vec<_> =3D 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 =3D "drain", since =3D "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 e= lements - // are accessible at all if the Drain's destructor never gets to r= un. - // - // 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 =3D self.len(); - let Range { start, end } =3D 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 =3D slice::from_raw_parts(self.as_ptr().add(st= art), 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 =3D vec![1, 2, 3]; - /// - /// v.clear(); - /// - /// assert!(v.is_empty()); - /// ``` - #[inline] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn clear(&mut self) { - let elems: *mut [T] =3D self.as_mut_slice(); - - // SAFETY: - // - `elems` comes directly from `as_mut_slice` and is therefore v= alid. - // - 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 drop= ping - // some twice. - unsafe { - self.len =3D 0; - ptr::drop_in_place(elems); - } - } - - /// Returns the number of elements in the vector, also referred to - /// as its 'length'. - /// - /// # Examples - /// - /// ``` - /// let a =3D vec![1, 2, 3]; - /// assert_eq!(a.len(), 3); - /// ``` - #[inline] - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn len(&self) -> usize { - self.len - } - - /// Returns `true` if the vector contains no elements. - /// - /// # Examples - /// - /// ``` - /// let mut v =3D Vec::new(); - /// assert!(v.is_empty()); - /// - /// v.push(1); - /// assert!(!v.is_empty()); - /// ``` - #[stable(feature =3D "rust1", since =3D "1.0.0")] - pub fn is_empty(&self) -> bool { - self.len() =3D=3D 0 - } - - /// Splits the collection into two at the given index. - /// - /// Returns a newly allocated vector containing the elements in the ra= nge - /// `[at, len)`. After the call, the original vector will be left cont= aining - /// the elements `[0, at)` with its previous capacity unchanged. - /// - /// # Panics - /// - /// Panics if `at > len`. - /// - /// # Examples - /// - /// ``` - /// let mut vec =3D vec![1, 2, 3]; - /// let vec2 =3D vec.split_off(1); - /// assert_eq!(vec, [1]); - /// assert_eq!(vec2, [2, 3]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[must_use =3D "use `.truncate()` if you don't need the other half"] - #[stable(feature =3D "split_off", since =3D "1.4.0")] - pub fn split_off(&mut self, at: usize) -> Self - where - A: Clone, - { - #[cold] - #[cfg_attr(not(feature =3D "panic_immediate_abort"), inline(never)= )] - #[track_caller] - fn assert_failed(at: usize, len: usize) -> ! { - panic!("`at` split index (is {at}) should be <=3D len (is {len= })"); - } - - if at > self.len() { - assert_failed(at, self.len()); - } - - if at =3D=3D 0 { - // the new vector can take over the original buffer and avoid = the copy - return mem::replace( - self, - Vec::with_capacity_in(self.capacity(), self.allocator().cl= one()), - ); - } - - let other_len =3D self.len - at; - let mut other =3D 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_p= tr(), 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 =3D vec![1, 2, 3]; - /// vec.resize_with(5, Default::default); - /// assert_eq!(vec, [1, 2, 3, 0, 0]); - /// - /// let mut vec =3D vec![]; - /// let mut p =3D 1; - /// vec.resize_with(4, || { p *=3D 2; p }); - /// assert_eq!(vec, [2, 4, 8, 16]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "vec_resize_with", since =3D "1.33.0")] - pub fn resize_with(&mut self, new_len: usize, f: F) - where - F: FnMut() -> T, - { - let len =3D 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 life= time - /// `'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 `Ve= c`, - /// so the leaked allocation may include unused capacity that is not p= art - /// of the returned slice. - /// - /// This function is mainly useful for data that lives for the remaind= er of - /// the program's life. Dropping the returned reference will cause a m= emory - /// leak. - /// - /// # Examples - /// - /// Simple usage: - /// - /// ``` - /// let x =3D vec![1, 2, 3]; - /// let static_ref: &'static mut [usize] =3D x.leak(); - /// static_ref[0] +=3D 1; - /// assert_eq!(static_ref, &[2, 2, 3]); - /// ``` - #[stable(feature =3D "vec_leak", since =3D "1.47.0")] - #[inline] - pub fn leak<'a>(self) -> &'a mut [T] - where - A: 'a, - { - let mut me =3D 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 =3D Vec::with_capacity(10); - /// - /// // Fill in the first 3 elements. - /// let uninit =3D 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 =3D "vec_spare_capacity", since =3D "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 w= ith data - /// (e.g. by reading from a file) before marking the data as initializ= ed 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 =3D vec![1, 1, 2]; - /// - /// // Reserve additional space big enough for 10 elements. - /// v.reserve(10); - /// - /// let (init, uninit) =3D v.split_at_spare_mut(); - /// let sum =3D 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 =3D v.len(); - /// v.set_len(len + 4); - /// } - /// - /// assert_eq!(&v, &[1, 1, 2, 4, 8, 12, 16]); - /// ``` - #[unstable(feature =3D "vec_split_at_spare", issue =3D "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, _) =3D unsafe { self.split_at_spare_mut_with_len= () }; - (init, spare) - } - - /// Safety: changing returned .2 (&mut usize) is considered the same a= s calling `.set_len(_)`. - /// - /// This method provides unique access to all vec parts at once in `ex= tend_from_within`. - unsafe fn split_at_spare_mut_with_len( - &mut self, - ) -> (&mut [T], &mut [MaybeUninit], &mut usize) { - let ptr =3D self.as_mut_ptr(); - // SAFETY: - // - `ptr` is guaranteed to be valid for `self.len` elements - // - but the allocation extends out to `self.buf.capacity()` eleme= nts, possibly - // uninitialized - let spare_ptr =3D unsafe { ptr.add(self.len) }; - let spare_ptr =3D spare_ptr.cast::>(); - let spare_len =3D 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 do= esn't overlap with `initialized` - unsafe { - let initialized =3D slice::from_raw_parts_mut(ptr, self.len); - let spare =3D 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`] 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.resize(3, "world"); - /// assert_eq!(vec, ["hello", "world", "world"]); - /// - /// let mut vec =3D vec![1, 2, 3, 4]; - /// vec.resize(2, 0); - /// assert_eq!(vec, [1, 2]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "vec_resize", since =3D "1.5.0")] - pub fn resize(&mut self, new_len: usize, value: T) { - let len =3D self.len(); - - if new_len > len { - self.extend_with(new_len - len, value) - } else { - self.truncate(new_len); - } - } - - /// 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, 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 - /// 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.extend_from_slice(&[2, 3, 4]); - /// assert_eq!(vec, [1, 2, 3, 4]); - /// ``` - /// - /// [`extend`]: Vec::extend - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "vec_extend_from_slice", since =3D "1.6.0")] - pub fn extend_from_slice(&mut self, other: &[T]) { - self.spec_extend(other.iter()) - } - - /// 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 - /// - /// 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 vec =3D vec![0, 1, 2, 3, 4]; - /// - /// vec.extend_from_within(2..); - /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]); - /// - /// vec.extend_from_within(..2); - /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]); - /// - /// vec.extend_from_within(4..8); - /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature =3D "vec_extend_from_within", since =3D "1.53.0")] - pub fn extend_from_within(&mut self, src: R) - where - R: RangeBounds, - { - let range =3D slice::range(src, ..self.len()); - self.reserve(range.len()); - - // SAFETY: - // - `slice::range` guarantees that the given range is valid for i= ndexing 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 `usi= ze`. - /// - /// This is only possible when flattening a vector of arrays of zero-s= ized - /// types, and thus tends to be irrelevant in practice. If - /// `size_of::() > 0`, this will never panic. - /// - /// # Examples - /// - /// ``` - /// #![feature(slice_flatten)] - /// - /// let mut vec =3D vec![[1, 2, 3], [4, 5, 6], [7, 8, 9]]; - /// assert_eq!(vec.pop(), Some([7, 8, 9])); - /// - /// let mut flattened =3D vec.into_flattened(); - /// assert_eq!(flattened.pop(), Some(6)); - /// ``` - #[unstable(feature =3D "slice_flatten", issue =3D "95629")] - pub fn into_flattened(self) -> Vec { - let (ptr, len, cap, alloc) =3D self.into_raw_parts_with_alloc(); - let (new_len, new_cap) =3D if T::IS_ZST { - (len.checked_mul(N).expect("vec len overflow"), usize::MAX) - } else { - // SAFETY: - // - `cap * N` cannot overflow because the allocation is alrea= dy 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::()` =3D=3D `cap * size_of::<[T; N]>()` - // - `len` <=3D `cap`, so `len * N` <=3D `cap * N`. - unsafe { Vec::::from_raw_parts_in(ptr.cast(), new_len, new_c= ap, alloc) } - } -} - -impl Vec { - #[cfg(not(no_global_oom_handling))] - /// Extend the vector by `n` clones of value. - fn extend_with(&mut self, n: usize, value: T) { - self.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.clone()); - ptr =3D ptr.add(1); - // Increment the length in every step in case clone() pani= cs - 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 - } - } - - /// Try to extend the vector by `n` clones of value. - fn try_extend_with(&mut self, n: usize, value: T) -> Result<(), TryRes= erveError> { - 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.clone()); - ptr =3D ptr.add(1); - // Increment the length in every step in case clone() pani= cs - 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 - Ok(()) - } - } -} - -impl Vec { - /// Removes consecutive repeated elements in the vector according to t= he - /// [`PartialEq`] trait implementation. - /// - /// If the vector is sorted, this removes all duplicates. - /// - /// # Examples - /// - /// ``` - /// let mut vec =3D vec![1, 2, 2, 3, 2]; - /// - /// vec.dedup(); - /// - /// assert_eq!(vec, [1, 2, 3, 2]); - /// ``` - #[stable(feature =3D "rust1", since =3D "1.0.0")] - #[inline] - pub fn dedup(&mut self) { - self.dedup_by(|a, b| a =3D=3D b) - } -} - -//////////////////////////////////////////////////////////////////////////= ////// -// Internal methods and functions -//////////////////////////////////////////////////////////////////////////= ////// - -#[doc(hidden)] -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -pub fn from_elem(elem: T, n: usize) -> Vec { - ::from_elem(elem, n, Global) -} - -#[doc(hidden)] -#[cfg(not(no_global_oom_handling))] -#[unstable(feature =3D "allocator_api", issue =3D "32838")] -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 `>=3D 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) =3D unsafe { self.split_at_spare_mut_with_l= en() }; - - // SAFETY: - // - caller guarantees that src is a valid index - let to_clone =3D 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`, s= o it's ok to increase len - // - len is increased after each element to prevent leaks (see= issue #82533) - .for_each(|_| *len +=3D 1); - } -} - -#[cfg(not(no_global_oom_handling))] -impl ExtendFromWithinSpec for Vec { - unsafe fn spec_extend_from_within(&mut self, src: Range) { - let count =3D src.len(); - { - let (init, spare) =3D self.split_at_spare_mut(); - - // SAFETY: - // - caller guarantees that `src` is a valid index - let source =3D 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 val= id for - // `count` reads - // - `.reserve(count)` guarantees that `spare.len() >=3D count= ` so spare - // is valid for `count` writes - unsafe { ptr::copy_nonoverlapping(source.as_ptr(), spare.as_mu= t_ptr() as _, count) }; - } - - // SAFETY: - // - The elements were just initialized by `copy_nonoverlapping` - self.len +=3D count; - } -} - -//////////////////////////////////////////////////////////////////////////= ////// -// Common trait implementations for Vec -//////////////////////////////////////////////////////////////////////////= ////// - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl ops::Deref for Vec { - type Target =3D [T]; - - #[inline] - fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl ops::DerefMut for Vec { - #[inline] - fn deref_mut(&mut self) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Clone for Vec { - #[cfg(not(test))] - fn clone(&self) -> Self { - let alloc =3D self.allocator().clone(); - <[T]>::to_vec_in(&**self, alloc) - } - - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, wh= ich 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 =3D self.allocator().clone(); - crate::slice::to_vec(&**self, alloc) - } - - fn clone_from(&mut self, other: &Self) { - crate::slice::SpecCloneIntoVec::clone_into(other.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 =3D std::hash::RandomState::new(); -/// let v: Vec =3D vec![0xa8, 0x3c, 0x09]; -/// let s: &[u8] =3D &[0xa8, 0x3c, 0x09]; -/// assert_eq!(b.hash_one(v), b.hash_one(s)); -/// ``` -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Hash for Vec { - #[inline] - fn hash(&self, state: &mut H) { - Hash::hash(&**self, state) - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[rustc_on_unimplemented( - message =3D "vector indices are of type `usize` or ranges of `usize`", - label =3D "vector indices are of type `usize` or ranges of `usize`" -)] -impl, A: Allocator> Index for Vec { - type Output =3D I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - Index::index(&**self, index) - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -#[rustc_on_unimplemented( - message =3D "vector indices are of type `usize` or ranges of `usize`", - label =3D "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) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl FromIterator for Vec { - #[inline] - fn from_iter>(iter: I) -> Vec { - >::from_iter(iter.into_iter()) - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl IntoIterator for Vec { - type Item =3D T; - type IntoIter =3D IntoIter; - - /// Creates a consuming iterator, that is, one that moves each value o= ut of - /// the vector (from start to end). The vector cannot be used after ca= lling - /// this. - /// - /// # Examples - /// - /// ``` - /// let v =3D vec!["a".to_string(), "b".to_string()]; - /// let mut v_iter =3D v.into_iter(); - /// - /// let first_element: Option =3D 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 mut me =3D ManuallyDrop::new(self); - let alloc =3D ManuallyDrop::new(ptr::read(me.allocator())); - let begin =3D me.as_mut_ptr(); - let end =3D if T::IS_ZST { - begin.wrapping_byte_add(me.len()) - } else { - begin.add(me.len()) as *const T - }; - let cap =3D me.buf.capacity(); - IntoIter { - buf: NonNull::new_unchecked(begin), - phantom: PhantomData, - cap, - alloc, - ptr: begin, - end, - } - } - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a Vec { - type Item =3D &'a T; - type IntoIter =3D slice::Iter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { - type Item =3D &'a mut T; - type IntoIter =3D slice::IterMut<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Extend for Vec { - #[inline] - fn extend>(&mut self, iter: I) { - >::spec_extend(self, iter.into_= iter()) - } - - #[inline] - fn extend_one(&mut self, item: T) { - self.push(item); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.reserve(additional); - } -} - -impl Vec { - // leaf method to which various SpecFrom/SpecExtend implementations de= legate when - // they have no further optimizations to apply - #[cfg(not(no_global_oom_handling))] - 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) =3D iterator.next() { - let len =3D self.len(); - if len =3D=3D self.capacity() { - let (lower, _) =3D 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); - } - } - } - - // 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(()) - } - - // specific extend for `TrustedLen` iterators, called both by the spec= ializations - // and internal places where resolving specialization makes compilatio= n slower - #[cfg(not(no_global_oom_handling))] - fn extend_trusted(&mut self, iterator: impl iter::TrustedLen) { - 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 ptr =3D self.as_mut_ptr(); - let mut local_len =3D 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 w= e 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 whi= ch would eventually - // panic anyway. - panic!("capacity overflow"); - } - } - - // specific extend for `TrustedLen` iterators, called both by the spec= ializations - // and internal places where resolving specialization makes compilatio= n slower - fn try_extend_trusted(&mut self, iterator: impl iter::TrustedLen) -> Result<(), TryReserveError> { - 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 ptr =3D self.as_mut_ptr(); - let mut local_len =3D 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 w= e 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); - }); - } - Ok(()) - } else { - Err(TryReserveErrorKind::CapacityOverflow.into()) - } - } - - /// 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`. - /// - /// `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 `Splic= e` 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`=E2= =80=99s length - /// * or the lower bound of its `size_hint()` is exact. - /// - /// Otherwise, a temporary vector is allocated and the tail is moved t= wice. - /// - /// # 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 =3D vec![1, 2, 3, 4]; - /// let new =3D [7, 8, 9]; - /// let u: Vec<_> =3D 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 =3D "vec_splice", since =3D "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 elemen= t should be removed. - /// - /// If the closure returns true, then the element is removed and yield= ed. - /// If the closure returns false, the element will remain in the vecto= r and will not be yielded - /// by the iterator. - /// - /// If the returned `ExtractIf` is not exhausted, e.g. because it is d= ropped 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 ret= urned iterator. - /// - /// [`retain`]: Vec::retain - /// - /// Using this method is equivalent to the following code: - /// - /// ``` - /// # let some_predicate =3D |x: &mut i32| { *x =3D=3D 2 || *x =3D=3D = 3 || *x =3D=3D 6 }; - /// # let mut vec =3D vec![1, 2, 3, 4, 5, 6]; - /// let mut i =3D 0; - /// while i < vec.len() { - /// if some_predicate(&mut vec[i]) { - /// let val =3D vec.remove(i); - /// // your code here - /// } else { - /// i +=3D 1; - /// } - /// } - /// - /// # assert_eq!(vec, vec![1, 4, 5]); - /// ``` - /// - /// But `extract_if` is easier to use. `extract_if` is also more effic= ient, - /// because it can backshift the elements of the array in bulk. - /// - /// Note that `extract_if` also lets you mutate every element in the f= ilter closure, - /// regardless of whether you choose to keep or remove it. - /// - /// # Examples - /// - /// Splitting an array into evens and odds, reusing the original alloc= ation: - /// - /// ``` - /// #![feature(extract_if)] - /// let mut numbers =3D vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; - /// - /// let evens =3D numbers.extract_if(|x| *x % 2 =3D=3D 0).collect::>(); - /// let odds =3D numbers; - /// - /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); - /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); - /// ``` - #[unstable(feature =3D "extract_if", reason =3D "recently added", issu= e =3D "43244")] - pub fn extract_if(&mut self, filter: F) -> ExtractIf<'_, T, F, A> - where - F: FnMut(&mut T) -> bool, - { - let old_len =3D 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 pu= shing 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 =3D "extend_ref", since =3D "1.2.0")] -impl<'a, T: Copy + 'a, A: Allocator> Extend<&'a T> for Vec { - fn extend>(&mut self, iter: I) { - self.spec_extend(iter.into_iter()) - } - - #[inline] - fn extend_one(&mut self, &item: &'a T) { - self.push(item); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.reserve(additional); - } -} - -/// Implements comparison of vectors, [lexicographically](Ord#lexicographi= cal-comparison). -#[stable(feature =3D "rust1", since =3D "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 =3D "rust1", since =3D "1.0.0")] -impl Eq for Vec {} - -/// Implements ordering of vectors, [lexicographically](Ord#lexicographica= l-comparison). -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl Ord for Vec { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - Ord::cmp(&**self, &**other) - } -} - -#[stable(feature =3D "rust1", since =3D "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 w= eakest necessary type; - // could avoid questions of validity in certain cases - ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_p= tr(), self.len)) - } - // RawVec handles deallocation - } -} - -#[stable(feature =3D "rust1", since =3D "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 =3D "rust1", since =3D "1.0.0")] -impl fmt::Debug for Vec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl AsRef> for Vec { - fn as_ref(&self) -> &Vec { - self - } -} - -#[stable(feature =3D "vec_as_mut", since =3D "1.5.0")] -impl AsMut> for Vec { - fn as_mut(&mut self) -> &mut Vec { - self - } -} - -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl AsRef<[T]> for Vec { - fn as_ref(&self) -> &[T] { - self - } -} - -#[stable(feature =3D "vec_as_mut", since =3D "1.5.0")] -impl AsMut<[T]> for Vec { - fn as_mut(&mut self) -> &mut [T] { - self - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl From<&[T]> for Vec { - /// Allocate a `Vec` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]); - /// ``` - #[cfg(not(test))] - 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 =3D "vec_from_mut", since =3D "1.19.0")] -impl From<&mut [T]> for Vec { - /// Allocate a `Vec` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]); - /// ``` - #[cfg(not(test))] - 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 =3D "vec_from_array_ref", since =3D "1.74.0")] -impl From<&[T; N]> for Vec { - /// Allocate a `Vec` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); - /// ``` - fn from(s: &[T; N]) -> Vec { - Self::from(s.as_slice()) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "vec_from_array_ref", since =3D "1.74.0")] -impl From<&mut [T; N]> for Vec { - /// Allocate a `Vec` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); - /// ``` - fn from(s: &mut [T; N]) -> Vec { - Self::from(s.as_mut_slice()) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "vec_from_array", since =3D "1.44.0")] -impl From<[T; N]> for Vec { - /// Allocate a `Vec` and move `s`'s items into it. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); - /// ``` - #[cfg(not(test))] - 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)) - } -} - -#[cfg(not(no_borrow))] -#[stable(feature =3D "vec_from_cow_slice", since =3D "1.14.0")] -impl<'a, T> From> for Vec -where - [T]: ToOwned>, -{ - /// Convert 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]> =3D Cow::Owned(vec![1, 2, 3]); - /// let b: Cow<'_, [i32]> =3D Cow::Borrowed(&[1, 2, 3]); - /// assert_eq!(Vec::from(o), Vec::from(b)); - /// ``` - fn from(s: Cow<'a, [T]>) -> Vec { - s.into_owned() - } -} - -// note: test pulls in std, which causes errors here -#[cfg(not(test))] -#[stable(feature =3D "vec_from_box", since =3D "1.18.0")] -impl From> for Vec { - /// Convert a boxed slice into a vector by transferring ownership of - /// the existing heap allocation. - /// - /// # Examples - /// - /// ``` - /// let b: Box<[i32]> =3D 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 =3D "box_from_vec", since =3D "1.20.0")] -impl From> for Box<[T], A> { - /// Convert a vector into a boxed slice. - /// - /// If `v` has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Box::from(vec![1, 2, 3]), vec![1, 2, 3].into_boxed_slic= e()); - /// ``` - /// - /// Any excess capacity is removed: - /// ``` - /// let mut vec =3D Vec::with_capacity(10); - /// vec.extend([1, 2, 3]); - /// - /// assert_eq!(Box::from(vec), vec![1, 2, 3].into_boxed_slice()); - /// ``` - fn from(v: Vec) -> Self { - v.into_boxed_slice() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature =3D "rust1", since =3D "1.0.0")] -impl From<&str> for Vec { - /// Allocate a `Vec` and fill it with a UTF-8 string. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from("123"), vec![b'1', b'2', b'3']); - /// ``` - fn from(s: &str) -> Vec { - From::from(s.as_bytes()) - } -} - -#[stable(feature =3D "array_try_from_vec", since =3D "1.48.0")] -impl TryFrom> for [T; N] { - type Error =3D 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], _> =3D (0..10).collect::>().try_int= o(); - /// 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 =3D String::from("hello world").into_bytes(); - /// v.sort(); - /// v.truncate(2); - /// let [a, b]: [_; 2] =3D 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() !=3D 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 =3D unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; - Ok(array) - } -} diff --git a/rust/alloc/vec/partial_eq.rs b/rust/alloc/vec/partial_eq.rs deleted file mode 100644 index 10ad4e492287..000000000000 --- a/rust/alloc/vec/partial_eq.rs +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -use crate::alloc::Allocator; -#[cfg(not(no_global_oom_handling))] -use crate::borrow::Cow; - -use super::Vec; - -macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$st= ability:meta]) =3D> { - #[$stability] - impl PartialEq<$rhs> for $lhs - where - T: PartialEq, - $($ty: $bound)? - { - #[inline] - fn eq(&self, other: &$rhs) -> bool { self[..] =3D=3D other[..]= } - #[inline] - fn ne(&self, other: &$rhs) -> bool { self[..] !=3D other[..] } - } - } -} - -__impl_slice_eq1! { [A1: Allocator, A2: Allocator] Vec, Vec,= #[stable(feature =3D "rust1", since =3D "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature =3D "= rust1", since =3D "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = =3D "rust1", since =3D "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature =3D "= partialeq_vec_for_ref_slice", since =3D "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = =3D "partialeq_vec_for_ref_slice", since =3D "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature =3D "p= artialeq_vec_for_slice", since =3D "1.48.0")] } -__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature =3D "p= artialeq_vec_for_slice", since =3D "1.48.0")] } -#[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone,= #[stable(feature =3D "rust1", since =3D "1.0.0")] } -#[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature= =3D "rust1", since =3D "1.0.0")] } -#[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(fea= ture =3D "rust1", since =3D "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[st= able(feature =3D "rust1", since =3D "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[s= table(feature =3D "rust1", since =3D "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/rust/alloc/vec/set_len_on_drop.rs b/rust/alloc/vec/set_len_on_= drop.rs deleted file mode 100644 index d3c7297b80ec..000000000000 --- a/rust/alloc/vec/set_len_on_drop.rs +++ /dev/null @@ -1,35 +0,0 @@ -// 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 -// 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; - } - - #[inline] - pub(super) fn current_len(&self) -> usize { - self.local_len - } -} - -impl Drop for SetLenOnDrop<'_> { - #[inline] - fn drop(&mut self) { - *self.len =3D self.local_len; - } -} diff --git a/rust/alloc/vec/spec_extend.rs b/rust/alloc/vec/spec_extend.rs deleted file mode 100644 index ada919537446..000000000000 --- a/rust/alloc/vec/spec_extend.rs +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 OR MIT - -use crate::alloc::Allocator; -use crate::collections::TryReserveError; -use core::iter::TrustedLen; -use core::slice::{self}; - -use super::{IntoIter, Vec}; - -// Specialization trait used for Vec::extend -#[cfg(not(no_global_oom_handling))] -pub(super) trait SpecExtend { - fn spec_extend(&mut self, iter: I); -} - -// 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, -{ - default fn spec_extend(&mut self, iter: I) { - self.extend_desugared(iter) - } -} - -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, -{ - default fn spec_extend(&mut self, iterator: I) { - self.extend_trusted(iterator) - } -} - -impl TrySpecExtend for Vec -where - I: TrustedLen, -{ - default fn try_spec_extend(&mut self, iterator: I) -> Result<(), TryRe= serveError> { - self.try_extend_trusted(iterator) - } -} - -#[cfg(not(no_global_oom_handling))] -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 TrySpecExtend> for Vec { - fn try_spec_extend(&mut self, mut iterator: IntoIter) -> Result<(),= TryReserveError> { - unsafe { - self.try_append_elements(iterator.as_slice() as _)?; - } - iterator.forget_remaining_elements(); - Ok(()) - } -} - -#[cfg(not(no_global_oom_handling))] -impl<'a, T: 'a, I, A: Allocator> 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, I, A: Allocator> 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> SpecExtend<&'a T, slice::Iter<'a, T>> for Ve= c -where - T: Copy, -{ - fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { - let slice =3D iterator.as_slice(); - unsafe { self.append_elements(slice) }; - } -} - -impl<'a, T: 'a, A: Allocator> 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.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1FB4A24B4A; Wed, 27 Mar 2024 02:36:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506978; cv=none; b=B57IGDUKi5DhZeTQQodk/xJcWvSQOVOOiZy8QYFcZFDvJSj1K12k1ZkjcTrV/RmqyNmN5yFwDecDKW2rhdSuyDX2502Tj1J7Hphgmi72fdKjEitEI3Sf2PnNwnUklIYPkS+z3F5lHfR9fkxETXSwBbvpYfHtOvdz5R1rBKQqA5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506978; c=relaxed/simple; bh=0fCsGNf1188vA6CAE01UEQquzZhM0FfzVV+EIiO8TSw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=U78qXQktTaxoM4xyh92NXVgee88ZvbWEGZwjghpkr3ZuackfDz8w2ijTfZiYyIb9SmZG7xdQad6Nzayhwf1oYyodtWzcKYz5rLsMHMyWyqtFz2Y0HAAfcg+eRh1PsJxLphIRYus8cnqpoQf03zENBF11BeUKYE1flSGEIH/ykhE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AUwTWvFO; arc=none smtp.client-ip=209.85.216.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AUwTWvFO" Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-29f93c4946cso4194993a91.1; Tue, 26 Mar 2024 19:36:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506976; x=1712111776; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1nOGf5fpM64u9bq6Y02DKyESI+dcDeLAOylIn1hPVDk=; b=AUwTWvFObc6H3SOcovV3oRkKroYCa/OovYPqu+jheqpTP876WkJ4sXU8S4Jq4QKPWJ /+8TGBH94qJN++57lq04FK5HKxP1acpCM2uT8q7Zln5MWHmaWYpMXqug7AQMw999M3Vk 8vAO/c4IeLOM3P6H71ultmiZ5vhYUxZ5thIgkZrld2xJJ7AqjtyFQQTG/LJIiFXVaNMQ X08lCS7ITFwiHGSCrMO/Q+gVsuu/MKNK3p5feH8UJjfpm0RPCluZ+kEPrWbkeoZmh7X9 s5ZdQrpiKXsdiuFkcimKK/G752oJ9WBZqzLuFXJKdKx0tQULewjr5rbpN1MMnK0gkopn SRzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506976; x=1712111776; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1nOGf5fpM64u9bq6Y02DKyESI+dcDeLAOylIn1hPVDk=; b=qRdDlykf++C2gUreYvk3zYV1maDgGrVhiq5AQSDpNVl9pvw4gyrnrgVJQ67Gx+NRco icJX3m6GTsI1qUmj8g+fqbMej6pB4Hhtw2+fJE/mEYqdSQ+A1jbW5mnWlpQd95AgxTYh bqwUlX1WCP6wbPa1DFlYf9FfMdT94bUAWEdf1XfORz/PjbH6Ly8mrMU0jH3XIrW6fmmO 8v5zx/5+MTVK9Az0MUgTxIrj4zKIcGYzjSrsWQfPRN2pweHf8a755SeDFVQ99BE1wdN8 tjDcXbIDFOtgYwoTWY570VDH9jMnN2t6G52VBACCZszkYMPysK6D/DtvpU7aS6vmRth5 aBfQ== X-Forwarded-Encrypted: i=1; AJvYcCXViiolvJCmQIg+d7a0p2qfRJa1EOEh7KnOXorJdGjDjrom3kTQqhMJDJIXu188D3wGdO3s8AJJD9oTGRHeQ7H6lZrHC/8fgE0dyEvZ X-Gm-Message-State: AOJu0Yw7O3fhNx6OltHPyN9FsK32wCDexf2b93K+SMtTNj/N0FGmnFKU CCdN9HVuiib+L2MGxJVTyfqPw/SCE+2tXnNBP1mungw7/EeJh5jYA1c4wB7j X-Google-Smtp-Source: AGHT+IFmQvoPLIdrjBKDhCQTw0wXy6EPV4pLT8wSmz0VmoB7JynqXBk1OHP6LF8DHlR+cZ2rpcurHQ== X-Received: by 2002:a17:90a:d3d6:b0:29b:9d98:5388 with SMTP id d22-20020a17090ad3d600b0029b9d985388mr1516802pjw.12.1711506976293; Tue, 26 Mar 2024 19:36:16 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:15 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 05/10] rust: alloc: introduce allocation flags Date: Tue, 26 Mar 2024 23:35:26 -0300 Message-Id: <20240327023531.187880-6-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho We'll use them when allocating `Box`, `Arc`, and `UniqueArc` instances, as well as when allocating memory for `Vec` elements. These changes will come in subsequent patches. Reviewed-by: Benno Lossin Signed-off-by: Wedson Almeida Filho --- rust/bindings/bindings_helper.h | 3 ++ rust/kernel/alloc.rs | 56 +++++++++++++++++++++++++++++++++ rust/kernel/prelude.rs | 2 +- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 65b98831b975..ddb5644d4fd9 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -20,5 +20,8 @@ =20 /* `bindgen` gets confused at certain things. */ const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN =3D ARCH_SLAB_MINALIGN; +const gfp_t RUST_CONST_HELPER_GFP_ATOMIC =3D GFP_ATOMIC; const gfp_t RUST_CONST_HELPER_GFP_KERNEL =3D GFP_KERNEL; +const gfp_t RUST_CONST_HELPER_GFP_KERNEL_ACCOUNT =3D GFP_KERNEL_ACCOUNT; +const gfp_t RUST_CONST_HELPER_GFP_NOWAIT =3D GFP_NOWAIT; const gfp_t RUST_CONST_HELPER___GFP_ZERO =3D __GFP_ZERO; diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 2c99635f9fd3..0502bcf00bce 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -6,3 +6,59 @@ #[cfg(not(testlib))] mod allocator; pub mod vec_ext; + +/// Flags to be used when allocating memory. +/// +/// They can be combined with the operators `|`, `&`, and `!`. +/// +/// Values can be used from the [`flags`] module. +#[derive(Clone, Copy)] +pub struct Flags(u32); + +impl core::ops::BitOr for Flags { + type Output =3D Self; + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } +} + +impl core::ops::BitAnd for Flags { + type Output =3D Self; + fn bitand(self, rhs: Self) -> Self::Output { + Self(self.0 & rhs.0) + } +} + +impl core::ops::Not for Flags { + type Output =3D Self; + fn not(self) -> Self::Output { + Self(!self.0) + } +} + +/// Allocation flags. +/// +/// These are meant to be used in functions that can allocate memory. +pub mod flags { + use super::Flags; + use crate::bindings; + + /// Users can not sleep and need the allocation to succeed. + /// + /// A lower watermark is applied to allow access to "atomic reserves".= The current + /// implementation doesn't support NMI and few other strict non-preemp= tive contexts (e.g. + /// raw_spin_lock). The same applies to [`GFP_NOWAIT`]. + pub const GFP_ATOMIC: Flags =3D Flags(bindings::GFP_ATOMIC); + + /// Typical for kernel-internal allocations. The caller requires ZONE_= NORMAL or a lower zone + /// for direct access but can direct reclaim. + pub const GFP_KERNEL: Flags =3D Flags(bindings::GFP_KERNEL); + + /// The same as [`GFP_KERNEL`], except the allocation is accounted to = kmemcg. + pub const GFP_KERNEL_ACCOUNT: Flags =3D Flags(bindings::GFP_KERNEL_ACC= OUNT); + + /// Ror kernel allocations that should not stall for direct reclaim, s= tart physical IO or + /// use any filesystem callback. It is very likely to fail to allocat= e memory, even for very + /// small allocations. + pub const GFP_NOWAIT: Flags =3D Flags(bindings::GFP_NOWAIT); +} diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index c85b5972c0d3..827e4dfd77df 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,7 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::vec_ext::VecExt; +pub use crate::alloc::{flags::*, vec_ext::VecExt}; =20 #[doc(no_inline)] pub use alloc::{boxed::Box, vec::Vec}; --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pg1-f173.google.com (mail-pg1-f173.google.com [209.85.215.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD50424B5B; Wed, 27 Mar 2024 02:36:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506983; cv=none; b=V3JUDvMbANOtevTcemQsiOzBHkGfVK6yNPbdI5EQS6og1OEfThgbqxLKq7zf9N9eh+qvpF8D1cq/KWWwi6/cLAR87ptKck7QYAwgreIvnvUxNr5I6qvT+Uw2g4rAKYb80qgFNHFnKB87lJ77kz/EIcqFJM8gauhQMfgFiM789xI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506983; c=relaxed/simple; bh=17ik0Ul2gPKK8aUlxS+AElFknDr9P8MWNuwiq1vhq+0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WZhBQz86G62Xv2CB5EPDx9fSQkS+KMX9lva1NNvRR6NjCTLPTKvnG19lLt0LykcRdO4V47qXNcgsQKiToeiC8CfpThWIX6b0RVxC1b6+iK+ISpbxHr1GzkTeNBiCUR9hgtJYjfBtIbkzjTPdk0ogNjB0BHk8K5hQxsykk9gUV18= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QGvyb41W; arc=none smtp.client-ip=209.85.215.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QGvyb41W" Received: by mail-pg1-f173.google.com with SMTP id 41be03b00d2f7-5d3907ff128so4694344a12.3; Tue, 26 Mar 2024 19:36:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506981; x=1712111781; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0HHQeIoqMo2CZOYcEbyAnPxdtILQe9NcGBVh9oiIIeA=; b=QGvyb41WE4bHkWCAixzXlEX6gunz0ILP4HWloKkkvQ9Vy70RbRuQ344VmcQ7gqA3Uk o0ChVxDNtdlO3Ve1Exq4oJP2y8RDXZiX26en5hy45FfUyeNUXQY5QQgBG+rWuE9xiLrK 3DQZo28sibiy6u1n8I9opXkX3dSjZZSk0ykjLq/7WmtFEVEuv3uOSxKostHLEdQNWEKL weZziQim/fW8OMfOuzb8isngATyuhWQK1EcjqiKQkUxfm89xxXsYKkMXTS34fRnCSaRp YlzEdJCxIBY+CrK6noFlujjegD1Pg8StTEgb3TZYzxACi/jUEZGHf/s4mORpzaIzeBZC 1UAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506981; x=1712111781; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0HHQeIoqMo2CZOYcEbyAnPxdtILQe9NcGBVh9oiIIeA=; b=sM8rbJGdb9IAui9Ihzb38OQ/yqCl3mD9KZZHOLm8PVevGI0HIkeo38IPt2UsFNFpk9 UXoMOs7BPILE+hlFy/YWBXPWLzDRCgEVW6TAbaMrFqqoS0hKgT4hc6BVeoYiXrxjaGbH g6uwTCaPIEmYDryvmwg8sl1cBrcgNjpJZFPhv72h1hbN82n+Uq1281e6V0qVWxCgME0v MNQNh7jgKJFaj1ewzUqrwRs68US2V5IiMVdyHzcrD9V7xiFAg0LT/evOjqJOa/HI/dIh QljB/M2OhZKBtJk53qEoHJ9SmXb+ZF80dcjcDQ2dl778eewZPWW3M0hx+kJMRvozRz9B eG4A== X-Forwarded-Encrypted: i=1; AJvYcCUjBvYWasynLvkduEaHKg4Jopf7mQgLGL4NHgcWnkajnVng+/Pa5m3Kc2LRgJetzf+61Kzh2ktY+/lmjfwG+cbxSFPhGbjVAbHX27vg X-Gm-Message-State: AOJu0YxXg4v0/pyArmd2tlr/YleQs6RPXtuiIhbHZAbQIvp+3MddE5b1 jWmQgFRertJnTX+pfFJOEYTsvAMMN+i9NQ7I5Lhf+FZFF0TFl6OKzkQ0wGPl X-Google-Smtp-Source: AGHT+IGQDsKjcKuyDURBUBz2PqgK/gvpzGoPM9zjK4nSWJIL+hN6jJasAB7nKlBRx2zHEJZLAUCIqw== X-Received: by 2002:a05:6a21:150d:b0:1a3:da69:8eeb with SMTP id nq13-20020a056a21150d00b001a3da698eebmr4086556pzb.52.1711506981166; Tue, 26 Mar 2024 19:36:21 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:20 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 06/10] rust: alloc: introduce the `BoxExt` trait Date: Tue, 26 Mar 2024 23:35:27 -0300 Message-Id: <20240327023531.187880-7-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho Make fallible versions of `new` and `new_uninit` methods available in `Box` even though it doesn't implement them because we build `alloc` with the `no_global_oom_handling` config. They also have an extra `flags` parameter that allows callers to pass flags to the allocator. Signed-off-by: Wedson Almeida Filho --- rust/kernel/alloc.rs | 1 + rust/kernel/alloc/allocator.rs | 6 +++- rust/kernel/alloc/box_ext.rs | 62 ++++++++++++++++++++++++++++++++++ rust/kernel/init.rs | 13 +++---- rust/kernel/prelude.rs | 2 +- rust/kernel/sync/arc.rs | 3 +- 6 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 rust/kernel/alloc/box_ext.rs diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index 0502bcf00bce..a4c4b1f79bc9 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -5,6 +5,7 @@ #[cfg(not(test))] #[cfg(not(testlib))] mod allocator; +pub mod box_ext; pub mod vec_ext; =20 /// Flags to be used when allocating memory. diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index 01ad139e19bc..fc0439455faa 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -15,7 +15,11 @@ /// /// - `ptr` can be either null or a pointer which has been allocated by th= is allocator. /// - `new_layout` must have a non-zero size. -unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindin= gs::gfp_t) -> *mut u8 { +pub(crate) unsafe fn krealloc_aligned( + ptr: *mut u8, + new_layout: Layout, + flags: bindings::gfp_t, +) -> *mut u8 { // Customized layouts from `Layout::from_size_align()` can have size <= align, so pad first. let layout =3D new_layout.pad_to_align(); =20 diff --git a/rust/kernel/alloc/box_ext.rs b/rust/kernel/alloc/box_ext.rs new file mode 100644 index 000000000000..aaa6a20d12b6 --- /dev/null +++ b/rust/kernel/alloc/box_ext.rs @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Extensions to [`Box`] for fallible allocations. + +use super::Flags; +use alloc::boxed::Box; +use core::alloc::AllocError; +use core::mem::MaybeUninit; +use core::result::Result; + +/// Extensions to [`Box`]. +pub trait BoxExt: Sized { + /// Allocates a new box. + /// + /// The allocation may fail, in which case an error is returned. + fn new(x: T, flags: Flags) -> Result; + + /// Allocates a new uninitialised box. + /// + /// The allocation may fail, in which case an error is returned. + fn new_uninit(flags: Flags) -> Result>, AllocError>; +} + +impl BoxExt for Box { + #[cfg(any(test, testlib))] + fn new(x: T, _flags: Flags) -> Result { + Ok(Box::new(x)) + } + + #[cfg(not(any(test, testlib)))] + fn new(x: T, flags: Flags) -> Result { + let ptr =3D if core::mem::size_of::() =3D=3D 0 { + core::ptr::NonNull::::dangling().as_ptr() + } else { + let layout =3D core::alloc::Layout::new::(); + + // SAFETY: Memory is being allocated (first arg is null). The = only other source of + // safety issues is sleeping on atomic context, which is addre= ssed by klint. Lastly, + // the type is not a SZT (checked above). + let ptr =3D unsafe { + super::allocator::krealloc_aligned(core::ptr::null_mut(), = layout, flags.0) + }; + if ptr.is_null() { + return Err(AllocError); + } + + let ptr =3D ptr.cast::(); + + // SAFETY: We just allocated the memory above, it is valid for= write. + unsafe { ptr.write(x) }; + ptr + }; + + // SAFETY: For non-zero-sized types, we allocate above using the g= lobal allocator. For + // zero-sized types, we use `NonNull::dangling`. + Ok(unsafe { Box::from_raw(ptr) }) + } + + fn new_uninit(flags: Flags) -> Result>, AllocError>= { + as BoxExt<_>>::new(MaybeUninit::::uninit(), flags) + } +} diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index 424257284d16..9c798cffc8e4 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -210,6 +210,7 @@ //! [`pin_init!`]: crate::pin_init! =20 use crate::{ + alloc::{box_ext::BoxExt, flags::*}, error::{self, Error}, sync::UniqueArc, types::{Opaque, ScopeGuard}, @@ -305,9 +306,9 @@ macro_rules! stack_pin_init { /// /// stack_try_pin_init!(let foo: Result, AllocError> =3D pin= _init!(Foo { /// a <- new_mutex!(42), -/// b: Box::try_new(Bar { +/// b: Box::new(Bar { /// x: 64, -/// })?, +/// }, GFP_KERNEL)?, /// })); /// let foo =3D foo.unwrap(); /// pr_info!("a: {}", &*foo.a.lock()); @@ -331,9 +332,9 @@ macro_rules! stack_pin_init { /// /// stack_try_pin_init!(let foo: Pin<&mut Foo> =3D? pin_init!(Foo { /// a <- new_mutex!(42), -/// b: Box::try_new(Bar { +/// b: Box::new(Bar { /// x: 64, -/// })?, +/// }, GFP_KERNEL)?, /// })); /// pr_info!("a: {}", &*foo.a.lock()); /// # Ok::<_, AllocError>(()) @@ -1158,7 +1159,7 @@ fn try_pin_init(init: impl PinInit) -> Resul= t, E> where E: From, { - let mut this =3D Box::try_new_uninit()?; + let mut this =3D as BoxExt<_>>::new_uninit(GFP_KERNEL)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid and will not be moved, because we pin it later. @@ -1172,7 +1173,7 @@ fn try_init(init: impl Init) -> Result where E: From, { - let mut this =3D Box::try_new_uninit()?; + let mut this =3D as BoxExt<_>>::new_uninit(GFP_KERNEL)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid. diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 827e4dfd77df..b37a0b3180fb 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,7 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; =20 -pub use crate::alloc::{flags::*, vec_ext::VecExt}; +pub use crate::alloc::{box_ext::BoxExt, flags::*, vec_ext::VecExt}; =20 #[doc(no_inline)] pub use alloc::{boxed::Box, vec::Vec}; diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 7d4c4bf58388..1252a1b630ed 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -16,6 +16,7 @@ //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html =20 use crate::{ + alloc::{box_ext::BoxExt, flags::*}, bindings, error::{self, Error}, init::{self, InPlaceInit, Init, PinInit}, @@ -170,7 +171,7 @@ pub fn try_new(contents: T) -> Result= { data: contents, }; =20 - let inner =3D Box::try_new(value)?; + let inner =3D as BoxExt<_>>::new(value, GFP_KERNEL)?; =20 // SAFETY: We just created `inner` with a reference count of 1, wh= ich is owned by the new // `Arc` object. --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pg1-f179.google.com (mail-pg1-f179.google.com [209.85.215.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E1F5D25630; Wed, 27 Mar 2024 02:36:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506987; cv=none; b=UlkpLzcJjMQSgwqbiWYMKMGwTQOMlyS20gRC9a0mGEQKheaaVrf7uMBUwUpTyEcZeCCqDU6rgxDBMPONEefXGBMySZeTEv+AYqJ72jAPQFR2+NlLXCmVYuk+s2bQLK2hApH9PbbGIlzvYr5DnCEn8mDodDTrPFMXxVIKcT056Cw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506987; c=relaxed/simple; bh=0M4ppCPUwtz16eZhrPWe5yLXkPkDNAmVPGzlAvCJotc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QueHWrnoYodzyzI6/LbXztiherOtbZW/VRv8owDo8klrpsM4sq73R/+5MOzJJ2UcARA513V2tJnqh9bTg2MdNyRfVgigpJfGdox/PxSh0jRhcK2pAjZrGwiF61LJZn8tND8eRihSVq2Da+nDfjCfONR0erV8FdgQOdTz2bpxF/0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RkODSVOr; arc=none smtp.client-ip=209.85.215.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RkODSVOr" Received: by mail-pg1-f179.google.com with SMTP id 41be03b00d2f7-53fbf2c42bfso4539691a12.3; Tue, 26 Mar 2024 19:36:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506985; x=1712111785; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=435GQ6m0tr/HQyJUi6qsfFFlxdcC37v/LHKOTsBj2jE=; b=RkODSVOrevQ0uXedak9b6MZGEwEbNrLTMme03Gi0V9cWpRbxe2XNM9OTatgn6ok7gH 4QwSL8cmYMoUESMtagPf0tdcFxLSnxarrRlxdvHIaz5bSs/wO+MdzfFBNj804keo/2iZ MMAsEtDyW7emrc5e99sB3dpY5bj5dvBvxvFwQn3HfmzZaC4DJuWeUw3D14aBbJmbKFsS AraGAofL6Y6QvVR63YY7nGUE1XdGRAqtmxLpUHyvo6ZmY8WscXSPhCXpEkRedUTs1GOz Q6K0lL48ffealAyCpkIKfts6La5p5SvpBUeImQUQrNbzFe5yIY0NfsYlmusE3H+iFmJb cEOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506985; x=1712111785; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=435GQ6m0tr/HQyJUi6qsfFFlxdcC37v/LHKOTsBj2jE=; b=mXM80I4RqyH/dayYBOaJTMlFNEOjV4UNzr4FZm/YCnKYDIYcDU4ddfS9xv4QuBnxqs 4Btyzk707T/1vbn5LyP53AWPsWat1EY1Vzo+CAMwNqb/OHsCjm1/JHCL4x2IC6Lyv6+y xHf6jWzjyc0abdjd/qSokN4n3MN6ihyKho+nSDEt4Da4zVGWMbVszjSSFJnEa3aWruRX vhcWREJai6UsO5ccwhR0wq6YxXUNuwdI+Zm3eNPJUW6jc07UeDM0ogb9NezdrrZyH6uB Q7XR0+xpTt/PXPWjryxyRd8ZUNKcTX/YSDRe0Tnif+WxrjYD6SPO+LflRYFZzhLFy+JN c7CA== X-Forwarded-Encrypted: i=1; AJvYcCUAb3SEEEZD9+epVbjABbVEUYZGk49zDelkAQXlfdm9HYU8pJHSMXh+8PrgwfKsHOPI2uRQSdObbCteOjAQTAPjLFFyckj5XlhDin/s X-Gm-Message-State: AOJu0YzXFfBDDX/PSdRU/YS2gjJVIppCMKr++BujscISn8xGQYZvollz ZFoI1W50fGfIn4dh2CYw1xg0esFqNb2cwvjNVfkmpGZBwWqxxVYMCUhlpicK X-Google-Smtp-Source: AGHT+IHlC7IN/HbcRU25f86+8d45EQJIX5I1ESqZbfxED600vb9obrVZgJnJnGZSsHhx9/RzwYolQw== X-Received: by 2002:a05:6a21:33a0:b0:1a3:c3d9:fd15 with SMTP id yy32-20020a056a2133a000b001a3c3d9fd15mr3312675pzb.38.1711506985130; Tue, 26 Mar 2024 19:36:25 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:24 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 07/10] rust: alloc: update `VecExt` to take allocation flags Date: Tue, 26 Mar 2024 23:35:28 -0300 Message-Id: <20240327023531.187880-8-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho We also rename the methods by removing the `try_` prefix since the names are available due to our usage of the `no_global_oom_handling` config when building the `alloc` crate. Signed-off-by: Wedson Almeida Filho Reviewed-by: Boqun Feng --- rust/kernel/alloc/vec_ext.rs | 106 ++++++++++++++++++++++++++++++----- rust/kernel/error.rs | 11 +--- rust/kernel/lib.rs | 1 - rust/kernel/str.rs | 6 +- rust/kernel/types.rs | 4 +- samples/rust/rust_minimal.rs | 6 +- 6 files changed, 100 insertions(+), 34 deletions(-) diff --git a/rust/kernel/alloc/vec_ext.rs b/rust/kernel/alloc/vec_ext.rs index 311e62cc5784..bb6cb1c4ea67 100644 --- a/rust/kernel/alloc/vec_ext.rs +++ b/rust/kernel/alloc/vec_ext.rs @@ -2,47 +2,123 @@ =20 //! Extensions to [`Vec`] for fallible allocations. =20 -use alloc::{collections::TryReserveError, vec::Vec}; +use super::Flags; +use alloc::{alloc::AllocError, vec::Vec}; use core::result::Result; =20 /// Extensions to [`Vec`]. pub trait VecExt: Sized { /// Creates a new [`Vec`] instance with at least the given capacity. - fn try_with_capacity(capacity: usize) -> Result; + fn with_capacity(capacity: usize, flags: Flags) -> Result; =20 /// Appends an element to the back of the [`Vec`] instance. - fn try_push(&mut self, v: T) -> Result<(), TryReserveError>; + fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError>; =20 /// Pushes clones of the elements of slice into the [`Vec`] instance. - fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryRese= rveError> + fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(= ), AllocError> where T: Clone; + + /// Ensures that the capacity exceeds the length by at least `addition= al` elements. + fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), A= llocError>; } =20 impl VecExt for Vec { - fn try_with_capacity(capacity: usize) -> Result= { + fn with_capacity(capacity: usize, flags: Flags) -> Result { let mut v =3D Vec::new(); - v.try_reserve(capacity)?; + >::reserve(&mut v, capacity, flags)?; Ok(v) } =20 - fn try_push(&mut self, v: T) -> Result<(), TryReserveError> { - if let Err(retry) =3D self.push_within_capacity(v) { - self.try_reserve(1)?; - let _ =3D self.push_within_capacity(retry); - } + fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> { + >::reserve(self, 1, flags)?; + let s =3D self.spare_capacity_mut(); + s[0].write(v); + + // SAFETY: We just initialised the first spare entry, so it is saf= e to increase the length + // by 1. We also know that the new length is <=3D capacity because= of the previous call to + // `reserve` above. + unsafe { self.set_len(self.len() + 1) }; Ok(()) } =20 - fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryRese= rveError> + fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(= ), AllocError> where T: Clone, { - self.try_reserve(other.len())?; - for item in other { - self.try_push(item.clone())?; + >::reserve(self, other.len(), flags)?; + for (slot, item) in core::iter::zip(self.spare_capacity_mut(), oth= er) { + slot.write(item.clone()); } =20 + // SAFETY: We just initialised the `other.len()` spare entries, so= it is safe to increase + // the length by the same amount. We also know that the new length= is <=3D capacity because + // of the previous call to `reserve` above. + unsafe { self.set_len(self.len() + 1) }; + Ok(()) + } + + #[cfg(any(test, testlib))] + fn reserve(&mut self, additional: usize, _flags: Flags) -> Result<(), = AllocError> { + Vec::reserve(self, additional); Ok(()) } + + #[cfg(not(any(test, testlib)))] + fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), A= llocError> { + let len =3D self.len(); + let cap =3D self.capacity(); + + if cap - len >=3D additional { + return Ok(()); + } + + if core::mem::size_of::() =3D=3D 0 { + // The capacity is already `usize::MAX` for SZTs, we can't go = higher. + return Err(AllocError); + } + + // We know cap is <=3D `isize::MAX` because `Layout::array` fails = if the resulting byte size + // is greater than `isize::MAX`. So the multiplication by two won'= t overflow. + let new_cap =3D core::cmp::max(cap * 2, len.checked_add(additional= ).ok_or(AllocError)?); + let layout =3D core::alloc::Layout::array::(new_cap).map_err(|_= | AllocError)?; + + let (ptr, len, cap) =3D destructure(self); + + // SAFETY: `ptr` is valid because it's either NULL or comes from a= previous call to + // `krealloc_aligned`. We also verified that the type is not a ZST. + let new_ptr =3D unsafe { super::allocator::krealloc_aligned(ptr.ca= st(), layout, flags.0) }; + if new_ptr.is_null() { + // SAFETY: We are just rebuilding the existing `Vec` with no c= hanges. + unsafe { rebuild(self, ptr, len, cap) }; + Err(AllocError) + } else { + // SAFETY: `ptr` has been reallocated with the layout for `new= _cap` elements. New cap + // is greater than `cap`, so it continues to be >=3D `len`. + unsafe { rebuild(self, new_ptr.cast::(), len, new_cap) }; + Ok(()) + } + } +} + +#[cfg(not(any(test, testlib)))] +fn destructure(v: &mut Vec) -> (*mut T, usize, usize) { + let mut tmp =3D Vec::new(); + core::mem::swap(&mut tmp, v); + let mut tmp =3D core::mem::ManuallyDrop::new(tmp); + let len =3D tmp.len(); + let cap =3D tmp.capacity(); + (tmp.as_mut_ptr(), len, cap) +} + +/// Rebuilds a `Vec` from a pointer, length, and capacity. +/// +/// # Safety +/// +/// The same as [`Vec::from_raw_parts`]. +#[cfg(not(any(test, testlib)))] +unsafe fn rebuild(v: &mut Vec, ptr: *mut T, len: usize, cap: usize) { + // SAFETY: The safety requirements from this function satisfy those of= `from_raw_parts`. + let mut tmp =3D unsafe { Vec::from_raw_parts(ptr, len, cap) }; + core::mem::swap(&mut tmp, v); } diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 4786d3ee1e92..e53466937796 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -6,10 +6,7 @@ =20 use crate::str::CStr; =20 -use alloc::{ - alloc::{AllocError, LayoutError}, - collections::TryReserveError, -}; +use alloc::alloc::{AllocError, LayoutError}; =20 use core::convert::From; use core::fmt; @@ -192,12 +189,6 @@ fn from(_: Utf8Error) -> Error { } } =20 -impl From for Error { - fn from(_: TryReserveError) -> Error { - code::ENOMEM - } -} - impl From for Error { fn from(_: LayoutError) -> Error { code::ENOMEM diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 7f2841a18d05..51f30e55bd00 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -19,7 +19,6 @@ #![feature(offset_of)] #![feature(receiver_trait)] #![feature(unsize)] -#![feature(vec_push_within_capacity)] =20 // Ensure conditional compilation based on the kernel configuration works; // otherwise we may silently break things like initcall handling. diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index e1be6c5e72a9..58f2ddafb326 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -2,7 +2,7 @@ =20 //! String representations. =20 -use crate::alloc::vec_ext::VecExt; +use crate::alloc::{flags::*, vec_ext::VecExt}; use alloc::alloc::AllocError; use alloc::vec::Vec; use core::fmt::{self, Write}; @@ -730,7 +730,7 @@ pub fn try_from_fmt(args: fmt::Arguments<'_>) -> Result= { let size =3D f.bytes_written(); =20 // Allocate a vector with the required number of bytes, and write = to it. - let mut buf =3D Vec::try_with_capacity(size)?; + let mut buf =3D as VecExt<_>>::with_capacity(size, GFP_KER= NEL)?; // SAFETY: The buffer stored in `buf` is at least of size `size` a= nd is valid for writes. let mut f =3D unsafe { Formatter::from_buffer(buf.as_mut_ptr(), si= ze) }; f.write_fmt(args)?; @@ -771,7 +771,7 @@ impl<'a> TryFrom<&'a CStr> for CString { fn try_from(cstr: &'a CStr) -> Result { let mut buf =3D Vec::new(); =20 - buf.try_extend_from_slice(cstr.as_bytes_with_nul()) + as VecExt<_>>::extend_from_slice(&mut buf, cstr.as_bytes_w= ith_nul(), GFP_KERNEL) .map_err(|_| AllocError)?; =20 // INVARIANT: The `CStr` and `CString` types have the same invaria= nts for diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index aa77bad9bce4..8fad61268465 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -157,11 +157,11 @@ unsafe fn from_foreign(_: *const core::ffi::c_void) -= > Self {} /// let mut vec =3D /// ScopeGuard::new_with_data(Vec::new(), |v| pr_info!("vec had {}= elements\n", v.len())); /// -/// vec.try_push(10u8)?; +/// vec.push(10u8, GFP_KERNEL)?; /// if arg { /// return Ok(()); /// } -/// vec.try_push(20u8)?; +/// vec.push(20u8, GFP_KERNEL)?; /// Ok(()) /// } /// diff --git a/samples/rust/rust_minimal.rs b/samples/rust/rust_minimal.rs index dc05f4bbe27e..2a9eaab62d1c 100644 --- a/samples/rust/rust_minimal.rs +++ b/samples/rust/rust_minimal.rs @@ -22,9 +22,9 @@ fn init(_module: &'static ThisModule) -> Result { pr_info!("Am I built-in? {}\n", !cfg!(MODULE)); =20 let mut numbers =3D Vec::new(); - numbers.try_push(72)?; - numbers.try_push(108)?; - numbers.try_push(200)?; + numbers.push(72, GFP_KERNEL)?; + numbers.push(108, GFP_KERNEL)?; + numbers.push(200, GFP_KERNEL)?; =20 Ok(RustMinimal { numbers }) } --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pj1-f50.google.com (mail-pj1-f50.google.com [209.85.216.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFD9A28DC8; Wed, 27 Mar 2024 02:36:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506991; cv=none; b=u8DWCrRcPYQT2zBg4qP5wQSasIBPrxAruvC7tNpgtRspHTyGuC9vBQ+yIeXOOF1OFGxAIdn533oZwVXS2sj8dRFBcMaDw15QYnPdfZpX3aI4PO9B6KV8z8NLUGCWKTriFkKmhwzpvybXhvsUZhzWTPQqT/Cib6DAyYsgIB/RRqA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506991; c=relaxed/simple; bh=OnxJM8MtT6hmngjXVSsX0B92HW9GjGkLdfZieFHBEZo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dC68jv+x+9L8M/4LTT6Wf/3Uu/zieqIhqs7tjJjfkEGW57Hl/p4HCrxrIRBbGRDi0hF0QM5RS+5Zb9UB7PIieu9RLVaJgcqt5h01JfSTvbEuz8KuExLBTX2pyMnBIzWVZxHQIPhgW1l0hqNGZhDN5iwNi0v7DtTxyHpRNkptS6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=HYY9XVvD; arc=none smtp.client-ip=209.85.216.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HYY9XVvD" Received: by mail-pj1-f50.google.com with SMTP id 98e67ed59e1d1-29df3333d30so4419059a91.1; Tue, 26 Mar 2024 19:36:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506989; x=1712111789; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=OiOTxVpWX5GSU2dn6Y9lba1ybxkK7QhwN/uNuJH9fCw=; b=HYY9XVvD6+0ndtE63KgXFUf5iq9OWEbFYYR6LZ1v8PfhiE6eke6z9oDRNAgH7ZJnDB Y7nsy1ikj5iVh57QX/AdLkQol+3/ljgarcJPnDsplP3NMFEf/BpU+DDOC/CgUo4iBSX7 tWwLMrQUzA5paVQwLKKGT/MebcEAL2F+GxmwGUf6qHUobg5aK34piGveju4F05rOpw9E 1Aa/lByXaVA1739kt1D+9N8BybXTSOX4nyL0SqIUOGZWmkXIbHJd0RL7ZLBkjMp3StPm Rk+3neFg2ihCl060bB78ykZjqLS7Z+WURVVvLM6YKMKaPN91czu+0ooT3Z3kYvvX/ClD QnIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506989; x=1712111789; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OiOTxVpWX5GSU2dn6Y9lba1ybxkK7QhwN/uNuJH9fCw=; b=QVgvVZ8U/PolAlyHecrHF8tZruHmnBztaLH/oSzEW4TjPPjT0wdlslsMTCHNXktokt 4SpUB5qTgPCt6ncAURvT6VRkwoZJZCgIltNzzTdw4OYYZpJmAeMHAp658pT+diraU1xu /TyjIX39KOdTSzpCwTk2MgJvD69zM0jo6sJB4NdTzuNYROcAO+pPDZQh/aGNLzaTa6Jn whE4IrJa/7+4pdDHjURPtGheWhj7jQKTsOxMAnKh0NdMfHWWl7AkFlxdvJ+okJfQXypU OAuxINHHMAeiI/gAvV09PMcouL+yUAv+U/WBWcbCHM0n9f3wswtByq2X/+ImR8PXd/lN 0o3w== X-Forwarded-Encrypted: i=1; AJvYcCWNbbogYKg8zol41LBs09yDMaUd3VvsxiIXo8N02gBB/lekhk5QqlAmBc7OnO+MSTfELsz/lkX5S1xMwX4uGP70wTmfEQp1CaFXquXB X-Gm-Message-State: AOJu0YxsIQAMeNXXKWhBZMBIWPt0X9QbZrWzy7hP8WMFX+b2/HqMTDms RiWoM4OgqfnCPR1fZfo4DTePPVa9l3WSD682Qa26fR9dBX0Ms2z0m5GKSMIv X-Google-Smtp-Source: AGHT+IH+kP/Y8k1yZ43DmMLTxzGkzSTDl7vIb7SfQRbkXeffuQf6g0tnqkrkxQ5d8U9f6pE2ZpmS/A== X-Received: by 2002:a17:90a:f3c2:b0:2a0:7601:d50a with SMTP id ha2-20020a17090af3c200b002a07601d50amr1775473pjb.0.1711506989157; Tue, 26 Mar 2024 19:36:29 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:28 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 08/10] rust: sync: update `Arc` and `UniqueArc` to take allocation flags Date: Tue, 26 Mar 2024 23:35:29 -0300 Message-Id: <20240327023531.187880-9-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho We also remove the `try_` prefix to align with how `Box` and `Vec` are providing methods now. `init` is temporarily updated with uses of GFP_KERNEL. These will be updated in a subsequent patch to take flags as well. Reviewed-by: Benno Lossin Signed-off-by: Wedson Almeida Filho --- rust/kernel/init.rs | 4 ++-- rust/kernel/sync/arc.rs | 28 ++++++++++++++-------------- samples/rust/rust_print.rs | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index 9c798cffc8e4..a5911fec428b 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -1189,7 +1189,7 @@ fn try_pin_init(init: impl PinInit) -> Resul= t, E> where E: From, { - let mut this =3D UniqueArc::try_new_uninit()?; + let mut this =3D UniqueArc::new_uninit(GFP_KERNEL)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid and will not be moved, because we pin it later. @@ -1203,7 +1203,7 @@ fn try_init(init: impl Init) -> Result where E: From, { - let mut this =3D UniqueArc::try_new_uninit()?; + let mut this =3D UniqueArc::new_uninit(GFP_KERNEL)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid. diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 1252a1b630ed..b67bb876ddf7 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -16,7 +16,7 @@ //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html =20 use crate::{ - alloc::{box_ext::BoxExt, flags::*}, + alloc::{box_ext::BoxExt, Flags}, bindings, error::{self, Error}, init::{self, InPlaceInit, Init, PinInit}, @@ -58,7 +58,7 @@ /// } /// /// // Create a refcounted instance of `Example`. -/// let obj =3D Arc::try_new(Example { a: 10, b: 20 })?; +/// let obj =3D Arc::new(Example { a: 10, b: 20 }, GFP_KERNEL)?; /// /// // Get a new pointer to `obj` and increment the refcount. /// let cloned =3D obj.clone(); @@ -97,7 +97,7 @@ /// } /// } /// -/// let obj =3D Arc::try_new(Example { a: 10, b: 20 })?; +/// let obj =3D Arc::new(Example { a: 10, b: 20 }, GFP_KERNEL)?; /// obj.use_reference(); /// obj.take_over(); /// # Ok::<(), Error>(()) @@ -120,7 +120,7 @@ /// impl MyTrait for Example {} /// /// // `obj` has type `Arc`. -/// let obj: Arc =3D Arc::try_new(Example)?; +/// let obj: Arc =3D Arc::new(Example, GFP_KERNEL)?; /// /// // `coerced` has type `Arc`. /// let coerced: Arc =3D obj; @@ -163,7 +163,7 @@ unsafe impl Sync for Arc {} =20 impl Arc { /// Constructs a new reference counted instance of `T`. - pub fn try_new(contents: T) -> Result { + pub fn new(contents: T, flags: Flags) -> Result { // INVARIANT: The refcount is initialised to a non-zero value. let value =3D ArcInner { // SAFETY: There are no safety requirements for this FFI call. @@ -171,7 +171,7 @@ pub fn try_new(contents: T) -> Result= { data: contents, }; =20 - let inner =3D as BoxExt<_>>::new(value, GFP_KERNEL)?; + let inner =3D as BoxExt<_>>::new(value, flags)?; =20 // SAFETY: We just created `inner` with a reference count of 1, wh= ich is owned by the new // `Arc` object. @@ -388,7 +388,7 @@ fn from(item: Pin>) -> Self { /// e.into() /// } /// -/// let obj =3D Arc::try_new(Example)?; +/// let obj =3D Arc::new(Example, GFP_KERNEL)?; /// let cloned =3D do_something(obj.as_arc_borrow()); /// /// // Assert that both `obj` and `cloned` point to the same underlying ob= ject. @@ -412,7 +412,7 @@ fn from(item: Pin>) -> Self { /// } /// } /// -/// let obj =3D Arc::try_new(Example { a: 10, b: 20 })?; +/// let obj =3D Arc::new(Example { a: 10, b: 20 }, GFP_KERNEL)?; /// obj.as_arc_borrow().use_reference(); /// # Ok::<(), Error>(()) /// ``` @@ -500,7 +500,7 @@ fn deref(&self) -> &Self::Target { /// } /// /// fn test() -> Result> { -/// let mut x =3D UniqueArc::try_new(Example { a: 10, b: 20 })?; +/// let mut x =3D UniqueArc::new(Example { a: 10, b: 20 }, GFP_KERNEL)= ?; /// x.a +=3D 1; /// x.b +=3D 1; /// Ok(x.into()) @@ -523,7 +523,7 @@ fn deref(&self) -> &Self::Target { /// } /// /// fn test() -> Result> { -/// let x =3D UniqueArc::try_new_uninit()?; +/// let x =3D UniqueArc::new_uninit(GFP_KERNEL)?; /// Ok(x.write(Example { a: 10, b: 20 }).into()) /// } /// @@ -543,7 +543,7 @@ fn deref(&self) -> &Self::Target { /// } /// /// fn test() -> Result> { -/// let mut pinned =3D Pin::from(UniqueArc::try_new(Example { a: 10, b= : 20 })?); +/// let mut pinned =3D Pin::from(UniqueArc::new(Example { a: 10, b: 20= }, GFP_KERNEL)?); /// // We can modify `pinned` because it is `Unpin`. /// pinned.as_mut().a +=3D 1; /// Ok(pinned.into()) @@ -557,15 +557,15 @@ pub struct UniqueArc { =20 impl UniqueArc { /// Tries to allocate a new [`UniqueArc`] instance. - pub fn try_new(value: T) -> Result { + pub fn new(value: T, flags: Flags) -> Result { Ok(Self { // INVARIANT: The newly-created object has a refcount of 1. - inner: Arc::try_new(value)?, + inner: Arc::new(value, flags)?, }) } =20 /// Tries to allocate a new [`UniqueArc`] instance whose contents are = not initialised yet. - pub fn try_new_uninit() -> Result>, AllocErro= r> { + pub fn new_uninit(_flags: Flags) -> Result>, = AllocError> { // INVARIANT: The refcount is initialised to a non-zero value. let inner =3D Box::try_init::(try_init!(ArcInner { // SAFETY: There are no safety requirements for this FFI call. diff --git a/samples/rust/rust_print.rs b/samples/rust/rust_print.rs index 67ed8ebf8e8e..6eabb0d79ea3 100644 --- a/samples/rust/rust_print.rs +++ b/samples/rust/rust_print.rs @@ -18,8 +18,8 @@ fn arc_print() -> Result { use kernel::sync::*; =20 - let a =3D Arc::try_new(1)?; - let b =3D UniqueArc::try_new("hello, world")?; + let a =3D Arc::new(1, GFP_KERNEL)?; + let b =3D UniqueArc::new("hello, world", GFP_KERNEL)?; =20 // Prints the value of data in `a`. pr_info!("{}", a); --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pg1-f177.google.com (mail-pg1-f177.google.com [209.85.215.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6FD32C18F; Wed, 27 Mar 2024 02:36:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506995; cv=none; b=s3pe3AocUQFRSlOzFlmw2Oq7SSTxBvYvjqoOg3eTAP8b72RNIqxcFEcpi70W5m51UIa8Oya5HU2AteiaAehQvt6nAKdAyxX95x74PhuDUTz6HxY4L//jXCCld+ZfggmCXgmvhN+NI1BRPCHtYWW3f/vwuP5x+u05sqarumFfFMQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711506995; c=relaxed/simple; bh=/MFiKpIHCX/TkC4eO2Idl1URX2vUkxWYKlY4WkmGVbI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=tw7pqh24Z8+/QPFp7DEbOx6TI1aLGI7XWmLKGMRQx5Cem8V6iVC0U43vekHJr6zmxQG0gDRZY3VdGmH1h49Oz4RG1lUNDic8a5X7AJKjokuZ+S5frQsUCxO+z412wUl/hfWmdqQ0i7F4ES/B7qMWCTcdWp4kJmNOsumAvd4HFPQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QuGXho7T; arc=none smtp.client-ip=209.85.215.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QuGXho7T" Received: by mail-pg1-f177.google.com with SMTP id 41be03b00d2f7-5ca29c131ebso3732303a12.0; Tue, 26 Mar 2024 19:36:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506993; x=1712111793; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Su9TUxcyqp7E1w4G+ImqP9H/NVO5bEAfpZ37dB62GOI=; b=QuGXho7TMarZkBnf5ZgEumtUTWgXKI6YQI7VoLAcJxmhgqyrhaVhkKEqyR0d2aog9P FYSmznPLQoyteXxwrSMZU4Op5DWaZ6T3EOzD2xwlkIO8DcxRJWsyMRhe+tHFp3zEzpN5 Ni97CMGAiPVeNd8okIpXVBl3ju0hdBLcMHIb28hCgyFsQ3GQddbclAn7RUqxsPt4ak0t wHQKXHz+q/7s1fy9L/pxP1eQizxJXjRUkMLowXr+qazE6yCjiNWedAFaTXpt+1iKYljK RGN3Cr8c3QG+RhLVyECy6p5yFzT9NSjUmXA8PKvKL0c4KnorRq7B7eC7vP+BiXc6a27T Zv5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506993; x=1712111793; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Su9TUxcyqp7E1w4G+ImqP9H/NVO5bEAfpZ37dB62GOI=; b=p1t/tAXQ20EmXIqTh0e0r7WxiQWab256oPcEajV7ra5wQvZrSfLk98XFtoQoPeFLtK z+fjYY0grvOWCUnyFZMhD8LMYpFqtgTvCDPyW+LmZqT3ShxwXy3bXL4ggB3hdJjFnXel +HMuG85Qz3+WrVY1BmtQrfk+2N5vfovQqWx2v8C69JyKTPE1DZVnYwgm3dhzyQtRYd4u EZ6ZsKcl05DkDkPzovD5v+cu46j6LyGqAfzzJg717JW4ycl2MeZLjwdWZ8Qj5QCaKDAK lz9823o86MvraZGFAt9eflbRsEnkf4+UJWKqjh6c9kJjmsBFGiR5U2IewhII2/P/nfpz UR6g== X-Forwarded-Encrypted: i=1; AJvYcCX69a+micJMTutlgn1qv/FRtfzgx/OhDq4VqPri1ddfaufhbaLnPUttKAA04SuiV2A0CTH76sJFI/YQ8V1I5gNEbBQHbNq+uJw6vaY0 X-Gm-Message-State: AOJu0Yzv7f8D/LHDTgLh17+0NidT66bQIlgIDZJSSEfYEKT6Vc2qnPcu wX7HuJjpzwLDtgjACPwRxmjMQjY67wOQruVYyUc4nyWCSd+5IGpC8iXBvrgv X-Google-Smtp-Source: AGHT+IFPGnalkjt3Eo31tDVBROAL6FTPPNvqSU1vfmb+ndT88rEQxfjrp3qgOYaTQr2xmA6ArM1t4Q== X-Received: by 2002:a05:6a20:1587:b0:1a3:7285:a63 with SMTP id h7-20020a056a20158700b001a372850a63mr1624045pzj.55.1711506993031; Tue, 26 Mar 2024 19:36:33 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:32 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 09/10] rust: init: update `init` module to take allocation flags Date: Tue, 26 Mar 2024 23:35:30 -0300 Message-Id: <20240327023531.187880-10-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho This is the last component in the conversion for allocators to take allocation flags as parameters. Reviewed-by: Benno Lossin Signed-off-by: Wedson Almeida Filho --- rust/kernel/init.rs | 49 ++++++++++++++++--------------- rust/kernel/sync/arc.rs | 23 ++++++++------- rust/kernel/sync/condvar.rs | 2 +- rust/kernel/sync/lock/mutex.rs | 2 +- rust/kernel/sync/lock/spinlock.rs | 2 +- rust/kernel/workqueue.rs | 13 +++++--- 6 files changed, 50 insertions(+), 41 deletions(-) diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index a5911fec428b..fec47b274ec3 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -68,7 +68,7 @@ //! # a <- new_mutex!(42, "Foo::a"), //! # b: 24, //! # }); -//! let foo: Result>> =3D Box::pin_init(foo); +//! let foo: Result>> =3D Box::pin_init(foo, GFP_KERNEL); //! ``` //! //! For more information see the [`pin_init!`] macro. @@ -80,7 +80,8 @@ //! //! ```rust //! # use kernel::sync::{new_mutex, Arc, Mutex}; -//! let mtx: Result>> =3D Arc::pin_init(new_mutex!(42, "e= xample::mtx")); +//! let mtx: Result>> =3D +//! Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL); //! ``` //! //! To declare an init macro/function you just return an [`impl PinInit`]: @@ -99,7 +100,7 @@ //! fn new() -> impl PinInit { //! try_pin_init!(Self { //! status <- new_mutex!(0, "DriverData::status"), -//! buffer: Box::init(kernel::init::zeroed())?, +//! buffer: Box::init(kernel::init::zeroed(), GFP_KERNEL)?, //! }) //! } //! } @@ -210,7 +211,7 @@ //! [`pin_init!`]: crate::pin_init! =20 use crate::{ - alloc::{box_ext::BoxExt, flags::*}, + alloc::{box_ext::BoxExt, Flags}, error::{self, Error}, sync::UniqueArc, types::{Opaque, ScopeGuard}, @@ -391,7 +392,7 @@ macro_rules! stack_try_pin_init { /// }, /// }); /// # initializer } -/// # Box::pin_init(demo()).unwrap(); +/// # Box::pin_init(demo(), GFP_KERNEL).unwrap(); /// ``` /// /// Arbitrary Rust expressions can be used to set the value of a variable. @@ -461,7 +462,7 @@ macro_rules! stack_try_pin_init { /// # }) /// # } /// # } -/// let foo =3D Box::pin_init(Foo::new()); +/// let foo =3D Box::pin_init(Foo::new(), GFP_KERNEL); /// ``` /// /// They can also easily embed it into their own `struct`s: @@ -601,7 +602,7 @@ macro_rules! pin_init { /// impl BigBuf { /// fn new() -> impl PinInit { /// try_pin_init!(Self { -/// big: Box::init(init::zeroed())?, +/// big: Box::init(init::zeroed(), GFP_KERNEL)?, /// small: [0; 1024 * 1024], /// ptr: core::ptr::null_mut(), /// }? Error) @@ -702,7 +703,7 @@ macro_rules! init { /// impl BigBuf { /// fn new() -> impl Init { /// try_init!(Self { -/// big: Box::init(zeroed())?, +/// big: Box::init(zeroed(), GFP_KERNEL)?, /// small: [0; 1024 * 1024], /// }? Error) /// } @@ -1014,7 +1015,7 @@ pub fn uninit() -> impl Init, E>= { /// /// ```rust /// use kernel::{error::Error, init::init_array_from_fn}; -/// let array: Box<[usize; 1_000]> =3D Box::init::(init_array_from_= fn(|i| i)).unwrap(); +/// let array: Box<[usize; 1_000]> =3D Box::init::(init_array_from_= fn(|i| i), GFP_KERNEL).unwrap(); /// assert_eq!(array.len(), 1_000); /// ``` pub fn init_array_from_fn( @@ -1058,7 +1059,7 @@ pub fn init_array_from_fn( /// ```rust /// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mut= ex}; /// let array: Arc<[Mutex; 1_000]> =3D -/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i))).unwrap(); +/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNE= L).unwrap(); /// assert_eq!(array.len(), 1_000); /// ``` pub fn pin_init_array_from_fn( @@ -1116,7 +1117,7 @@ pub trait InPlaceInit: Sized { /// type. /// /// If `T: !Unpin` it will not be able to move afterwards. - fn try_pin_init(init: impl PinInit) -> Result, E> + fn try_pin_init(init: impl PinInit, flags: Flags) -> Result, E> where E: From; =20 @@ -1124,7 +1125,7 @@ fn try_pin_init(init: impl PinInit) -> Resul= t, E> /// type. /// /// If `T: !Unpin` it will not be able to move afterwards. - fn pin_init(init: impl PinInit) -> error::Result> + fn pin_init(init: impl PinInit, flags: Flags) -> error::Resul= t> where Error: From, { @@ -1132,16 +1133,16 @@ fn pin_init(init: impl PinInit) -> error::= Result> let init =3D unsafe { pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(= |e| Error::from(e))) }; - Self::try_pin_init(init) + Self::try_pin_init(init, flags) } =20 /// Use the given initializer to in-place initialize a `T`. - fn try_init(init: impl Init) -> Result + fn try_init(init: impl Init, flags: Flags) -> Result where E: From; =20 /// Use the given initializer to in-place initialize a `T`. - fn init(init: impl Init) -> error::Result + fn init(init: impl Init, flags: Flags) -> error::Result where Error: From, { @@ -1149,17 +1150,17 @@ fn init(init: impl Init) -> error::Result<= Self> let init =3D unsafe { init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| = Error::from(e))) }; - Self::try_init(init) + Self::try_init(init, flags) } } =20 impl InPlaceInit for Box { #[inline] - fn try_pin_init(init: impl PinInit) -> Result, E> + fn try_pin_init(init: impl PinInit, flags: Flags) -> Result, E> where E: From, { - let mut this =3D as BoxExt<_>>::new_uninit(GFP_KERNEL)?; + let mut this =3D as BoxExt<_>>::new_uninit(flags)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid and will not be moved, because we pin it later. @@ -1169,11 +1170,11 @@ fn try_pin_init(init: impl PinInit) -> Res= ult, E> } =20 #[inline] - fn try_init(init: impl Init) -> Result + fn try_init(init: impl Init, flags: Flags) -> Result where E: From, { - let mut this =3D as BoxExt<_>>::new_uninit(GFP_KERNEL)?; + let mut this =3D as BoxExt<_>>::new_uninit(flags)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid. @@ -1185,11 +1186,11 @@ fn try_init(init: impl Init) -> Result =20 impl InPlaceInit for UniqueArc { #[inline] - fn try_pin_init(init: impl PinInit) -> Result, E> + fn try_pin_init(init: impl PinInit, flags: Flags) -> Result, E> where E: From, { - let mut this =3D UniqueArc::new_uninit(GFP_KERNEL)?; + let mut this =3D UniqueArc::new_uninit(flags)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid and will not be moved, because we pin it later. @@ -1199,11 +1200,11 @@ fn try_pin_init(init: impl PinInit) -> Res= ult, E> } =20 #[inline] - fn try_init(init: impl Init) -> Result + fn try_init(init: impl Init, flags: Flags) -> Result where E: From, { - let mut this =3D UniqueArc::new_uninit(GFP_KERNEL)?; + let mut this =3D UniqueArc::new_uninit(flags)?; let slot =3D this.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but = not dropped, // slot is valid. diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index b67bb876ddf7..0866378f1360 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -182,22 +182,22 @@ pub fn new(contents: T, flags: Flags) -> Result { /// /// If `T: !Unpin` it will not be able to move afterwards. #[inline] - pub fn pin_init(init: impl PinInit) -> error::Result + pub fn pin_init(init: impl PinInit, flags: Flags) -> error::R= esult where Error: From, { - UniqueArc::pin_init(init).map(|u| u.into()) + UniqueArc::pin_init(init, flags).map(|u| u.into()) } =20 /// Use the given initializer to in-place initialize a `T`. /// /// This is equivalent to [`Arc::pin_init`], since an [`Arc`] is al= ways pinned. #[inline] - pub fn init(init: impl Init) -> error::Result + pub fn init(init: impl Init, flags: Flags) -> error::Result where Error: From, { - UniqueArc::init(init).map(|u| u.into()) + UniqueArc::init(init, flags).map(|u| u.into()) } } =20 @@ -565,13 +565,16 @@ pub fn new(value: T, flags: Flags) -> Result { } =20 /// Tries to allocate a new [`UniqueArc`] instance whose contents are = not initialised yet. - pub fn new_uninit(_flags: Flags) -> Result>, = AllocError> { + pub fn new_uninit(flags: Flags) -> Result>, A= llocError> { // INVARIANT: The refcount is initialised to a non-zero value. - let inner =3D Box::try_init::(try_init!(ArcInner { - // SAFETY: There are no safety requirements for this FFI call. - refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }), - data <- init::uninit::(), - }? AllocError))?; + let inner =3D Box::try_init::( + try_init!(ArcInner { + // SAFETY: There are no safety requirements for this FFI c= all. + refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) = }), + data <- init::uninit::(), + }? AllocError), + flags, + )?; Ok(UniqueArc { // INVARIANT: The newly-created object has a refcount of 1. // SAFETY: The pointer from the `Box` is valid. diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index 0c3671caffeb..ef6ffef0aa88 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -75,7 +75,7 @@ macro_rules! new_condvar { /// Box::pin_init(pin_init!(Example { /// value <- new_mutex!(0), /// value_changed <- new_condvar!(), -/// })) +/// }), GFP_KERNEL) /// } /// ``` /// diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs index ef4c4634d294..93e1c982facf 100644 --- a/rust/kernel/sync/lock/mutex.rs +++ b/rust/kernel/sync/lock/mutex.rs @@ -60,7 +60,7 @@ macro_rules! new_mutex { /// } /// /// // Allocate a boxed `Example`. -/// let e =3D Box::pin_init(Example::new())?; +/// let e =3D Box::pin_init(Example::new(), GFP_KERNEL)?; /// assert_eq!(e.c, 10); /// assert_eq!(e.d.lock().a, 20); /// assert_eq!(e.d.lock().b, 30); diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spin= lock.rs index 0b22c635634f..6e900807d3b7 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -58,7 +58,7 @@ macro_rules! new_spinlock { /// } /// /// // Allocate a boxed `Example`. -/// let e =3D Box::pin_init(Example::new())?; +/// let e =3D Box::pin_init(Example::new(), GFP_KERNEL)?; /// assert_eq!(e.c, 10); /// assert_eq!(e.d.lock().a, 20); /// assert_eq!(e.d.lock().b, 30); diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 544f0c51f1b7..09a0f158ff1b 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -53,7 +53,7 @@ //! Arc::pin_init(pin_init!(MyStruct { //! value, //! work <- new_work!("MyStruct::work"), -//! })) +//! }), GFP_KERNEL) //! } //! } //! @@ -101,7 +101,7 @@ //! value_2, //! work_1 <- new_work!("MyStruct::work_1"), //! work_2 <- new_work!("MyStruct::work_2"), -//! })) +//! }), GFP_KERNEL) //! } //! } //! @@ -132,6 +132,7 @@ //! //! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueu= e.h) =20 +use crate::alloc::Flags; use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Op= aque}; use alloc::alloc::AllocError; use alloc::boxed::Box; @@ -206,13 +207,17 @@ pub fn enqueue(&self, w: W) -> W::E= nqueueOutput /// Tries to spawn the given function or closure as a work item. /// /// This method can fail because it allocates memory to store the work= item. - pub fn try_spawn(&self, func: T) -> Resu= lt<(), AllocError> { + pub fn try_spawn( + &self, + flags: Flags, + func: T, + ) -> Result<(), AllocError> { let init =3D pin_init!(ClosureWork { work <- new_work!("Queue::try_spawn"), func: Some(func), }); =20 - self.enqueue(Box::pin_init(init).map_err(|_| AllocError)?); + self.enqueue(Box::pin_init(init, flags).map_err(|_| AllocError)?); Ok(()) } } --=20 2.34.1 From nobody Sat Feb 7 19:41:20 2026 Received: from mail-pg1-f175.google.com (mail-pg1-f175.google.com [209.85.215.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2B2D22C68B; Wed, 27 Mar 2024 02:36:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711507000; cv=none; b=czEY8rCxTsR6QsezsfZg46Y70DTMjvJ1LP4bpWjKpnm4GyvVZ6f5P2ESFMrol3MHMmcG/qgSsbnA7z1CIfQ3I7iNV2BS+tIcPsfv5dW4ytleg184TqzS6LhzrTQV6Y6rw6PTLulaf326iaF1+COeDVqwBaslV2oRqL4k9q2JILg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711507000; c=relaxed/simple; bh=b9alF6sEGnAWF3DsTbS3LyfyRWGhyBPjFkyJBWiDY+U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=h1rJExApjP7O85t6xkSlvhKiJUx06KYBD7cs2X9/7yU3NkHKtsDL2qFDYmObwbnmZgcTNPsGm34OIr3owaxgI9pNMjVJSH+8cW1ezMbzz5HcmeIRbAkCoDRqwrw45VmpizLO1ypBO9cL/+LlcVgTg1t/OwwhG4PwMXzn2nnRhGo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=loBNYcQA; arc=none smtp.client-ip=209.85.215.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="loBNYcQA" Received: by mail-pg1-f175.google.com with SMTP id 41be03b00d2f7-5d8ddbac4fbso4439627a12.0; Tue, 26 Mar 2024 19:36:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711506998; x=1712111798; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vQoBOKp3EwJBmRTdBR9tFZY4h3sKJNPj+YlazUqopAk=; b=loBNYcQAthazen8uJ/UfQrjk5FXJ8ykUZQ7ecNaRRs4SJgHJIxk23mD8wiCCSUgLeB 1Yehl1XjAM+ZkGv4gj6d1y/yqYVZhfBBYnAQ21+3gb4uWIXnucJScVfhkB89p3HkXWZj /bGj3HQjIT/mXD7o+C2ojqIcIgZKb65aueMiQOPPSp97WFnJyRw0Ef+rOrkyUjVGZMmV VmEmTmoKBLXSnLHZVd/N12WD8ql+EoiETeyhP/wsFfXBEaI/IhJ2VAJ9JgeCpeQh0bxz TA3oeffEAq/ROVp0nbrZNhuSfdkKRQnEFc0vEHi3K8ebu2zLPJC92M+eS+71U300Tpoy mzRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711506998; x=1712111798; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vQoBOKp3EwJBmRTdBR9tFZY4h3sKJNPj+YlazUqopAk=; b=mjOo4tM6rhfU78uGuSENM1oL0MSHIukIppLYnz1mhiYmYPVaxhxfFg8i1pvF0JRKjP 7u0d0Nuz1tht2d4WQW1kl/QLRT1cfq3gWLPq+6mgNgM1m1U0ZcGxXsJE2IcGszsfHqcS bSkxDxLSxLNvJEW7n8fNRXpjYjPWLiQaPaMHHvW3yuscp9D/IsCN94qzqNcwhJg2rP3k IBe3F01NbrCPzTNii0WYF4B/ZMbN5DB5R0ljKNhLiluK29W+Ki0WkF4VgR8Y9d/fAD2M IbVZV41VPbxdOKQqdkJEsppNvyHe9B1Sym4hxcdcDOd186yz2GDpLQHn5hUfJGufjI0N J83A== X-Forwarded-Encrypted: i=1; AJvYcCVu/zyjqAashgCBHMPvTDJ7Y8c+bbcB7rCmLaeRO79bXkviHvLwywz+IPljNSqoAOJRC4apLSOM1d6aNh6q8b/uuQIkTeTOHlMHAWyb X-Gm-Message-State: AOJu0YwJaomUSRZXfU6ouw36rkAZUwg7ewHSFog035XE3QAv7Q1jjYCp QSgl5yyO8Hh0cSGlIeG4tGkBpQuoO0OVZffwwdOWNmTXCXhLJ6LZdKrRnQqO X-Google-Smtp-Source: AGHT+IFWY2mh0CdivaeSNw4Td6JCtleJ4YJWfrzPeRqtVxSTyTnVsH8BTJXRS8fp1B4JFwtj2CsSQg== X-Received: by 2002:a17:90a:6d61:b0:29c:b540:706b with SMTP id z88-20020a17090a6d6100b0029cb540706bmr10445973pjj.17.1711506998404; Tue, 26 Mar 2024 19:36:38 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id l20-20020a17090a409400b0029b2e5bc1b9sm347441pjg.23.2024.03.26.19.36.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 19:36:38 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 10/10] rust: kernel: remove usage of `allocator_api` unstable feature Date: Tue, 26 Mar 2024 23:35:31 -0300 Message-Id: <20240327023531.187880-11-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240327023531.187880-1-wedsonaf@gmail.com> References: <20240327023531.187880-1-wedsonaf@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wedson Almeida Filho With the adoption of `BoxExt` and `VecExt`, we don't need the functions provided by this feature (namely the methods prefixed with `try_` and different allocator per collection instance). We do need `AllocError`, but we define our own as it is a trivial empty struct. Signed-off-by: Wedson Almeida Filho Reviewed-by: Benno Lossin --- rust/kernel/alloc.rs | 4 ++++ rust/kernel/alloc/box_ext.rs | 3 +-- rust/kernel/alloc/vec_ext.rs | 4 ++-- rust/kernel/error.rs | 4 ++-- rust/kernel/init.rs | 3 +-- rust/kernel/lib.rs | 1 - rust/kernel/str.rs | 3 +-- rust/kernel/sync/arc.rs | 4 ++-- rust/kernel/workqueue.rs | 3 +-- 9 files changed, 14 insertions(+), 15 deletions(-) diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index a4c4b1f79bc9..5b35786b6279 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -8,6 +8,10 @@ pub mod box_ext; pub mod vec_ext; =20 +/// Indicates an allocation error. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct AllocError; + /// Flags to be used when allocating memory. /// /// They can be combined with the operators `|`, `&`, and `!`. diff --git a/rust/kernel/alloc/box_ext.rs b/rust/kernel/alloc/box_ext.rs index aaa6a20d12b6..8dad58f23b11 100644 --- a/rust/kernel/alloc/box_ext.rs +++ b/rust/kernel/alloc/box_ext.rs @@ -2,9 +2,8 @@ =20 //! Extensions to [`Box`] for fallible allocations. =20 -use super::Flags; +use super::{AllocError, Flags}; use alloc::boxed::Box; -use core::alloc::AllocError; use core::mem::MaybeUninit; use core::result::Result; =20 diff --git a/rust/kernel/alloc/vec_ext.rs b/rust/kernel/alloc/vec_ext.rs index bb6cb1c4ea67..25305ff2fac4 100644 --- a/rust/kernel/alloc/vec_ext.rs +++ b/rust/kernel/alloc/vec_ext.rs @@ -2,8 +2,8 @@ =20 //! Extensions to [`Vec`] for fallible allocations. =20 -use super::Flags; -use alloc::{alloc::AllocError, vec::Vec}; +use super::{AllocError, Flags}; +use alloc::vec::Vec; use core::result::Result; =20 /// Extensions to [`Vec`]. diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index e53466937796..fc986bc24c6d 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -4,9 +4,9 @@ //! //! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/ua= pi/asm-generic/errno-base.h) =20 -use crate::str::CStr; +use crate::{alloc::AllocError, str::CStr}; =20 -use alloc::alloc::{AllocError, LayoutError}; +use alloc::alloc::LayoutError; =20 use core::convert::From; use core::fmt; diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index fec47b274ec3..9608f2bd2211 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -211,14 +211,13 @@ //! [`pin_init!`]: crate::pin_init! =20 use crate::{ - alloc::{box_ext::BoxExt, Flags}, + alloc::{box_ext::BoxExt, AllocError, Flags}, error::{self, Error}, sync::UniqueArc, types::{Opaque, ScopeGuard}, }; use alloc::boxed::Box; use core::{ - alloc::AllocError, cell::UnsafeCell, convert::Infallible, marker::PhantomData, diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 51f30e55bd00..5c641233e26d 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -12,7 +12,6 @@ //! do so first instead of bypassing this crate. =20 #![no_std] -#![feature(allocator_api)] #![feature(coerce_unsized)] #![feature(dispatch_from_dyn)] #![feature(new_uninit)] diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 58f2ddafb326..dfd1c40d46a2 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -2,8 +2,7 @@ =20 //! String representations. =20 -use crate::alloc::{flags::*, vec_ext::VecExt}; -use alloc::alloc::AllocError; +use crate::alloc::{flags::*, vec_ext::VecExt, AllocError}; use alloc::vec::Vec; use core::fmt::{self, Write}; use core::ops::{self, Deref, Index}; diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 0866378f1360..c2a3a2c7cbc5 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -16,7 +16,7 @@ //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html =20 use crate::{ - alloc::{box_ext::BoxExt, Flags}, + alloc::{box_ext::BoxExt, AllocError, Flags}, bindings, error::{self, Error}, init::{self, InPlaceInit, Init, PinInit}, @@ -25,7 +25,7 @@ }; use alloc::boxed::Box; use core::{ - alloc::{AllocError, Layout}, + alloc::Layout, fmt, marker::{PhantomData, Unsize}, mem::{ManuallyDrop, MaybeUninit}, diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 09a0f158ff1b..50837e56efc7 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -132,9 +132,8 @@ //! //! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueu= e.h) =20 -use crate::alloc::Flags; +use crate::alloc::{AllocError, Flags}; use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Op= aque}; -use alloc::alloc::AllocError; use alloc::boxed::Box; use core::marker::PhantomData; use core::pin::Pin; --=20 2.34.1