From 709ea7469f5093fb488607fcb966445c63d49a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=C3=AFssata?= Date: Mon, 11 Jul 2022 13:12:41 +0000 Subject: [PATCH 01/15] Add Read Impl for &Stdin --- library/std/src/io/stdio.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 261b570dee74f..e929eaa639696 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -445,6 +445,29 @@ impl Read for Stdin { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Read for &Stdin { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.lock().read(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + self.lock().read_vectored(bufs) + } + #[inline] + fn is_read_vectored(&self) -> bool { + self.lock().is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.lock().read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + self.lock().read_to_string(buf) + } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + self.lock().read_exact(buf) + } +} + // only used by platform-dependent io::copy specializations, i.e. unused on some platforms #[cfg(any(target_os = "linux", target_os = "android"))] impl StdinLock<'_> { From 8ea292278aadcbd923e317fc39447fd6ad2f0b6c Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 9 Aug 2023 14:36:54 +0100 Subject: [PATCH 02/15] Make `impl` impl take `?Sized` --- library/std/src/os/fd/owned.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 24f2bdcf4217c..06b3c4583bf1b 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -244,7 +244,7 @@ pub trait AsFd { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsFd for &T { +impl AsFd for &T { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { T::as_fd(self) @@ -252,7 +252,7 @@ impl AsFd for &T { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsFd for &mut T { +impl AsFd for &mut T { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { T::as_fd(self) @@ -396,7 +396,7 @@ impl From for crate::net::UdpSocket { /// impl MyTrait for Box {} /// # } /// ``` -impl AsFd for crate::sync::Arc { +impl AsFd for crate::sync::Arc { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() @@ -404,7 +404,7 @@ impl AsFd for crate::sync::Arc { } #[stable(feature = "asfd_rc", since = "1.69.0")] -impl AsFd for crate::rc::Rc { +impl AsFd for crate::rc::Rc { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() @@ -412,7 +412,7 @@ impl AsFd for crate::rc::Rc { } #[stable(feature = "asfd_ptrs", since = "1.64.0")] -impl AsFd for Box { +impl AsFd for Box { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() From f4aeb7030993f5c143e9a84c50061892f6b7046f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 28 Jan 2024 23:31:55 +0000 Subject: [PATCH 03/15] Make `impl` impl take `?Sized` --- library/std/src/os/windows/io/handle.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index b0540872c0b62..55c3913904432 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -422,7 +422,7 @@ pub trait AsHandle { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsHandle for &T { +impl AsHandle for &T { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { T::as_handle(self) @@ -430,7 +430,7 @@ impl AsHandle for &T { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsHandle for &mut T { +impl AsHandle for &mut T { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { T::as_handle(self) @@ -450,7 +450,7 @@ impl AsHandle for &mut T { /// impl MyTrait for Box {} /// # } /// ``` -impl AsHandle for crate::sync::Arc { +impl AsHandle for crate::sync::Arc { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { (**self).as_handle() @@ -458,7 +458,7 @@ impl AsHandle for crate::sync::Arc { } #[stable(feature = "as_windows_ptrs", since = "1.71.0")] -impl AsHandle for crate::rc::Rc { +impl AsHandle for crate::rc::Rc { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { (**self).as_handle() @@ -466,7 +466,7 @@ impl AsHandle for crate::rc::Rc { } #[stable(feature = "as_windows_ptrs", since = "1.71.0")] -impl AsHandle for Box { +impl AsHandle for Box { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { (**self).as_handle() From e49cd1c578227e450f0a703b08fa429e3931c228 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 21 Feb 2024 15:56:50 +0000 Subject: [PATCH 04/15] TryReserveError to ErrorKind::OutOfMemory --- library/std/src/io/error.rs | 12 ++++++++++++ library/std/src/io/tests.rs | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 13cc0511e103e..7ae15e0fd017e 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -83,6 +83,18 @@ impl From for Error { } } +#[stable(feature = "io_error_from_try_reserve", since = "CURRENT_RUSTC_VERSION")] +impl From for Error { + /// Converts `TryReserveError` to an error with [`ErrorKind::OutOfMemory`]. + /// + /// `TryReserveError` won't be available as the error `source()`, + /// but this may change in the future. + fn from(_: alloc::collections::TryReserveError) -> Error { + // ErrorData::Custom allocates, which isn't great for handling OOM errors. + ErrorKind::OutOfMemory.into() + } +} + // Only derive debug in tests, to make sure it // doesn't accidentally get printed. #[cfg_attr(test, derive(Debug))] diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 5396f7f6e216c..c306de3039fc3 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -692,3 +692,13 @@ fn read_buf_full_read() { assert_eq!(BufReader::new(FullRead).fill_buf().unwrap().len(), DEFAULT_BUF_SIZE); } + +#[test] +// 64-bit only to be sure the allocator will fail fast on an impossible to satsify size +#[cfg(target_pointer_width = "64")] +fn try_oom_error() { + let mut v = Vec::::new(); + let reserve_err = v.try_reserve(isize::MAX as usize - 1).unwrap_err(); + let io_err = io::Error::from(reserve_err); + assert_eq!(io::ErrorKind::OutOfMemory, io_err.kind()); +} From aa581f0a0a3fbb61efe1f37786c237b2733dfbfa Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 21 Feb 2024 15:59:41 +0000 Subject: [PATCH 05/15] Remove unnecessary map_err --- library/std/src/fs.rs | 8 ++++---- library/std/src/io/buffered/bufreader.rs | 2 +- library/std/src/io/impls.rs | 4 ++-- library/std/src/io/mod.rs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 6b1dd1b5af4c9..fee529993715b 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -261,7 +261,7 @@ pub fn read>(path: P) -> io::Result> { let mut file = File::open(path)?; let size = file.metadata().map(|m| m.len() as usize).ok(); let mut bytes = Vec::new(); - bytes.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + bytes.try_reserve_exact(size.unwrap_or(0))?; io::default_read_to_end(&mut file, &mut bytes, size)?; Ok(bytes) } @@ -304,7 +304,7 @@ pub fn read_to_string>(path: P) -> io::Result { let mut file = File::open(path)?; let size = file.metadata().map(|m| m.len() as usize).ok(); let mut string = String::new(); - string.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + string.try_reserve_exact(size.unwrap_or(0))?; io::default_read_to_string(&mut file, &mut string, size)?; Ok(string) } @@ -777,14 +777,14 @@ impl Read for &File { // Reserves space in the buffer based on the file size when available. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let size = buffer_capacity_required(self); - buf.try_reserve(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + buf.try_reserve(size.unwrap_or(0))?; io::default_read_to_end(self, buf, size) } // Reserves space in the buffer based on the file size when available. fn read_to_string(&mut self, buf: &mut String) -> io::Result { let size = buffer_capacity_required(self); - buf.try_reserve(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + buf.try_reserve(size.unwrap_or(0))?; io::default_read_to_string(self, buf, size) } } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index e0dc9f96ae9b2..83db332ee2558 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -344,7 +344,7 @@ impl Read for BufReader { // delegate to the inner implementation. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let inner_buf = self.buffer(); - buf.try_reserve(inner_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?; + buf.try_reserve(inner_buf.len())?; buf.extend_from_slice(inner_buf); let nread = inner_buf.len(); self.discard_buffer(); diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 557e64dc8674e..cb972abd2b821 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -304,7 +304,7 @@ impl Read for &[u8] { #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let len = self.len(); - buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?; + buf.try_reserve(len)?; buf.extend_from_slice(*self); *self = &self[len..]; Ok(len) @@ -452,7 +452,7 @@ impl Read for VecDeque { fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { // The total len is known upfront so we can reserve it in a single call. let len = self.len(); - buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?; + buf.try_reserve(len)?; let (front, back) = self.as_slices(); buf.extend_from_slice(front); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 102db62fced34..0d1c2702b7829 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -465,7 +465,7 @@ pub(crate) fn default_read_to_end( if buf.len() == buf.capacity() { // buf is full, need more space - buf.try_reserve(PROBE_SIZE).map_err(|_| ErrorKind::OutOfMemory)?; + buf.try_reserve(PROBE_SIZE)?; } let mut spare = buf.spare_capacity_mut(); @@ -834,7 +834,7 @@ pub trait Read { /// if src_buf.is_empty() { /// break; /// } - /// dest_vec.try_reserve(src_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?; + /// dest_vec.try_reserve(src_buf.len())?; /// dest_vec.extend_from_slice(src_buf); /// /// // Any irreversible side effects should happen after `try_reserve` succeeds, From ea476b1fa1cd42f5ee10a4d6cc95d6bbaf63ce86 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 23 Feb 2024 22:41:21 +0300 Subject: [PATCH 06/15] on the fly type casting for `build.rustc` and `build.cargo` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 834025c81887e..3461beba0bd0a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -811,8 +811,8 @@ define_config! { host: Option> = "host", target: Option> = "target", build_dir: Option = "build-dir", - cargo: Option = "cargo", - rustc: Option = "rustc", + cargo: Option = "cargo", + rustc: Option = "rustc", rustfmt: Option = "rustfmt", docs: Option = "docs", compiler_docs: Option = "compiler-docs", @@ -1421,7 +1421,7 @@ impl Config { if !flags.skip_stage0_validation { config.check_stage0_version(&rustc, "rustc"); } - PathBuf::from(rustc) + rustc } else { config.download_beta_toolchain(); config.out.join(config.build.triple).join("stage0/bin/rustc") @@ -1431,7 +1431,7 @@ impl Config { if !flags.skip_stage0_validation { config.check_stage0_version(&cargo, "cargo"); } - PathBuf::from(cargo) + cargo } else { config.download_beta_toolchain(); config.out.join(config.build.triple).join("stage0/bin/cargo") @@ -2292,7 +2292,7 @@ impl Config { } // check rustc/cargo version is same or lower with 1 apart from the building one - pub fn check_stage0_version(&self, program_path: &str, component_name: &'static str) { + pub fn check_stage0_version(&self, program_path: &Path, component_name: &'static str) { if self.dry_run() { return; } @@ -2303,7 +2303,8 @@ impl Config { let stage0_name = stage0_output.next().unwrap(); if stage0_name != component_name { fail(&format!( - "Expected to find {component_name} at {program_path} but it claims to be {stage0_name}" + "Expected to find {component_name} at {} but it claims to be {stage0_name}", + program_path.display() )); } From b921a34f1738a615c17db513868b6c5219f32893 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 25 Feb 2024 23:47:10 -0800 Subject: [PATCH 07/15] Fix stable feature name and stabilization version of Read for &Stdin --- library/std/src/io/stdio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index e929eaa639696..6920281f24bf2 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -445,7 +445,7 @@ impl Read for Stdin { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "read_shared_stdin", since = "CURRENT_RUSTC_VERSION")] impl Read for &Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.lock().read(buf) From b18280f9d5d07ff1a1b5352924c383c1ed3024e9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 25 Feb 2024 23:50:00 -0800 Subject: [PATCH 08/15] Fill in Read::read_buf for &Stdin --- library/std/src/io/stdio.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 6920281f24bf2..19ed03056a2f9 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -450,6 +450,9 @@ impl Read for &Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.lock().read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.lock().read_buf(buf) + } fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.lock().read_vectored(bufs) } From 228347878ebd45d5cb7e6f424bad18eb0b92543a Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 27 Feb 2024 18:54:18 -0300 Subject: [PATCH 09/15] Implement junction_point --- library/std/src/fs/tests.rs | 12 +-- library/std/src/os/windows/fs.rs | 12 +++ library/std/src/sys/pal/windows/c.rs | 11 --- library/std/src/sys/pal/windows/fs.rs | 132 ++++++++++++++------------ 4 files changed, 86 insertions(+), 81 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 5917bf8df029e..a65e78542bf20 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -20,11 +20,9 @@ use crate::os::unix::fs::symlink as symlink_dir; #[cfg(unix)] use crate::os::unix::fs::symlink as symlink_file; #[cfg(unix)] -use crate::os::unix::fs::symlink as symlink_junction; +use crate::os::unix::fs::symlink as junction_point; #[cfg(windows)] -use crate::os::windows::fs::{symlink_dir, symlink_file, OpenOptionsExt}; -#[cfg(windows)] -use crate::sys::fs::symlink_junction; +use crate::os::windows::fs::{junction_point, symlink_dir, symlink_file, OpenOptionsExt}; #[cfg(target_os = "macos")] use crate::sys::weak::weak; @@ -598,7 +596,7 @@ fn recursive_rmdir() { check!(fs::create_dir_all(&dtt)); check!(fs::create_dir_all(&d2)); check!(check!(File::create(&canary)).write(b"foo")); - check!(symlink_junction(&d2, &dt.join("d2"))); + check!(junction_point(&d2, &dt.join("d2"))); let _ = symlink_file(&canary, &d1.join("canary")); check!(fs::remove_dir_all(&d1)); @@ -615,7 +613,7 @@ fn recursive_rmdir_of_symlink() { let canary = dir.join("do_not_delete"); check!(fs::create_dir_all(&dir)); check!(check!(File::create(&canary)).write(b"foo")); - check!(symlink_junction(&dir, &link)); + check!(junction_point(&dir, &link)); check!(fs::remove_dir_all(&link)); assert!(!link.is_dir()); @@ -1403,7 +1401,7 @@ fn create_dir_all_with_junctions() { fs::create_dir(&target).unwrap(); - check!(symlink_junction(&target, &junction)); + check!(junction_point(&target, &junction)); check!(fs::create_dir_all(&b)); // the junction itself is not a directory, but `is_dir()` on a Path // follows links diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index e9d7a13e9d5b2..27947d91c99de 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -620,3 +620,15 @@ pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io: pub fn symlink_dir, Q: AsRef>(original: P, link: Q) -> io::Result<()> { sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true) } + +/// Create a junction point. +/// +/// The `link` path will be a directory junction pointing to the original path. +/// If `link` is a relative path then it will be made absolute prior to creating the junction point. +/// The `original` path must be a directory or a link to a directory, otherwise the junction point will be broken. +/// +/// If either path is not a local file path then this will fail. +#[unstable(feature = "junction_point", issue = "121709")] +pub fn junction_point, Q: AsRef>(original: P, link: Q) -> io::Result<()> { + sys::fs::junction_point(original.as_ref(), link.as_ref()) +} diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index b007796722baf..abdbc0ad315d9 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -25,7 +25,6 @@ pub type UINT = c_uint; pub type WCHAR = u16; pub type USHORT = c_ushort; pub type SIZE_T = usize; -pub type WORD = u16; pub type CHAR = c_char; pub type ULONG = c_ulong; @@ -142,16 +141,6 @@ pub struct MOUNT_POINT_REPARSE_BUFFER { pub PrintNameLength: c_ushort, pub PathBuffer: WCHAR, } -#[repr(C)] -pub struct REPARSE_MOUNTPOINT_DATA_BUFFER { - pub ReparseTag: DWORD, - pub ReparseDataLength: DWORD, - pub Reserved: WORD, - pub ReparseTargetLength: WORD, - pub ReparseTargetMaximumLength: WORD, - pub Reserved1: WORD, - pub ReparseTarget: WCHAR, -} #[repr(C)] pub struct SOCKADDR_STORAGE_LH { diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 3a9e7b4660b36..e92c5e80eac9c 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -1,7 +1,9 @@ +use core::ptr::addr_of; + use crate::os::windows::prelude::*; use crate::borrow::Cow; -use crate::ffi::{c_void, OsString}; +use crate::ffi::{c_void, OsStr, OsString}; use crate::fmt; use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem::{self, MaybeUninit}; @@ -1446,75 +1448,79 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { Ok(size as u64) } -#[allow(dead_code)] -pub fn symlink_junction, Q: AsRef>( - original: P, - junction: Q, -) -> io::Result<()> { - symlink_junction_inner(original.as_ref(), junction.as_ref()) -} - -// Creating a directory junction on windows involves dealing with reparse -// points and the DeviceIoControl function, and this code is a skeleton of -// what can be found here: -// -// http://www.flexhex.com/docs/articles/hard-links.phtml -#[allow(dead_code)] -fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> { - let d = DirBuilder::new(); - d.mkdir(junction)?; - +pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { + // Create and open a new directory in one go. let mut opts = OpenOptions::new(); + opts.create_new(true); opts.write(true); - opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); - let f = File::open(junction, &opts)?; - let h = f.as_inner().as_raw_handle(); - unsafe { - let mut data = - Align8([MaybeUninit::::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]); - let data_ptr = data.0.as_mut_ptr(); - let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize); - let db = data_ptr.cast::(); - // Zero the header to ensure it's fully initialized, including reserved parameters. - *db = mem::zeroed(); - let reparse_target_slice = { - let buf_start = ptr::addr_of_mut!((*db).ReparseTarget).cast::(); - // Compute offset in bytes and then divide so that we round down - // rather than hit any UB (admittedly this arithmetic should work - // out so that this isn't necessary) - let buf_len_bytes = usize::try_from(data_end.byte_offset_from(buf_start)).unwrap(); - let buf_len_wchars = buf_len_bytes / core::mem::size_of::(); - core::slice::from_raw_parts_mut(buf_start, buf_len_wchars) - }; - - // FIXME: this conversion is very hacky - let iter = br"\??\" - .iter() - .map(|x| *x as u16) - .chain(original.as_os_str().encode_wide()) - .chain(core::iter::once(0)); - let mut i = 0; - for c in iter { - if i >= reparse_target_slice.len() { - return Err(crate::io::const_io_error!( - crate::io::ErrorKind::InvalidFilename, - "Input filename is too long" - )); - } - reparse_target_slice[i] = c; - i += 1; + opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_POSIX_SEMANTICS); + opts.attributes(c::FILE_ATTRIBUTE_DIRECTORY); + + let d = File::open(link, &opts)?; + + // We need to get an absolute, NT-style path. + let path_bytes = original.as_os_str().as_encoded_bytes(); + let abs_path: Vec = if path_bytes.starts_with(br"\\?\") || path_bytes.starts_with(br"\??\") + { + // It's already an absolute path, we just need to convert the prefix to `\??\` + let bytes = unsafe { OsStr::from_encoded_bytes_unchecked(&path_bytes[4..]) }; + r"\??\".encode_utf16().chain(bytes.encode_wide()).collect() + } else { + // Get an absolute path and then convert the prefix to `\??\` + let abs_path = crate::path::absolute(original)?.into_os_string().into_encoded_bytes(); + if abs_path.len() > 0 && abs_path[1..].starts_with(br":\") { + let bytes = unsafe { OsStr::from_encoded_bytes_unchecked(&abs_path) }; + r"\??\".encode_utf16().chain(bytes.encode_wide()).collect() + } else if abs_path.starts_with(br"\\.\") { + let bytes = unsafe { OsStr::from_encoded_bytes_unchecked(&abs_path[4..]) }; + r"\??\".encode_utf16().chain(bytes.encode_wide()).collect() + } else if abs_path.starts_with(br"\\") { + let bytes = unsafe { OsStr::from_encoded_bytes_unchecked(&abs_path[2..]) }; + r"\??\UNC\".encode_utf16().chain(bytes.encode_wide()).collect() + } else { + return Err(io::const_io_error!(io::ErrorKind::InvalidInput, "path is not valid")); } - (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT; - (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD; - (*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD; - (*db).ReparseDataLength = (*db).ReparseTargetLength as c::DWORD + 12; + }; + // Defined inline so we don't have to mess about with variable length buffer. + #[repr(C)] + pub struct MountPointBuffer { + ReparseTag: u32, + ReparseDataLength: u16, + Reserved: u16, + SubstituteNameOffset: u16, + SubstituteNameLength: u16, + PrintNameOffset: u16, + PrintNameLength: u16, + PathBuffer: [MaybeUninit; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize], + } + let data_len = 12 + (abs_path.len() * 2); + if data_len > u16::MAX as usize { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "`original` path is too long" + )); + } + let data_len = data_len as u16; + let mut header = MountPointBuffer { + ReparseTag: c::IO_REPARSE_TAG_MOUNT_POINT, + ReparseDataLength: data_len, + Reserved: 0, + SubstituteNameOffset: 0, + SubstituteNameLength: (abs_path.len() * 2) as u16, + PrintNameOffset: ((abs_path.len() + 1) * 2) as u16, + PrintNameLength: 0, + PathBuffer: [MaybeUninit::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize], + }; + unsafe { + let ptr = header.PathBuffer.as_mut_ptr(); + ptr.copy_from(abs_path.as_ptr().cast::>(), abs_path.len()); let mut ret = 0; cvt(c::DeviceIoControl( - h as *mut _, + d.as_raw_handle(), c::FSCTL_SET_REPARSE_POINT, - data_ptr.cast(), - (*db).ReparseDataLength + 8, + addr_of!(header).cast::(), + data_len as u32 + 8, ptr::null_mut(), 0, &mut ret, From f27a22c24a51ba734e4eb25c499320d819ebe236 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 30 Jan 2024 15:58:08 +0000 Subject: [PATCH 10/15] try_with_capacity for RawVec --- library/alloc/src/raw_vec.rs | 36 +++++++++++++++++------------- library/alloc/src/raw_vec/tests.rs | 7 +++--- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index dd8d6f6c7e634..2d86fa377f16d 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -17,7 +17,6 @@ use crate::collections::TryReserveErrorKind::*; #[cfg(test)] mod tests; -#[cfg(not(no_global_oom_handling))] enum AllocInit { /// The contents of the new memory are uninitialized. Uninitialized, @@ -93,6 +92,8 @@ impl RawVec { /// zero-sized. Note that if `T` is zero-sized this means you will /// *not* get a `RawVec` with the requested capacity. /// + /// Non-fallible version of `try_with_capacity` + /// /// # Panics /// /// Panics if the requested capacity exceeds `isize::MAX` bytes. @@ -104,7 +105,7 @@ impl RawVec { #[must_use] #[inline] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global)) } /// Like `with_capacity`, but guarantees the buffer is zeroed. @@ -142,7 +143,7 @@ impl 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) + handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc)) } /// Like `with_capacity_zeroed`, but parameterized over the choice @@ -150,7 +151,7 @@ impl 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) + handle_reserve(Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc)) } /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. @@ -179,35 +180,40 @@ impl RawVec { } } - #[cfg(not(no_global_oom_handling))] - fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { + fn try_allocate_in( + capacity: usize, + init: AllocInit, + alloc: A, + ) -> Result { // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. + if T::IS_ZST || capacity == 0 { - Self::new_in(alloc) + Ok(Self::new_in(alloc)) } else { // We avoid `unwrap_or_else` here because it bloats the amount of // LLVM IR generated. let layout = match Layout::array::(capacity) { Ok(layout) => layout, - Err(_) => capacity_overflow(), + Err(_) => return Err(CapacityOverflow.into()), }; - match alloc_guard(layout.size()) { - Ok(_) => {} - Err(_) => capacity_overflow(), + + if let Err(err) = alloc_guard(layout.size()) { + return Err(err); } + let result = match init { AllocInit::Uninitialized => alloc.allocate(layout), AllocInit::Zeroed => alloc.allocate_zeroed(layout), }; let ptr = match result { Ok(ptr) => ptr, - Err(_) => handle_alloc_error(layout), + Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()), }; // Allocators currently return a `NonNull<[u8]>` whose length // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / mem::size_of::()`. - Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc } + Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }) } } @@ -537,11 +543,11 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { // Central function for reserve error handling. #[cfg(not(no_global_oom_handling))] #[inline] -fn handle_reserve(result: Result<(), TryReserveError>) { +fn handle_reserve(result: Result) -> T { match result.map_err(|e| e.kind()) { + Ok(res) => res, Err(CapacityOverflow) => capacity_overflow(), Err(AllocError { layout, .. }) => handle_alloc_error(layout), - Ok(()) => { /* yay */ } } } diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index f8cada01c0309..4194be530612d 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -105,13 +105,14 @@ fn zst() { let v: RawVec = RawVec::with_capacity_in(100, Global); zst_sanity(&v); - let v: RawVec = RawVec::allocate_in(0, AllocInit::Uninitialized, Global); + let v: RawVec = RawVec::try_allocate_in(0, AllocInit::Uninitialized, Global).unwrap(); zst_sanity(&v); - let v: RawVec = RawVec::allocate_in(100, AllocInit::Uninitialized, Global); + let v: RawVec = RawVec::try_allocate_in(100, AllocInit::Uninitialized, Global).unwrap(); zst_sanity(&v); - let mut v: RawVec = RawVec::allocate_in(usize::MAX, AllocInit::Uninitialized, Global); + let mut v: RawVec = + RawVec::try_allocate_in(usize::MAX, AllocInit::Uninitialized, Global).unwrap(); zst_sanity(&v); // Check all these operations work as expected with zero-sized elements. From 78fb977d6b600865b7887245d24f6dca22a0099a Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 30 Jan 2024 16:08:57 +0000 Subject: [PATCH 11/15] try_with_capacity for Vec, VecDeque, String #91913 --- .../alloc/src/collections/vec_deque/mod.rs | 24 +++++++++++++ library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec.rs | 9 +++++ library/alloc/src/string.rs | 13 +++++++ library/alloc/src/vec/mod.rs | 34 ++++++++++++++++++ library/alloc/tests/lib.rs | 1 + library/alloc/tests/string.rs | 11 ++++++ library/alloc/tests/vec.rs | 12 +++++++ library/alloc/tests/vec_deque.rs | 11 ++++++ tests/codegen/vec-with-capacity.rs | 35 +++++++++++++++++++ tests/ui/suggestions/deref-path-method.stderr | 4 +-- tests/ui/ufcs/bad-builder.stderr | 4 +-- 12 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 tests/codegen/vec-with-capacity.rs diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c35bab5ef6657..41adc2e79dc74 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -559,6 +559,30 @@ impl VecDeque { pub fn with_capacity(capacity: usize) -> VecDeque { Self::with_capacity_in(capacity, Global) } + + /// Creates an empty deque with space for at least `capacity` elements. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + /// + /// # Examples + /// + /// ``` + /// # #![feature(try_with_capacity)] + /// # #[allow(unused)] + /// # fn example() -> Result<(), std::collections::TryReserveError> { + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque = VecDeque::try_with_capacity(10)?; + /// # Ok(()) } + /// ``` + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result, TryReserveError> { + Ok(VecDeque { head: 0, len: 0, buf: RawVec::try_with_capacity_in(capacity, Global)? }) + } } impl VecDeque { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 28695ade5bf55..ca504b05a9689 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -163,6 +163,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] +#![feature(try_with_capacity)] #![feature(tuple_trait)] #![feature(unchecked_math)] #![feature(unicode_internals)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 2d86fa377f16d..c5cf12209d90a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -20,6 +20,7 @@ mod tests; enum AllocInit { /// The contents of the new memory are uninitialized. Uninitialized, + #[cfg(not(no_global_oom_handling))] /// The new memory is guaranteed to be zeroed. Zeroed, } @@ -146,6 +147,13 @@ impl RawVec { handle_reserve(Self::try_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))] @@ -203,6 +211,7 @@ impl RawVec { let result = match init { AllocInit::Uninitialized => alloc.allocate(layout), + #[cfg(not(no_global_oom_handling))] AllocInit::Zeroed => alloc.allocate_zeroed(layout), }; let ptr = match result { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 98ded7f6cdf5b..c4dcff1b1c49c 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -492,6 +492,19 @@ impl String { String { vec: Vec::with_capacity(capacity) } } + /// Creates a new empty `String` with at least the specified capacity. + /// + /// # Errors + /// + /// Returns [`Err`] if the capacity exceeds `isize::MAX` bytes, + /// or if the memory allocator reports failure. + /// + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result { + Ok(String { vec: Vec::try_with_capacity(capacity)? }) + } + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is // required for this method definition, is not available. Since we don't // require this method for testing purposes, I'll just stub it diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 7bd19875584a3..4b8b095c752f7 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -481,6 +481,22 @@ impl Vec { Self::with_capacity_in(capacity, Global) } + /// Constructs a new, empty `Vec` with at least the specified capacity. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result { + Self::try_with_capacity_in(capacity, Global) + } + /// Creates a `Vec` directly from a pointer, a length, and a capacity. /// /// # Safety @@ -672,6 +688,24 @@ impl Vec { Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } } + /// Constructs a new, empty `Vec` with at least the specified capacity + /// with the provided allocator. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result { + Ok(Vec { buf: RawVec::try_with_capacity_in(capacity, alloc)?, len: 0 }) + } + /// Creates a `Vec` directly from a pointer, a length, a capacity, /// and an allocator. /// diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index c4e89a58a05ac..e4e1a02fd8325 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -20,6 +20,7 @@ #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] +#![feature(try_with_capacity)] #![feature(unboxed_closures)] #![feature(associated_type_bounds)] #![feature(binary_heap_into_iter_sorted)] diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs index 711e4eef2e724..e20ceae87b0d5 100644 --- a/library/alloc/tests/string.rs +++ b/library/alloc/tests/string.rs @@ -723,6 +723,17 @@ fn test_reserve_exact() { assert!(s.capacity() >= 33) } +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_with_capacity() { + let string = String::try_with_capacity(1000).unwrap(); + assert_eq!(0, string.len()); + assert!(string.capacity() >= 1000 && string.capacity() <= isize::MAX as usize); + + assert!(String::try_with_capacity(usize::MAX).is_err()); +} + #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 15ee4d6520523..aa95b4e977081 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1694,6 +1694,18 @@ fn test_reserve_exact() { assert!(v.capacity() >= 33) } +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_with_capacity() { + let mut vec: Vec = Vec::try_with_capacity(5).unwrap(); + assert_eq!(0, vec.len()); + assert!(vec.capacity() >= 5 && vec.capacity() <= isize::MAX as usize / 4); + assert!(vec.spare_capacity_mut().len() >= 5); + + assert!(Vec::::try_with_capacity(isize::MAX as usize + 1).is_err()); +} + #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index eda2f8bb812b5..cea5de4dd5984 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1182,6 +1182,17 @@ fn test_reserve_exact_2() { assert!(v.capacity() >= 33) } +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_with_capacity() { + let vec: VecDeque = VecDeque::try_with_capacity(5).unwrap(); + assert_eq!(0, vec.len()); + assert!(vec.capacity() >= 5 && vec.capacity() <= isize::MAX as usize / 4); + + assert!(VecDeque::::try_with_capacity(isize::MAX as usize + 1).is_err()); +} + #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc diff --git a/tests/codegen/vec-with-capacity.rs b/tests/codegen/vec-with-capacity.rs new file mode 100644 index 0000000000000..47051f2eef891 --- /dev/null +++ b/tests/codegen/vec-with-capacity.rs @@ -0,0 +1,35 @@ +//@ compile-flags: -O +//@ ignore-debug +// (with debug assertions turned on, `assert_unchecked` generates a real assertion) + +#![crate_type = "lib"] +#![feature(try_with_capacity)] + +// CHECK-LABEL: @with_capacity_does_not_grow1 +#[no_mangle] +pub fn with_capacity_does_not_grow1() -> Vec { + let v = Vec::with_capacity(1234); + // CHECK: call {{.*}}__rust_alloc( + // CHECK-NOT: call {{.*}}__rust_realloc + // CHECK-NOT: call {{.*}}capacity_overflow + // CHECK-NOT: call {{.*}}finish_grow + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: memcpy + // CHECK-NOT: memset + v +} + +// CHECK-LABEL: @try_with_capacity_does_not_grow2 +#[no_mangle] +pub fn try_with_capacity_does_not_grow2() -> Option>> { + let v = Vec::try_with_capacity(1234).ok()?; + // CHECK: call {{.*}}__rust_alloc( + // CHECK-NOT: call {{.*}}__rust_realloc + // CHECK-NOT: call {{.*}}capacity_overflow + // CHECK-NOT: call {{.*}}finish_grow + // CHECK-NOT: call {{.*}}handle_alloc_error + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Some(v) +} diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index a2b68fa966fcb..b27d9aef06614 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -7,9 +7,9 @@ LL | Vec::contains(&vec, &0); note: if you're trying to build a new `Vec<_, _>` consider using one of the following associated functions: Vec::::new Vec::::with_capacity + Vec::::try_with_capacity Vec::::from_raw_parts - Vec::::new_in - and 2 others + and 4 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr index e1c5e45b3ebb7..9cfeb7a5d09d6 100644 --- a/tests/ui/ufcs/bad-builder.stderr +++ b/tests/ui/ufcs/bad-builder.stderr @@ -7,9 +7,9 @@ LL | Vec::::mew() note: if you're trying to build a new `Vec` consider using one of the following associated functions: Vec::::new Vec::::with_capacity + Vec::::try_with_capacity Vec::::from_raw_parts - Vec::::new_in - and 2 others + and 4 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: there is an associated function `new` with a similar name | From 784e6a1e080e5ba18e5c246e744e2d20525d1c3d Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 31 Jan 2024 15:23:52 +0000 Subject: [PATCH 12/15] Move capacity_overflow function to make ui tests change less Code changes in raw_vec require blessing UI tests every time --- library/alloc/src/raw_vec.rs | 18 +++++++++--------- tests/ui/hygiene/panic-location.run.stderr | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index c5cf12209d90a..5e37de18c954f 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -17,6 +17,15 @@ use crate::collections::TryReserveErrorKind::*; #[cfg(test)] mod tests; +// One central function responsible for reporting capacity overflows. This'll +// ensure that the code generation related to these panics is minimal as there's +// only one location which panics rather than a bunch throughout the module. +#[cfg(not(no_global_oom_handling))] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +fn capacity_overflow() -> ! { + panic!("capacity overflow"); +} + enum AllocInit { /// The contents of the new memory are uninitialized. Uninitialized, @@ -576,12 +585,3 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { Ok(()) } } - -// One central function responsible for reporting capacity overflows. This'll -// ensure that the code generation related to these panics is minimal as there's -// only one location which panics rather than a bunch throughout the module. -#[cfg(not(no_global_oom_handling))] -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -fn capacity_overflow() -> ! { - panic!("capacity overflow"); -} diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5c552411da7f3..ec0ce18c3dfa7 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:26:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From 0a0074980fb7802ac621ceac92bf98bdc640bd78 Mon Sep 17 00:00:00 2001 From: Andrew Wock Date: Sun, 18 Feb 2024 18:06:16 -0500 Subject: [PATCH 13/15] Implement MaybeUninit::fill{,_with,_from} ACP: rust-lang/libs-team#156 Signed-off-by: Andrew Wock --- library/core/src/mem/maybe_uninit.rs | 202 +++++++++++++++++++++++-- library/core/tests/lib.rs | 1 + library/core/tests/mem.rs | 217 ++++++++++++++++++++++++++- 3 files changed, 398 insertions(+), 22 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index c19b5791562ce..026e21586d403 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1125,22 +1125,6 @@ impl MaybeUninit { // unlike copy_from_slice this does not call clone_from_slice on the slice // this is because `MaybeUninit` does not implement Clone. - struct Guard<'a, T> { - slice: &'a mut [MaybeUninit], - initialized: usize, - } - - impl<'a, T> Drop for Guard<'a, T> { - fn drop(&mut self) { - let initialized_part = &mut self.slice[..self.initialized]; - // SAFETY: this raw slice will contain only initialized objects - // that's why, it is allowed to drop it. - unsafe { - crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part)); - } - } - } - assert_eq!(this.len(), src.len(), "destination and source slices have different lengths"); // NOTE: We need to explicitly slice them to the same length // for bounds checking to be elided, and the optimizer will @@ -1162,6 +1146,151 @@ impl MaybeUninit { unsafe { MaybeUninit::slice_assume_init_mut(this) } } + /// Fills `this` with elements by cloning `value`, returning a mutable reference to the now + /// initialized contents of `this`. + /// Any previously initialized elements will not be dropped. + /// + /// This is similar to [`slice::fill`]. + /// + /// # Panics + /// + /// This function will panic if any call to `Clone` panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with 1. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 10]; + /// let initialized = MaybeUninit::fill(buf.as_mut_slice(), 1); + /// assert_eq!(initialized, &mut [1; 10]); + /// ``` + #[doc(alias = "memset")] + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill<'a>(this: &'a mut [MaybeUninit], value: T) -> &'a mut [T] + where + T: Clone, + { + SpecFill::spec_fill(this, value); + // SAFETY: Valid elements have just been filled into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Fills `this` with elements returned by calling a closure repeatedly. + /// + /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use + /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can + /// pass [`Default::default`] as the argument. + /// + /// # Panics + /// + /// This function will panic if any call to the provided closure panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with the default value. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::::uninit(); 10]; + /// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default); + /// assert_eq!(initialized, &mut [0; 10]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit], mut f: F) -> &'a mut [T] + where + F: FnMut() -> T, + { + let mut guard = Guard { slice: this, initialized: 0 }; + + for element in guard.slice.iter_mut() { + element.write(f()); + guard.initialized += 1; + } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Fills `this` with elements yielded by an iterator until either all elements have been + /// initialized or the iterator is empty. + /// + /// Returns two slices. The first slice contains the initialized portion of the original slice. + /// The second slice is the still-uninitialized remainder of the original slice. + /// + /// # Panics + /// + /// This function panics if the iterator's `next` function panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with a cycling iterator. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// + /// let iter = [1, 2, 3].into_iter().cycle(); + /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); + /// + /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); + /// assert_eq!(0, remainder.len()); + /// ``` + /// + /// Fill an uninit vec, but not completely. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// let iter = [1, 2]; + /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); + /// + /// assert_eq!(initialized, &mut [1, 2]); + /// assert_eq!(remainder.len(), 3); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill_from<'a, I>( + this: &'a mut [MaybeUninit], + it: I, + ) -> (&'a mut [T], &'a mut [MaybeUninit]) + where + I: IntoIterator, + { + let iter = it.into_iter(); + let mut guard = Guard { slice: this, initialized: 0 }; + + for (element, val) in guard.slice.iter_mut().zip(iter) { + element.write(val); + guard.initialized += 1; + } + + let initialized_len = guard.initialized; + super::forget(guard); + + // SAFETY: guard.initialized <= this.len() + let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) }; + + // SAFETY: Valid elements have just been written into `init`, so that portion + // of `this` is initialized. + (unsafe { MaybeUninit::slice_assume_init_mut(initted) }, remainder) + } + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still @@ -1315,3 +1444,44 @@ impl [MaybeUninit; N] { unsafe { intrinsics::transmute_unchecked(self) } } } + +struct Guard<'a, T> { + slice: &'a mut [MaybeUninit], + initialized: usize, +} + +impl<'a, T> Drop for Guard<'a, T> { + fn drop(&mut self) { + let initialized_part = &mut self.slice[..self.initialized]; + // SAFETY: this raw sub-slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part)); + } + } +} + +trait SpecFill { + fn spec_fill(&mut self, value: T); +} + +impl SpecFill for [MaybeUninit] { + default fn spec_fill(&mut self, value: T) { + let mut guard = Guard { slice: self, initialized: 0 }; + + if let Some((last, elems)) = guard.slice.split_last_mut() { + for el in elems { + el.write(value.clone()); + guard.initialized += 1; + } + + last.write(value); + } + super::forget(guard); + } +} + +impl SpecFill for [MaybeUninit] { + fn spec_fill(&mut self, value: T) { + self.fill(MaybeUninit::new(value)); + } +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index fa0e9a979d060..c5a7e87c4aa4f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -54,6 +54,7 @@ #![feature(slice_from_ptr_range)] #![feature(slice_split_once)] #![feature(split_as_slice)] +#![feature(maybe_uninit_fill)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] #![feature(maybe_uninit_uninit_array_transpose)] diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 0f7fde747690a..e388800f400df 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -308,21 +308,226 @@ fn uninit_write_slice_cloned_mid_panic() { } } +#[derive(Clone)] +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + panic!("dropped a bomb! kaboom!") + } +} + #[test] fn uninit_write_slice_cloned_no_drop() { - #[derive(Clone)] - struct Bomb; + let mut dst = [MaybeUninit::uninit()]; + let src = [Bomb]; + + MaybeUninit::clone_from_slice(&mut dst, &src); + + forget(src); +} + +#[test] +fn uninit_fill() { + let mut dst = [MaybeUninit::new(255); 64]; + let expect = [0; 64]; + + assert_eq!(MaybeUninit::fill(&mut dst, 0), &expect); +} + +#[cfg(panic = "unwind")] +struct CloneUntilPanic { + limit: usize, + rc: Rc<()>, +} - impl Drop for Bomb { - fn drop(&mut self) { - panic!("dropped a bomb! kaboom") +#[cfg(panic = "unwind")] +impl Clone for CloneUntilPanic { + fn clone(&self) -> Self { + if Rc::strong_count(&self.rc) >= self.limit { + panic!("expected panic on clone"); } + Self { limit: self.limit, rc: self.rc.clone() } } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_clone_panic_drop() { + use std::panic; + + let rc = Rc::new(()); + + let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; + + let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; + let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { + MaybeUninit::fill(&mut dst, src); + })); + + match err { + Ok(_) => unreachable!(), + Err(payload) => { + payload + .downcast::<&'static str>() + .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) }) + .unwrap_or_else(|p| panic::resume_unwind(p)); + assert_eq!(Rc::strong_count(&rc), 1) + } + } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_clone_no_drop_clones() { + let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; + + MaybeUninit::fill(&mut dst, Bomb); +} + +#[test] +fn uninit_fill_with() { + let mut dst = [MaybeUninit::new(255); 64]; + let expect = [0; 64]; + + assert_eq!(MaybeUninit::fill_with(&mut dst, || 0), &expect); +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_with_mid_panic() { + use std::panic; + + let rc = Rc::new(()); + + let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; + + let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; + let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { + MaybeUninit::fill_with(&mut dst, || src.clone()); + })); + + drop(src); + + match err { + Ok(_) => unreachable!(), + Err(payload) => { + payload + .downcast::<&'static str>() + .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) }) + .unwrap_or_else(|p| panic::resume_unwind(p)); + assert_eq!(Rc::strong_count(&rc), 1) + } + } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_with_no_drop() { + let mut dst = [MaybeUninit::uninit()]; + let src = Bomb; + + MaybeUninit::fill_with(&mut dst, || src.clone()); + + forget(src); +} + +#[test] +fn uninit_fill_from() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 64]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src); + assert_eq!(remainder.len(), 0); +} + +#[test] +fn uninit_fill_from_partial() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 48]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src); + assert_eq!(remainder.len(), 16); +} + +#[test] +fn uninit_over_fill() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 72]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src[0..64]); + assert_eq!(remainder.len(), 0); +} + +#[test] +fn uninit_empty_fill() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 0]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src[0..0]); + assert_eq!(remainder.len(), 64); +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_from_mid_panic() { + use std::panic; + + struct IterUntilPanic { + limit: usize, + rc: Rc<()>, + } + + impl Iterator for IterUntilPanic { + type Item = Rc<()>; + fn next(&mut self) -> Option { + if Rc::strong_count(&self.rc) >= self.limit { + panic!("expected panic on next"); + } + Some(self.rc.clone()) + } + } + + let rc = Rc::new(()); + + let mut dst = [ + MaybeUninit::uninit(), + MaybeUninit::uninit(), + MaybeUninit::uninit(), + MaybeUninit::uninit(), + ]; + + let src = IterUntilPanic { limit: 3, rc: rc.clone() }; + + let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { + MaybeUninit::fill_from(&mut dst, src); + })); + + match err { + Ok(_) => unreachable!(), + Err(payload) => { + payload + .downcast::<&'static str>() + .and_then(|s| if *s == "expected panic on next" { Ok(s) } else { Err(s) }) + .unwrap_or_else(|p| panic::resume_unwind(p)); + + assert_eq!(Rc::strong_count(&rc), 1) + } + } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_from_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = [Bomb]; - MaybeUninit::clone_from_slice(&mut dst, &src); + MaybeUninit::fill_from(&mut dst, src.iter()); forget(src); } From 52501c2a75143ca18eed4d4a72463c27dae450fd Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 23 Feb 2024 16:37:47 +0300 Subject: [PATCH 14/15] bump itertools to 0.12 still depend on 0.11: * clippy * rustfmt, sigh --- Cargo.lock | 27 +++++++++++------------ compiler/rustc_ast_passes/Cargo.toml | 2 +- compiler/rustc_ast_pretty/Cargo.toml | 2 +- compiler/rustc_borrowck/Cargo.toml | 2 +- compiler/rustc_codegen_llvm/Cargo.toml | 2 +- compiler/rustc_codegen_ssa/Cargo.toml | 2 +- compiler/rustc_hir_analysis/Cargo.toml | 2 +- compiler/rustc_hir_typeck/Cargo.toml | 2 +- compiler/rustc_mir_build/Cargo.toml | 2 +- compiler/rustc_mir_transform/Cargo.toml | 2 +- compiler/rustc_passes/Cargo.toml | 1 - compiler/rustc_trait_selection/Cargo.toml | 2 +- compiler/rustc_transmute/Cargo.toml | 2 +- compiler/rustc_ty_utils/Cargo.toml | 2 +- src/librustdoc/Cargo.toml | 2 +- 15 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 853acd1abd6dd..074c33cfb5962 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3497,7 +3497,7 @@ dependencies = [ name = "rustc_ast_passes" version = "0.0.0" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "rustc_ast", "rustc_ast_pretty", "rustc_attr", @@ -3517,7 +3517,7 @@ dependencies = [ name = "rustc_ast_pretty" version = "0.0.0" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "rustc_ast", "rustc_lexer", "rustc_span", @@ -3558,7 +3558,7 @@ name = "rustc_borrowck" version = "0.0.0" dependencies = [ "either", - "itertools 0.11.0", + "itertools 0.12.1", "polonius-engine", "rustc_data_structures", "rustc_errors", @@ -3611,7 +3611,7 @@ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ "bitflags 2.4.2", - "itertools 0.11.0", + "itertools 0.12.1", "libc", "measureme", "object", @@ -3647,7 +3647,7 @@ dependencies = [ "ar_archive_writer", "bitflags 2.4.2", "cc", - "itertools 0.11.0", + "itertools 0.12.1", "jobserver", "libc", "object", @@ -3929,7 +3929,7 @@ dependencies = [ name = "rustc_hir_analysis" version = "0.0.0" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "rustc_arena", "rustc_ast", "rustc_attr", @@ -3968,7 +3968,7 @@ dependencies = [ name = "rustc_hir_typeck" version = "0.0.0" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "rustc_ast", "rustc_ast_ir", "rustc_attr", @@ -4255,7 +4255,7 @@ name = "rustc_mir_build" version = "0.0.0" dependencies = [ "either", - "itertools 0.11.0", + "itertools 0.12.1", "rustc_apfloat", "rustc_arena", "rustc_ast", @@ -4302,7 +4302,7 @@ name = "rustc_mir_transform" version = "0.0.0" dependencies = [ "either", - "itertools 0.11.0", + "itertools 0.12.1", "rustc_arena", "rustc_ast", "rustc_attr", @@ -4382,7 +4382,6 @@ dependencies = [ name = "rustc_passes" version = "0.0.0" dependencies = [ - "itertools 0.11.0", "rustc_ast", "rustc_ast_pretty", "rustc_attr", @@ -4632,7 +4631,7 @@ name = "rustc_trait_selection" version = "0.0.0" dependencies = [ "bitflags 2.4.2", - "itertools 0.11.0", + "itertools 0.12.1", "rustc_ast", "rustc_ast_ir", "rustc_attr", @@ -4672,7 +4671,7 @@ dependencies = [ name = "rustc_transmute" version = "0.0.0" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "rustc_ast_ir", "rustc_data_structures", "rustc_hir", @@ -4688,7 +4687,7 @@ dependencies = [ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "rustc_ast_ir", "rustc_data_structures", "rustc_errors", @@ -4738,7 +4737,7 @@ dependencies = [ "askama", "expect-test", "indexmap", - "itertools 0.11.0", + "itertools 0.12.1", "minifier", "once_cell", "regex", diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 99e79f65fb4ab..eace5ce820892 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.11" +itertools = "0.12" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index b38a2915a43df..9ae5c9b3cec6c 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.11" +itertools = "0.12" rustc_ast = { path = "../rustc_ast" } rustc_lexer = { path = "../rustc_lexer" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 714f46270f92c..bafc62c7318b4 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1.5.0" -itertools = "0.11" +itertools = "0.12" polonius-engine = "0.13.0" rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 3948a49ee2aa7..3fda59e8b5234 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -9,7 +9,7 @@ test = false [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -itertools = "0.11" +itertools = "0.12" libc = "0.2" measureme = "11" object = { version = "0.32.0", default-features = false, features = ["std", "read"] } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 81ca42e1ad802..7851b9e8e038c 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" ar_archive_writer = "0.1.5" bitflags = "2.4.1" cc = "1.0.90" -itertools = "0.11" +itertools = "0.12" jobserver = "0.1.28" pathdiff = "0.2.0" regex = "1.4" diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 648b569a217f0..04ca7f123d3e0 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -9,7 +9,7 @@ doctest = false [dependencies] # tidy-alphabetical-start -itertools = "0.11" +itertools = "0.12" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 0a5fa37ed04fa..9e7f0776b6087 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.11" +itertools = "0.12" rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index d71f712132205..6618e4f5a0024 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1" -itertools = "0.11" +itertools = "0.12" rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 9cc083edb44e3..bd0a54ef3638a 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1" -itertools = "0.11" +itertools = "0.12" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 80e6c104bd46d..6abfa08c53080 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.11" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 3a58d41fcd0a4..811eb4c98104e 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -itertools = "0.11.0" +itertools = "0.12" rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index 3d0ad31747ff7..79939d62a51a6 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -29,5 +29,5 @@ rustc = [ [dev-dependencies] # tidy-alphabetical-start -itertools = "0.11" +itertools = "0.12" # tidy-alphabetical-end diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 2a30bd5d53907..01d5251bfa0cc 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.11" +itertools = "0.12" rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index e13e95ef70888..bd0fbef998b2b 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,7 +9,7 @@ path = "lib.rs" [dependencies] arrayvec = { version = "0.7", default-features = false } askama = { version = "0.12", default-features = false, features = ["config"] } -itertools = "0.11" +itertools = "0.12" indexmap = "2" minifier = "0.3.0" once_cell = "1.10.0" From 2de98c8b7ea10df2f827d94d7eab0b03df9df01c Mon Sep 17 00:00:00 2001 From: klensy Date: Wed, 28 Feb 2024 12:41:11 +0300 Subject: [PATCH 15/15] remove unused derive_more dep --- Cargo.lock | 9 --------- compiler/rustc_middle/Cargo.toml | 1 - src/tools/tidy/src/deps.rs | 1 - 3 files changed, 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 074c33cfb5962..a2a4df2744400 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -784,12 +784,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "core" version = "0.0.0" @@ -1035,10 +1029,8 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", "proc-macro2", "quote", - "rustc_version", "syn 1.0.109", ] @@ -4217,7 +4209,6 @@ name = "rustc_middle" version = "0.0.0" dependencies = [ "bitflags 2.4.2", - "derive_more", "either", "field-offset", "gsgdt", diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 5a24a7ab0bd55..96c58ef411b71 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -derive_more = "0.99.17" either = "1.5.0" field-offset = "0.3.5" gsgdt = "0.1.2" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 79bc380c1e9b3..10fdfc0a65f75 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -209,7 +209,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "cc", "cfg-if", "compiler_builtins", - "convert_case", // dependency of derive_more "cpufeatures", "crc32fast", "crossbeam-channel",