mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
refactor: move implementation inside anymap crate into stdx crate
This commit is contained in:
parent
00e238e99b
commit
f671b0b864
9 changed files with 140 additions and 174 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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 }
|
|
@ -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<dyn CloneAny>` object.
|
||||
fn clone_to_any(&self) -> Box<dyn CloneAny>;
|
||||
}
|
||||
|
||||
impl<T: Any + Clone> CloneToAny for T {
|
||||
#[inline]
|
||||
fn clone_to_any(&self) -> Box<dyn CloneAny> {
|
||||
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<dyn CloneAny> = (**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::<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.
|
||||
|
||||
/// 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<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*.
|
||||
unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T;
|
||||
}
|
||||
|
||||
/// A trait for the conversion of an object into a boxed trait object.
|
||||
pub trait IntoBox<A: ?Sized + Downcast>: Any {
|
||||
/// Convert self into the appropriate boxed form.
|
||||
fn into_box(self) -> Box<A>;
|
||||
}
|
||||
|
||||
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<T: 'static>(&self) -> &T {
|
||||
&*(self as *const Self as *const T)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
|
||||
&mut *(self as *mut Self as *mut T)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: $any_trait $(+ $auto_traits)*> IntoBox<dyn $any_trait $(+ $auto_traits)*> for T {
|
||||
#[inline]
|
||||
fn into_box(self) -> Box<dyn $any_trait $(+ $auto_traits)*> {
|
||||
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<T: Any + Clone> 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);
|
|
@ -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
|
||||
|
|
|
@ -29,8 +29,8 @@ use std::{
|
|||
ops::{Index, IndexMut},
|
||||
};
|
||||
|
||||
use anymap::Map;
|
||||
use rustc_hash::FxHashMap;
|
||||
use stdx::anymap::Map;
|
||||
|
||||
pub struct Key<K, V, P = (K, V)> {
|
||||
_phantom: PhantomData<(K, V, P)>,
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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<A: ?Sized + Downcast> Map<A> {
|
|||
|
||||
/// Gets the entry for the given type in the collection for in-place manipulation
|
||||
#[inline]
|
||||
pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<A, T> {
|
||||
pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<'_, A, T> {
|
||||
match self.raw.entry(TypeId::of::<T>()) {
|
||||
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<A>> 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::<Vec<u8>>());
|
||||
}
|
||||
}
|
||||
|
||||
// impl some traits for dyn Any
|
||||
use core::fmt;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait CloneToAny {
|
||||
/// Clone `self` into a new `Box<dyn CloneAny>` object.
|
||||
fn clone_to_any(&self) -> Box<dyn CloneAny>;
|
||||
}
|
||||
|
||||
impl<T: Any + Clone> CloneToAny for T {
|
||||
#[inline]
|
||||
fn clone_to_any(&self) -> Box<dyn CloneAny> {
|
||||
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<dyn CloneAny> = (**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::<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.
|
||||
|
||||
/// 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<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*.
|
||||
unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T;
|
||||
}
|
||||
|
||||
/// A trait for the conversion of an object into a boxed trait object.
|
||||
pub trait IntoBox<A: ?Sized + Downcast>: Any {
|
||||
/// Convert self into the appropriate boxed form.
|
||||
fn into_box(self) -> Box<A>;
|
||||
}
|
||||
|
||||
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<T: 'static>(&self) -> &T {
|
||||
&*(self as *const Self as *const T)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
|
||||
&mut *(self as *mut Self as *mut T)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: $any_trait $(+ $auto_traits)*> IntoBox<dyn $any_trait $(+ $auto_traits)*> for T {
|
||||
#[inline]
|
||||
fn into_box(self) -> Box<dyn $any_trait $(+ $auto_traits)*> {
|
||||
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<T: Any + Clone> 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);
|
|
@ -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};
|
||||
|
||||
|
|
Loading…
Reference in a new issue