mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
refactor: move implementation inside anymap crate into stdx crate
This commit is contained in:
parent
00e238e99b
commit
f671b0b864
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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "anymap"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"hashbrown 0.14.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arbitrary"
|
name = "arbitrary"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@ -540,7 +533,6 @@ dependencies = [
|
|||||||
name = "hir-def"
|
name = "hir-def"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anymap",
|
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"base-db",
|
"base-db",
|
||||||
"bitflags 2.3.2",
|
"bitflags 2.3.2",
|
||||||
@ -1831,6 +1823,7 @@ dependencies = [
|
|||||||
"always-assert",
|
"always-assert",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
|
"hashbrown 0.14.0",
|
||||||
"jod-thread",
|
"jod-thread",
|
||||||
"libc",
|
"libc",
|
||||||
"miow",
|
"miow",
|
||||||
|
@ -46,7 +46,6 @@ debug = 0
|
|||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
# local crates
|
# local crates
|
||||||
anymap = { path = "./crates/anymap", version = "0.0.0" }
|
|
||||||
base-db = { path = "./crates/base-db", version = "0.0.0" }
|
base-db = { path = "./crates/base-db", version = "0.0.0" }
|
||||||
cfg = { path = "./crates/cfg", version = "0.0.0" }
|
cfg = { path = "./crates/cfg", version = "0.0.0" }
|
||||||
flycheck = { path = "./crates/flycheck", 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
|
rustc-dependencies.workspace = true
|
||||||
|
|
||||||
# local deps
|
# local deps
|
||||||
anymap.workspace = true
|
|
||||||
stdx.workspace = true
|
stdx.workspace = true
|
||||||
intern.workspace = true
|
intern.workspace = true
|
||||||
base-db.workspace = true
|
base-db.workspace = true
|
||||||
|
@ -29,8 +29,8 @@ use std::{
|
|||||||
ops::{Index, IndexMut},
|
ops::{Index, IndexMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anymap::Map;
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use stdx::anymap::Map;
|
||||||
|
|
||||||
pub struct Key<K, V, P = (K, V)> {
|
pub struct Key<K, V, P = (K, V)> {
|
||||||
_phantom: PhantomData<(K, V, P)>,
|
_phantom: PhantomData<(K, V, P)>,
|
||||||
|
@ -17,6 +17,7 @@ backtrace = { version = "0.3.67", optional = true }
|
|||||||
always-assert = { version = "0.1.2", features = ["log"] }
|
always-assert = { version = "0.1.2", features = ["log"] }
|
||||||
jod-thread = "0.1.2"
|
jod-thread = "0.1.2"
|
||||||
crossbeam-channel = "0.5.5"
|
crossbeam-channel = "0.5.5"
|
||||||
|
hashbrown = { version = "0.14.0" }
|
||||||
# Think twice before adding anything here
|
# Think twice before adding anything here
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
//! Copyright © 2014–2022 Chris Morgan
|
//! Copyright © 2014–2022 Chris Morgan
|
||||||
//! https://github.com/chris-morgan/anymap/blob/master/COPYING
|
//! 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.
|
//! This crate provides a safe and convenient store for one value of each type.
|
||||||
//!
|
//!
|
||||||
@ -23,10 +25,6 @@
|
|||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use core::hash::Hasher;
|
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.
|
/// 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
|
||||||
@ -63,8 +61,6 @@ use core::marker::PhantomData;
|
|||||||
|
|
||||||
use ::std::collections::hash_map::{self, HashMap};
|
use ::std::collections::hash_map::{self, HashMap};
|
||||||
|
|
||||||
use crate::any::{Downcast, IntoBox};
|
|
||||||
|
|
||||||
/// Raw access to the underlying `HashMap`.
|
/// Raw access to the underlying `HashMap`.
|
||||||
///
|
///
|
||||||
/// This alias is provided for convenience because of the ugly third generic parameter.
|
/// 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
|
/// Gets the entry for the given type in the collection for in-place manipulation
|
||||||
#[inline]
|
#[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>()) {
|
match self.raw.entry(TypeId::of::<T>()) {
|
||||||
hash_map::Entry::Occupied(e) => {
|
hash_map::Entry::Occupied(e) => {
|
||||||
Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData })
|
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.
|
/// 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
|
/// An occupied Entry
|
||||||
Occupied(OccupiedEntry<'a, A, V>),
|
Occupied(OccupiedEntry<'a, A, V>),
|
||||||
/// A vacant Entry
|
/// A vacant Entry
|
||||||
@ -201,7 +197,6 @@ impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> VacantEntry<'a, A, V> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::CloneAny;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
struct A(i32);
|
struct A(i32);
|
||||||
@ -255,3 +250,135 @@ mod tests {
|
|||||||
verify_hashing_with(TypeId::of::<Vec<u8>>());
|
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 non_empty_vec;
|
||||||
pub mod rand;
|
pub mod rand;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
|
pub mod anymap;
|
||||||
|
|
||||||
pub use always_assert::{always, never};
|
pub use always_assert::{always, never};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user