diff --git a/Cargo.lock b/Cargo.lock index 6b0f7efc6c..5dcf68e0ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,13 +49,6 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" -[[package]] -name = "anymap" -version = "0.0.0" -dependencies = [ - "hashbrown 0.14.0", -] - [[package]] name = "arbitrary" version = "1.3.0" @@ -540,7 +533,6 @@ dependencies = [ name = "hir-def" version = "0.0.0" dependencies = [ - "anymap", "arrayvec", "base-db", "bitflags 2.3.2", @@ -1831,6 +1823,7 @@ dependencies = [ "always-assert", "backtrace", "crossbeam-channel", + "hashbrown 0.14.0", "jod-thread", "libc", "miow", diff --git a/Cargo.toml b/Cargo.toml index 0b3ec8ed00..dd4348785d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,6 @@ debug = 0 [workspace.dependencies] # local crates -anymap = { path = "./crates/anymap", version = "0.0.0" } base-db = { path = "./crates/base-db", version = "0.0.0" } cfg = { path = "./crates/cfg", version = "0.0.0" } flycheck = { path = "./crates/flycheck", version = "0.0.0" } diff --git a/crates/anymap/Cargo.toml b/crates/anymap/Cargo.toml deleted file mode 100644 index 5f3976edcb..0000000000 --- a/crates/anymap/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "anymap" -version = "0.0.0" -description = "This crate is a port of only the necessary features from https://github.com/chris-morgan/anymap for use within rust-analyzer. Copyright © 2014–2022 Chris Morgan. COPYING: https://github.com/chris-morgan/anymap/blob/master/COPYING" - -authors.workspace = true -edition.workspace = true -license.workspace = true -rust-version.workspace = true - -[package.metadata.docs.rs] -all-features = true - -[features] -default = ["std"] -std = [] - -[dependencies] -# The hashbrown feature, disabled by default, is exposed under different stability guarantees than the usual SemVer ones: by preference the version range will only be extended, but it may be shrunk in a MINOR release. See README.md. -hashbrown = { version = "0.14.0", optional = true } diff --git a/crates/anymap/src/any.rs b/crates/anymap/src/any.rs deleted file mode 100644 index 1e205e7c9d..0000000000 --- a/crates/anymap/src/any.rs +++ /dev/null @@ -1,134 +0,0 @@ -//! Copyright © 2014–2022 Chris Morgan -//! https://github.com/chris-morgan/anymap/blob/master/COPYING -//! impl some traits for dyn Any -use core::any::{Any, TypeId}; -use core::fmt; - -#[doc(hidden)] -pub trait CloneToAny { - /// Clone `self` into a new `Box` object. - fn clone_to_any(&self) -> Box; -} - -impl CloneToAny for T { - #[inline] - fn clone_to_any(&self) -> Box { - Box::new(self.clone()) - } -} - -macro_rules! impl_clone { - ($t:ty) => { - impl Clone for Box<$t> { - #[inline] - fn clone(&self) -> Box<$t> { - // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this - // approach, given that I used to do it in safe code, but then came a dodgy - // future-compatibility warning where_clauses_object_safety, which is spurious for - // auto traits but still super annoying (future-compatibility lints seem to mean - // your bin crate needs a corresponding allow!). Although I explained my plight¹ - // and it was all explained and agreed upon, no action has been taken. So I finally - // caved and worked around it by doing it this way, which matches what’s done for - // core::any², so it’s probably not *too* bad. - // - // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013 - // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616 - let clone: Box = (**self).clone_to_any(); - let raw: *mut dyn CloneAny = Box::into_raw(clone); - unsafe { Box::from_raw(raw as *mut $t) } - } - } - - impl fmt::Debug for $t { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(stringify!($t)) - } - } - }; -} - -/// 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. -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::() 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::() 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. - - /// 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*. - unsafe fn downcast_ref_unchecked(&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*. - unsafe fn downcast_mut_unchecked(&mut self) -> &mut T; -} - -/// A trait for the conversion of an object into a boxed trait object. -pub trait IntoBox: Any { - /// Convert self into the appropriate boxed form. - fn into_box(self) -> Box; -} - -macro_rules! implement { - ($any_trait:ident $(+ $auto_traits:ident)*) => { - impl Downcast for dyn $any_trait $(+ $auto_traits)* { - #[inline] - fn type_id(&self) -> TypeId { - self.type_id() - } - - #[inline] - unsafe fn downcast_ref_unchecked(&self) -> &T { - &*(self as *const Self as *const T) - } - - #[inline] - unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { - &mut *(self as *mut Self as *mut T) - } - } - - impl IntoBox for T { - #[inline] - fn into_box(self) -> Box { - Box::new(self) - } - } - } -} - -implement!(Any); -implement!(Any + Send); -implement!(Any + Send + Sync); - -/// [`Any`], but with cloning. -/// -/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`. -/// See [`core::any`] for more details on `Any` in general. -pub trait CloneAny: Any + CloneToAny {} -impl CloneAny for T {} -implement!(CloneAny); -implement!(CloneAny + Send); -implement!(CloneAny + Send + Sync); -impl_clone!(dyn CloneAny); -impl_clone!(dyn CloneAny + Send); -impl_clone!(dyn CloneAny + Send + Sync); diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml index 261172ad94..99b8e9bf0e 100644 --- a/crates/hir-def/Cargo.toml +++ b/crates/hir-def/Cargo.toml @@ -33,7 +33,6 @@ triomphe.workspace = true rustc-dependencies.workspace = true # local deps -anymap.workspace = true stdx.workspace = true intern.workspace = true base-db.workspace = true diff --git a/crates/hir-def/src/dyn_map.rs b/crates/hir-def/src/dyn_map.rs index 63138aa6ad..a59bbf7e22 100644 --- a/crates/hir-def/src/dyn_map.rs +++ b/crates/hir-def/src/dyn_map.rs @@ -29,8 +29,8 @@ use std::{ ops::{Index, IndexMut}, }; -use anymap::Map; use rustc_hash::FxHashMap; +use stdx::anymap::Map; pub struct Key { _phantom: PhantomData<(K, V, P)>, diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml index 536f000a44..fae16fa2e4 100644 --- a/crates/stdx/Cargo.toml +++ b/crates/stdx/Cargo.toml @@ -17,6 +17,7 @@ backtrace = { version = "0.3.67", optional = true } always-assert = { version = "0.1.2", features = ["log"] } jod-thread = "0.1.2" crossbeam-channel = "0.5.5" +hashbrown = { version = "0.14.0" } # Think twice before adding anything here [target.'cfg(windows)'.dependencies] diff --git a/crates/anymap/src/lib.rs b/crates/stdx/src/anymap.rs similarity index 63% rename from crates/anymap/src/lib.rs rename to crates/stdx/src/anymap.rs index d8c6c889f7..0f4ae0a440 100644 --- a/crates/anymap/src/lib.rs +++ b/crates/stdx/src/anymap.rs @@ -1,5 +1,7 @@ //! Copyright © 2014–2022 Chris Morgan //! https://github.com/chris-morgan/anymap/blob/master/COPYING +//! Copyright © 2014–2022 Chris Morgan +//! https://github.com/chris-morgan/anymap/blob/master/COPYING //! //! This crate provides a safe and convenient store for one value of each type. //! @@ -23,10 +25,6 @@ use core::convert::TryInto; use core::hash::Hasher; -pub use crate::any::CloneAny; - -mod any; - /// 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 @@ -63,8 +61,6 @@ use core::marker::PhantomData; use ::std::collections::hash_map::{self, HashMap}; -use crate::any::{Downcast, IntoBox}; - /// Raw access to the underlying `HashMap`. /// /// This alias is provided for convenience because of the ugly third generic parameter. @@ -136,7 +132,7 @@ impl Map { /// Gets the entry for the given type in the collection for in-place manipulation #[inline] - pub fn entry>(&mut self) -> Entry { + pub fn entry>(&mut self) -> Entry<'_, A, T> { match self.raw.entry(TypeId::of::()) { hash_map::Entry::Occupied(e) => { Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData }) @@ -161,7 +157,7 @@ pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { } /// A view into a single location in an `Map`, which may be vacant or occupied. -pub enum Entry<'a, A: ?Sized + Downcast, V: 'a> { +pub enum Entry<'a, A: ?Sized + Downcast, V> { /// An occupied Entry Occupied(OccupiedEntry<'a, A, V>), /// A vacant Entry @@ -201,7 +197,6 @@ impl<'a, A: ?Sized + Downcast, V: IntoBox> VacantEntry<'a, A, V> { #[cfg(test)] mod tests { use super::*; - use crate::CloneAny; #[derive(Clone, Debug, PartialEq)] struct A(i32); @@ -255,3 +250,135 @@ mod tests { verify_hashing_with(TypeId::of::>()); } } + +// impl some traits for dyn Any +use core::fmt; + +#[doc(hidden)] +pub trait CloneToAny { + /// Clone `self` into a new `Box` object. + fn clone_to_any(&self) -> Box; +} + +impl CloneToAny for T { + #[inline] + fn clone_to_any(&self) -> Box { + Box::new(self.clone()) + } +} + +macro_rules! impl_clone { + ($t:ty) => { + impl Clone for Box<$t> { + #[inline] + fn clone(&self) -> Box<$t> { + // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this + // approach, given that I used to do it in safe code, but then came a dodgy + // future-compatibility warning where_clauses_object_safety, which is spurious for + // auto traits but still super annoying (future-compatibility lints seem to mean + // your bin crate needs a corresponding allow!). Although I explained my plight¹ + // and it was all explained and agreed upon, no action has been taken. So I finally + // caved and worked around it by doing it this way, which matches what’s done for + // core::any², so it’s probably not *too* bad. + // + // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013 + // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616 + let clone: Box = (**self).clone_to_any(); + let raw: *mut dyn CloneAny = Box::into_raw(clone); + unsafe { Box::from_raw(raw as *mut $t) } + } + } + + impl fmt::Debug for $t { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(stringify!($t)) + } + } + }; +} + +/// 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. +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::() 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::() 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. + + /// 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*. + unsafe fn downcast_ref_unchecked(&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*. + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T; +} + +/// A trait for the conversion of an object into a boxed trait object. +pub trait IntoBox: Any { + /// Convert self into the appropriate boxed form. + fn into_box(self) -> Box; +} + +macro_rules! implement { + ($any_trait:ident $(+ $auto_traits:ident)*) => { + impl Downcast for dyn $any_trait $(+ $auto_traits)* { + #[inline] + fn type_id(&self) -> TypeId { + self.type_id() + } + + #[inline] + unsafe fn downcast_ref_unchecked(&self) -> &T { + &*(self as *const Self as *const T) + } + + #[inline] + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + &mut *(self as *mut Self as *mut T) + } + } + + impl IntoBox for T { + #[inline] + fn into_box(self) -> Box { + Box::new(self) + } + } + } +} + +implement!(Any); +implement!(Any + Send); +implement!(Any + Send + Sync); + +/// [`Any`], but with cloning. +/// +/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`. +/// See [`core::any`] for more details on `Any` in general. +pub trait CloneAny: Any + CloneToAny {} +impl CloneAny for T {} +implement!(CloneAny); +implement!(CloneAny + Send); +implement!(CloneAny + Send + Sync); +impl_clone!(dyn CloneAny); +impl_clone!(dyn CloneAny + Send); +impl_clone!(dyn CloneAny + Send + Sync); diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 24990d6a0e..1e9a54e996 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -12,6 +12,7 @@ pub mod panic_context; pub mod non_empty_vec; pub mod rand; pub mod thread; +pub mod anymap; pub use always_assert::{always, never};