diff options
| author | BenjaminBrienen <Benjamin.Brienen@outlook.com> | 2025-04-04 18:37:21 +0200 |
|---|---|---|
| committer | BenjaminBrienen <Benjamin.Brienen@outlook.com> | 2025-04-06 23:55:12 +0200 |
| commit | 6c52687dc38229a717a7eb6fe53eba35fec08bd0 (patch) | |
| tree | ff085eabd2d1027823392ddb734ab7168cf15b28 /src/tools/rust-analyzer | |
| parent | 099d0e09cf6409847dc9ceea8452e8e14c677376 (diff) | |
| download | rust-6c52687dc38229a717a7eb6fe53eba35fec08bd0.tar.gz rust-6c52687dc38229a717a7eb6fe53eba35fec08bd0.zip | |
upstream stdx changes
Diffstat (limited to 'src/tools/rust-analyzer')
| -rw-r--r-- | src/tools/rust-analyzer/Cargo.lock | 4 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/Cargo.toml | 2 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/anymap.rs | 95 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/lib.rs | 31 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/non_empty_vec.rs | 6 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/panic_context.rs | 2 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/process.rs | 3 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/rand.rs | 7 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/thread.rs | 38 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/thread/intent.rs | 19 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs | 21 |
11 files changed, 131 insertions, 97 deletions
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index b6a32d5b642..0d509f55ce2 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1083,9 +1083,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jod-thread" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" +checksum = "a037eddb7d28de1d0fc42411f501b53b75838d313908078d6698d064f3029b24" [[package]] name = "kqueue" diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml index 76033308fe5..7bda106764b 100644 --- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml @@ -13,7 +13,7 @@ rust-version.workspace = true [dependencies] backtrace = { version = "0.3.74", optional = true } -jod-thread = "0.1.2" +jod-thread = "1.0.0" crossbeam-channel.workspace = true itertools.workspace = true tracing.workspace = true diff --git a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs index 0c39419133f..f55698ecb05 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs @@ -1,4 +1,5 @@ //! This file is a port of only the necessary features from <https://github.com/chris-morgan/anymap> version 1.0.0-beta.2 for use within rust-analyzer. +//! //! Copyright © 2014–2022 Chris Morgan. //! COPYING: <https://github.com/chris-morgan/anymap/blob/master/COPYING> //! Note that the license is changed from Blue Oak Model 1.0.0 or MIT or Apache-2.0 to MIT OR Apache-2.0 @@ -20,14 +21,14 @@ use core::hash::Hasher; -/// A hasher designed to eke a little more speed out, given `TypeId`’s known characteristics. +/// A hasher designed to eke a little more speed out, given `TypeId`'s known characteristics. /// -/// Specifically, this is a no-op hasher that expects to be fed a u64’s worth of +/// Specifically, this is a no-op hasher that expects to be fed a u64's worth of /// randomly-distributed bits. It works well for `TypeId` (eliminating start-up time, so that my -/// get_missing benchmark is ~30ns rather than ~900ns, and being a good deal faster after that, so -/// that my insert_and_get_on_260_types benchmark is ~12μs instead of ~21.5μs), but will +/// `get_missing` benchmark is ~30ns rather than ~900ns, and being a good deal faster after that, so +/// that my `insert_and_get_on_260_types` benchmark is ~12μs instead of ~21.5μs), but will /// panic in debug mode and always emit zeros in release mode for any other sorts of inputs, so -/// yeah, don’t use it! 😀 +/// yeah, don't use it! 😀 #[derive(Default)] pub struct TypeIdHasher { value: u64, @@ -36,9 +37,9 @@ pub struct TypeIdHasher { impl Hasher for TypeIdHasher { #[inline] fn write(&mut self, bytes: &[u8]) { - // This expects to receive exactly one 64-bit value, and there’s no realistic chance of - // that changing, but I don’t want to depend on something that isn’t expressly part of the - // contract for safety. But I’m OK with release builds putting everything in one bucket + // This expects to receive exactly one 64-bit value, and there's no realistic chance of + // that changing, but I don't want to depend on something that isn't expressly part of the + // contract for safety. But I'm OK with release builds putting everything in one bucket // if it *did* change (and debug builds panicking). debug_assert_eq!(bytes.len(), 8); let _ = bytes.try_into().map(|array| self.value = u64::from_ne_bytes(array)); @@ -59,7 +60,7 @@ use ::std::collections::hash_map; /// Raw access to the underlying `HashMap`. /// /// This alias is provided for convenience because of the ugly third generic parameter. -#[allow(clippy::disallowed_types)] // Uses a custom hasher +#[expect(clippy::disallowed_types, reason = "Uses a custom hasher")] pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>; /// A collection containing zero or one values for any given type and allowing convenient, @@ -73,19 +74,20 @@ pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeId /// /// Cumulatively, there are thus six forms of map: /// -/// - <code>[Map]<dyn [core::any::Any]></code>, +/// - `[Map]<dyn [core::any::Any]>`, /// also spelled [`AnyMap`] for convenience. -/// - <code>[Map]<dyn [core::any::Any] + Send></code> -/// - <code>[Map]<dyn [core::any::Any] + Send + Sync></code> +/// - `[Map]<dyn [core::any::Any] + Send>` +/// - `[Map]<dyn [core::any::Any] + Send + Sync>` /// /// ## Example /// -/// (Here using the [`AnyMap`] convenience alias; the first line could use -/// <code>[anymap::Map][Map]::<[core::any::Any]>::new()</code> instead if desired.) +/// (Here, the [`AnyMap`] convenience alias is used; +/// the first line could use `[anymap::Map][Map]::<[core::any::Any]>::new()` +/// instead if desired.) /// /// ``` /// # use stdx::anymap; -#[doc = "let mut data = anymap::AnyMap::new();"] +/// let mut data = anymap::AnyMap::new(); /// assert_eq!(data.get(), None::<&i32>); /// ``` /// @@ -95,11 +97,11 @@ pub struct Map<A: ?Sized + Downcast = dyn Any> { raw: RawMap<A>, } -/// The most common type of `Map`: just using `Any`; <code>[Map]<dyn [Any]></code>. +/// The most common type of `Map`: just using `Any`; `[Map]<dyn [Any]>`. /// /// Why is this a separate type alias rather than a default value for `Map<A>`? -/// `Map::new()` doesn’t seem to be happy to infer that it should go with the default -/// value. It’s a bit sad, really. Ah well, I guess this approach will do. +/// `Map::new()` doesn't seem to be happy to infer that it should go with the default +/// value. It's a bit sad, really. Ah well, I guess this approach will do. pub type AnyMap = Map<dyn Any>; impl<A: ?Sized + Downcast> Default for Map<A> { @@ -113,6 +115,7 @@ impl<A: ?Sized + Downcast> Map<A> { /// Returns a reference to the value stored in the collection for the type `T`, /// if it exists. #[inline] + #[must_use] pub fn get<T: IntoBox<A>>(&self) -> Option<&T> { self.raw.get(&TypeId::of::<T>()).map(|any| unsafe { any.downcast_ref_unchecked::<T>() }) } @@ -132,30 +135,30 @@ impl<A: ?Sized + Downcast> Map<A> { } /// A view into a single occupied location in an `Map`. -pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> { - inner: hash_map::OccupiedEntry<'a, TypeId, Box<A>>, +pub struct OccupiedEntry<'map, A: ?Sized + Downcast, V: 'map> { + inner: hash_map::OccupiedEntry<'map, TypeId, Box<A>>, type_: PhantomData<V>, } /// A view into a single empty location in an `Map`. -pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { - inner: hash_map::VacantEntry<'a, TypeId, Box<A>>, +pub struct VacantEntry<'map, A: ?Sized + Downcast, V: 'map> { + inner: hash_map::VacantEntry<'map, TypeId, Box<A>>, type_: PhantomData<V>, } /// A view into a single location in an `Map`, which may be vacant or occupied. -pub enum Entry<'a, A: ?Sized + Downcast, V> { +pub enum Entry<'map, A: ?Sized + Downcast, V> { /// An occupied Entry - Occupied(OccupiedEntry<'a, A, V>), + Occupied(OccupiedEntry<'map, A, V>), /// A vacant Entry - Vacant(VacantEntry<'a, A, V>), + Vacant(VacantEntry<'map, A, V>), } -impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> Entry<'a, A, V> { +impl<'map, A: ?Sized + Downcast, V: IntoBox<A>> Entry<'map, A, V> { /// Ensures a value is in the entry by inserting the result of the default function if /// empty, and returns a mutable reference to the value in the entry. #[inline] - pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V { + pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'map mut V { match self { Entry::Occupied(inner) => inner.into_mut(), Entry::Vacant(inner) => inner.insert(default()), @@ -163,20 +166,21 @@ impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> Entry<'a, A, V> { } } -impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> OccupiedEntry<'a, A, V> { - /// Converts the OccupiedEntry into a mutable reference to the value in the entry +impl<'map, A: ?Sized + Downcast, V: IntoBox<A>> OccupiedEntry<'map, A, V> { + /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry /// with a lifetime bound to the collection itself #[inline] - pub fn into_mut(self) -> &'a mut V { + #[must_use] + pub fn into_mut(self) -> &'map mut V { unsafe { self.inner.into_mut().downcast_mut_unchecked() } } } -impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> VacantEntry<'a, A, V> { - /// Sets the value of the entry with the VacantEntry's key, +impl<'map, A: ?Sized + Downcast, V: IntoBox<A>> VacantEntry<'map, A, V> { + /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it #[inline] - pub fn insert(self, value: V) -> &'a mut V { + pub fn insert(self, value: V) -> &'map mut V { unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() } } } @@ -201,14 +205,13 @@ mod tests { #[test] fn type_id_hasher() { use core::any::TypeId; - use core::hash::Hash; + use core::hash::Hash as _; fn verify_hashing_with(type_id: TypeId) { let mut hasher = TypeIdHasher::default(); type_id.hash(&mut hasher); - // SAFETY: u64 is valid for all bit patterns. - let _ = hasher.finish(); + _ = hasher.finish(); } - // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c. + // Pick a variety of types, just to demonstrate it's all sane. Normal, zero-sized, unsized, &c. verify_hashing_with(TypeId::of::<usize>()); verify_hashing_with(TypeId::of::<()>()); verify_hashing_with(TypeId::of::<str>()); @@ -220,34 +223,34 @@ mod tests { /// Methods for downcasting from an `Any`-like trait object. /// /// This should only be implemented on trait objects for subtraits of `Any`, though you can -/// implement it for other types and it’ll work fine, so long as your implementation is correct. +/// implement it for other types and it'll work fine, so long as your implementation is correct. pub trait Downcast { /// Gets the `TypeId` of `self`. fn type_id(&self) -> TypeId; // Note the bound through these downcast methods is 'static, rather than the inexpressible // concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding - // TypeId’s requirements. Sure, you *can* do CloneAny.downcast_unchecked::<NotClone>() and the - // type system won’t protect you, but that doesn’t introduce any unsafety: the method is + // TypeId's requirements. Sure, you *can* do CloneAny.downcast_unchecked::<NotClone>() and the + // type system won't protect you, but that doesn't introduce any unsafety: the method is // already unsafe because you can specify the wrong type, and if this were exposing safe // downcasting, CloneAny.downcast::<NotClone>() would just return an error, which is just as // correct. // - // Now in theory we could also add T: ?Sized, but that doesn’t play nicely with the common - // implementation, so I’m doing without it. + // Now in theory we could also add T: ?Sized, but that doesn't play nicely with the common + // implementation, so I'm doing without it. /// Downcast from `&Any` to `&T`, without checking the type matches. /// /// # Safety /// - /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behavior*. unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T; /// Downcast from `&mut Any` to `&mut T`, without checking the type matches. /// /// # Safety /// - /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behavior*. unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T; } @@ -267,12 +270,12 @@ macro_rules! implement { #[inline] unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T { - unsafe { &*(self as *const Self as *const T) } + unsafe { &*std::ptr::from_ref::<Self>(self).cast::<T>() } } #[inline] unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T { - unsafe { &mut *(self as *mut Self as *mut T) } + unsafe { &mut *std::ptr::from_mut::<Self>(self).cast::<T>() } } } diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs index 982be40dd42..9a292eacd7f 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs @@ -17,7 +17,7 @@ pub mod thread; pub use itertools; #[inline(always)] -pub fn is_ci() -> bool { +pub const fn is_ci() -> bool { option_env!("CI").is_some() } @@ -26,14 +26,14 @@ pub fn hash_once<Hasher: std::hash::Hasher + Default>(thing: impl std::hash::Has } #[must_use] -#[allow(clippy::print_stderr)] +#[expect(clippy::print_stderr, reason = "only visible to developers")] pub fn timeit(label: &'static str) -> impl Drop { let start = Instant::now(); - defer(move || eprintln!("{}: {:.2?}", label, start.elapsed())) + defer(move || eprintln!("{}: {:.2}", label, start.elapsed().as_nanos())) } /// Prints backtrace to stderr, useful for debugging. -#[allow(clippy::print_stderr)] +#[expect(clippy::print_stderr, reason = "only visible to developers")] pub fn print_backtrace() { #[cfg(feature = "backtrace")] eprintln!("{:?}", backtrace::Backtrace::new()); @@ -126,6 +126,7 @@ where } // Taken from rustc. +#[must_use] pub fn to_camel_case(ident: &str) -> String { ident .trim_matches('_') @@ -156,7 +157,7 @@ pub fn to_camel_case(ident: &str) -> String { camel_cased_component }) - .fold((String::new(), None), |(acc, prev): (_, Option<String>), next| { + .fold((String::new(), None), |(mut acc, prev): (_, Option<String>), next| { // separate two components with an underscore if their boundary cannot // be distinguished using an uppercase/lowercase case distinction let join = prev @@ -166,16 +167,20 @@ pub fn to_camel_case(ident: &str) -> String { Some(!char_has_case(l) && !char_has_case(f)) }) .unwrap_or(false); - (acc + if join { "_" } else { "" } + &next, Some(next)) + acc.push_str(if join { "_" } else { "" }); + acc.push_str(&next); + (acc, Some(next)) }) .0 } // Taken from rustc. -pub fn char_has_case(c: char) -> bool { +#[must_use] +pub const fn char_has_case(c: char) -> bool { c.is_lowercase() || c.is_uppercase() } +#[must_use] pub fn is_upper_snake_case(s: &str) -> bool { s.chars().all(|c| c.is_uppercase() || c == '_' || c.is_numeric()) } @@ -188,6 +193,7 @@ pub fn replace(buf: &mut String, from: char, to: &str) { *buf = buf.replace(from, to); } +#[must_use] pub fn trim_indent(mut text: &str) -> String { if text.starts_with('\n') { text = &text[1..]; @@ -249,8 +255,8 @@ impl ops::DerefMut for JodChild { impl Drop for JodChild { fn drop(&mut self) { - let _ = self.0.kill(); - let _ = self.0.wait(); + _ = self.0.kill(); + _ = self.0.wait(); } } @@ -259,12 +265,11 @@ impl JodChild { command.spawn().map(Self) } + #[must_use] + #[cfg(not(target_arch = "wasm32"))] pub fn into_inner(self) -> std::process::Child { - if cfg!(target_arch = "wasm32") { - panic!("no processes on wasm"); - } // SAFETY: repr transparent, except on WASM - unsafe { std::mem::transmute::<JodChild, std::process::Child>(self) } + unsafe { std::mem::transmute::<Self, std::process::Child>(self) } } } diff --git a/src/tools/rust-analyzer/crates/stdx/src/non_empty_vec.rs b/src/tools/rust-analyzer/crates/stdx/src/non_empty_vec.rs index 342194c7838..faa322d9e74 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/non_empty_vec.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/non_empty_vec.rs @@ -8,8 +8,8 @@ pub struct NonEmptyVec<T> { impl<T> NonEmptyVec<T> { #[inline] - pub fn new(first: T) -> Self { - NonEmptyVec { first, rest: Vec::new() } + pub const fn new(first: T) -> Self { + Self { first, rest: Vec::new() } } #[inline] @@ -24,7 +24,7 @@ impl<T> NonEmptyVec<T> { #[inline] pub fn push(&mut self, value: T) { - self.rest.push(value) + self.rest.push(value); } #[inline] diff --git a/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs b/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs index a35d50b78df..b220451c45a 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs @@ -16,7 +16,7 @@ impl Drop for PanicContext { } pub fn enter(frame: String) -> PanicContext { - #[allow(clippy::print_stderr)] + #[expect(clippy::print_stderr, reason = "already panicking anyway")] fn set_hook() { let default_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| { diff --git a/src/tools/rust-analyzer/crates/stdx/src/process.rs b/src/tools/rust-analyzer/crates/stdx/src/process.rs index 3b3955c72ca..2efeed45e44 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/process.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/process.rs @@ -54,6 +54,9 @@ pub fn streaming_output( Ok((stdout, stderr)) } +/// # Panics +/// +/// Panics if `cmd` is not configured to have `stdout` and `stderr` as `piped`. pub fn spawn_with_streaming_output( mut cmd: Command, on_stdout_line: &mut dyn FnMut(&str), diff --git a/src/tools/rust-analyzer/crates/stdx/src/rand.rs b/src/tools/rust-analyzer/crates/stdx/src/rand.rs index 115a073dab3..e028990900a 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/rand.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/rand.rs @@ -1,8 +1,7 @@ -//! We don't use `rand`, as that's too many things for us. +//! We don't use `rand` because that is too many things for us. //! -//! We currently use oorandom instead, but it's missing these two utilities. -//! Perhaps we should switch to `fastrand`, or our own small PRNG, it's not like -//! we need anything more complicated than xor-shift. +//! `oorandom` is used instead, but it's missing these two utilities. +//! Switching to `fastrand` or our own small PRNG may be good because only xor-shift is needed. pub fn shuffle<T>(slice: &mut [T], mut rand_index: impl FnMut(usize) -> usize) { let mut remaining = slice.len() - 1; diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread.rs b/src/tools/rust-analyzer/crates/stdx/src/thread.rs index e577eb43137..6c742fecf1b 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/thread.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/thread.rs @@ -1,12 +1,12 @@ //! A utility module for working with threads that automatically joins threads upon drop -//! and abstracts over operating system quality of service (QoS) APIs +//! and abstracts over operating system quality of service (`QoS`) APIs //! through the concept of a “thread intent”. //! //! The intent of a thread is frozen at thread creation time, //! i.e. there is no API to change the intent of a thread once it has been spawned. //! //! As a system, rust-analyzer should have the property that -//! old manual scheduling APIs are replaced entirely by QoS. +//! old manual scheduling APIs are replaced entirely by `QoS`. //! To maintain this invariant, we panic when it is clear that //! old scheduling APIs have been used. //! @@ -23,10 +23,12 @@ mod pool; pub use intent::ThreadIntent; pub use pool::Pool; +/// # Panics +/// +/// Panics if failed to spawn the thread. pub fn spawn<F, T>(intent: ThreadIntent, f: F) -> JoinHandle<T> where - F: FnOnce() -> T, - F: Send + 'static, + F: (FnOnce() -> T) + Send + 'static, T: Send + 'static, { Builder::new(intent).spawn(f).expect("failed to spawn thread") @@ -39,26 +41,29 @@ pub struct Builder { } impl Builder { - pub fn new(intent: ThreadIntent) -> Builder { - Builder { intent, inner: jod_thread::Builder::new(), allow_leak: false } + #[must_use] + pub fn new(intent: ThreadIntent) -> Self { + Self { intent, inner: jod_thread::Builder::new(), allow_leak: false } } - pub fn name(self, name: String) -> Builder { - Builder { inner: self.inner.name(name), ..self } + #[must_use] + pub fn name(self, name: String) -> Self { + Self { inner: self.inner.name(name), ..self } } - pub fn stack_size(self, size: usize) -> Builder { - Builder { inner: self.inner.stack_size(size), ..self } + #[must_use] + pub fn stack_size(self, size: usize) -> Self { + Self { inner: self.inner.stack_size(size), ..self } } - pub fn allow_leak(self, b: bool) -> Builder { - Builder { allow_leak: b, ..self } + #[must_use] + pub fn allow_leak(self, allow_leak: bool) -> Self { + Self { allow_leak, ..self } } pub fn spawn<F, T>(self, f: F) -> std::io::Result<JoinHandle<T>> where - F: FnOnce() -> T, - F: Send + 'static, + F: (FnOnce() -> T) + Send + 'static, T: Send + 'static, { let inner_handle = self.inner.spawn(move || { @@ -78,6 +83,10 @@ pub struct JoinHandle<T = ()> { } impl<T> JoinHandle<T> { + /// # Panics + /// + /// Panics if there is no thread to join. + #[must_use] pub fn join(mut self) -> T { self.inner.take().unwrap().join() } @@ -95,6 +104,7 @@ impl<T> Drop for JoinHandle<T> { } } +#[expect(clippy::min_ident_chars, reason = "trait impl")] impl<T> fmt::Debug for JoinHandle<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("JoinHandle { .. }") diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread/intent.rs b/src/tools/rust-analyzer/crates/stdx/src/thread/intent.rs index 7b65db30cc5..1203bfc3854 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/thread/intent.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/thread/intent.rs @@ -1,9 +1,9 @@ -//! An opaque façade around platform-specific QoS APIs. +//! An opaque façade around platform-specific `QoS` APIs. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] // Please maintain order from least to most priority for the derived `Ord` impl. pub enum ThreadIntent { - /// Any thread which does work that isn’t in the critical path of the user typing + /// Any thread which does work that isn't in the critical path of the user typing /// (e.g. processing Go To Definition). Worker, @@ -34,6 +34,7 @@ use imp::QoSClass; const IS_QOS_AVAILABLE: bool = imp::IS_QOS_AVAILABLE; +#[expect(clippy::semicolon_if_nothing_returned, reason = "thin wrapper")] fn set_current_thread_qos_class(class: QoSClass) { imp::set_current_thread_qos_class(class) } @@ -63,7 +64,7 @@ mod imp { /// /// * **You do not care about how long it takes for work to finish.** /// * **You do not care about work being deferred temporarily.** - /// (e.g. if the device’s battery is in a critical state) + /// (e.g. if the device's battery is in a critical state) /// /// Examples: /// @@ -84,7 +85,7 @@ mod imp { /// All other work is prioritized over background tasks. Background, - /// TLDR: tasks that don’t block using your app + /// TLDR: tasks that don't block using your app /// /// Contract: /// @@ -110,7 +111,7 @@ mod imp { /// for tasks using this class. /// /// This QoS class provides a balance between - /// performance, responsiveness and efficiency. + /// performance, responsiveness, and efficiency. Utility, /// TLDR: tasks that block using your app @@ -126,10 +127,10 @@ mod imp { /// * in a video editor: /// opening a saved project /// * in a browser: - /// loading a list of the user’s bookmarks and top sites + /// loading a list of the user's bookmarks and top sites /// when a new tab is created /// * in a collaborative word processor: - /// running a search on the document’s content + /// running a search on the document's content /// /// Use this QoS class for tasks which were initiated by the user /// and block the usage of your app while they are in progress. @@ -208,7 +209,7 @@ mod imp { } _ => { - // `pthread_set_qos_class_self_np`’s documentation + // `pthread_set_qos_class_self_np`'s documentation // does not mention any other errors. unreachable!("`pthread_set_qos_class_self_np` returned unexpected error {errno}") } @@ -223,7 +224,7 @@ mod imp { }; if code != 0 { - // `pthread_get_qos_class_np`’s documentation states that + // `pthread_get_qos_class_np`'s documentation states that // an error value is placed into errno if the return code is not zero. // However, it never states what errors are possible. // Inspecting the source[0] shows that, as of this writing, it always returns zero. diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs index 0efff381c68..074cd747dac 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs @@ -38,7 +38,11 @@ struct Job { } impl Pool { - pub fn new(threads: usize) -> Pool { + /// # Panics + /// + /// Panics if job panics + #[must_use] + pub fn new(threads: usize) -> Self { const STACK_SIZE: usize = 8 * 1024 * 1024; const INITIAL_INTENT: ThreadIntent = ThreadIntent::Worker; @@ -63,7 +67,7 @@ impl Pool { } extant_tasks.fetch_add(1, Ordering::SeqCst); // discard the panic, we should've logged the backtrace already - _ = panic::catch_unwind(job.f); + drop(panic::catch_unwind(job.f)); extant_tasks.fetch_sub(1, Ordering::SeqCst); } } @@ -73,9 +77,12 @@ impl Pool { handles.push(handle); } - Pool { _handles: handles.into_boxed_slice(), extant_tasks, job_sender } + Self { _handles: handles.into_boxed_slice(), extant_tasks, job_sender } } + /// # Panics + /// + /// Panics if job panics pub fn spawn<F>(&self, intent: ThreadIntent, f: F) where F: FnOnce() + Send + UnwindSafe + 'static, @@ -84,14 +91,20 @@ impl Pool { if cfg!(debug_assertions) { intent.assert_is_used_on_current_thread(); } - f() + f(); }); let job = Job { requested_intent: intent, f }; self.job_sender.send(job).unwrap(); } + #[must_use] pub fn len(&self) -> usize { self.extant_tasks.load(Ordering::SeqCst) } + + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } |
