From: Chris Morgan Date: Tue, 25 Jan 2022 01:57:35 +0000 (+1100) Subject: No more bare trait objects: use `dyn Trait` syntax X-Git-Tag: 1.0.0-beta.1~22 X-Git-Url: https://git.chrismorgan.info/anymap/commitdiff_plain/bf29e608d91175d0fca2108fd1b5d75596a4a796 No more bare trait objects: use `dyn Trait` syntax --- diff --git a/README.md b/README.md index cd88937..c4bbe6b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ As another example of such an interface, JavaScript objects are exactly the same Fortunately, we can do better than these things in Rust. Our type system is quite equal to easy, robust expression of such problems. -The ``AnyMap`` type is a friendly wrapper around a ``HashMap>``, exposing a nice, easy typed interface, perfectly safe and absolutely robust. +The ``AnyMap`` type is a friendly wrapper around a ``HashMap>``, exposing a nice, easy typed interface, perfectly safe and absolutely robust. What this means is that in an ``AnyMap`` you may store zero or one values for every type. @@ -14,7 +14,7 @@ What this means is that in an ``AnyMap`` you may store zero or one values for ev This library uses a fair bit of unsafe code for several reasons: -- To support Any and CloneAny, unsafe code is required (because of how the `downcast` methods are defined in `impl Any` rather than being trait methods; I think this is kind of a historical detail of the structure of `std::any::Any`); if you wanted to ditch `Clone` support this unsafety could be removed. +- To support Any and CloneAny, unsafe code is required (because of how the `downcast` methods are defined in `impl dyn Any` rather than being trait methods; I think this is kind of a historical detail of the structure of `std::any::Any`); if you wanted to ditch `Clone` support this unsafety could be removed. - In the interests of performance, skipping various checks that are unnecessary because of the invariants of the data structure (no need to check the type ID when it’s been statically ensured by being used as the hash map key) and simplifying hashing (type IDs are already good hashes, no need to mangle them through SipHash). diff --git a/src/any.rs b/src/any.rs index 976f768..4045889 100644 --- a/src/any.rs +++ b/src/any.rs @@ -8,37 +8,37 @@ use std::any::Any as StdAny; #[doc(hidden)] pub trait CloneToAny { - /// Clone `self` into a new `Box` object. - fn clone_to_any(&self) -> Box; + /// Clone `self` into a new `Box` object. + fn clone_to_any(&self) -> Box; - /// Clone `self` into a new `Box` object. - fn clone_to_any_send(&self) -> Box where Self: Send; + /// Clone `self` into a new `Box` object. + fn clone_to_any_send(&self) -> Box where Self: Send; - /// Clone `self` into a new `Box` object. - fn clone_to_any_sync(&self) -> Box where Self: Sync; + /// Clone `self` into a new `Box` object. + fn clone_to_any_sync(&self) -> Box where Self: Sync; - /// Clone `self` into a new `Box` object. - fn clone_to_any_send_sync(&self) -> Box where Self: Send + Sync; + /// Clone `self` into a new `Box` object. + fn clone_to_any_send_sync(&self) -> Box where Self: Send + Sync; } impl CloneToAny for T { #[inline] - fn clone_to_any(&self) -> Box { + fn clone_to_any(&self) -> Box { Box::new(self.clone()) } #[inline] - fn clone_to_any_send(&self) -> Box where Self: Send { + fn clone_to_any_send(&self) -> Box where Self: Send { Box::new(self.clone()) } #[inline] - fn clone_to_any_sync(&self) -> Box where Self: Sync { + fn clone_to_any_sync(&self) -> Box where Self: Sync { Box::new(self.clone()) } #[inline] - fn clone_to_any_send_sync(&self) -> Box where Self: Send + Sync { + fn clone_to_any_send_sync(&self) -> Box where Self: Send + Sync { Box::new(self.clone()) } } @@ -108,14 +108,14 @@ pub trait IntoBox: Any { macro_rules! implement { ($base:ident, $(+ $bounds:ident)*) => { - impl fmt::Debug for $base $(+ $bounds)* { + impl fmt::Debug for dyn $base $(+ $bounds)* { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(stringify!($base $(+ $bounds)*)) + f.pad(stringify!(dyn $base $(+ $bounds)*)) } } - impl UncheckedAnyExt for $base $(+ $bounds)* { + impl UncheckedAnyExt for dyn $base $(+ $bounds)* { #[inline] unsafe fn downcast_ref_unchecked(&self) -> &T { &*(self as *const Self as *const T) @@ -132,9 +132,9 @@ macro_rules! implement { } } - impl IntoBox<$base $(+ $bounds)*> for T { + impl IntoBox for T { #[inline] - fn into_box(self) -> Box<$base $(+ $bounds)*> { + fn into_box(self) -> Box { Box::new(self) } } @@ -152,7 +152,7 @@ implement!(CloneAny, + Sync); implement!(CloneAny, + Send + Sync); define!(CloneAny); -impl_clone!(CloneAny, clone_to_any); -impl_clone!((CloneAny + Send), clone_to_any_send); -impl_clone!((CloneAny + Sync), clone_to_any_sync); -impl_clone!((CloneAny + Send + Sync), clone_to_any_send_sync); +impl_clone!(dyn CloneAny, clone_to_any); +impl_clone!(dyn CloneAny + Send, clone_to_any_send); +impl_clone!(dyn CloneAny + Sync, clone_to_any_sync); +impl_clone!(dyn CloneAny + Send + Sync, clone_to_any_send_sync); diff --git a/src/lib.rs b/src/lib.rs index de03fb6..c9e0276 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,7 +95,7 @@ pub mod raw; /// be `anymap::any::Any`, but there are other choices: /// /// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`. -/// - You can add on `+ Send` and/or `+ Sync` (e.g. `Map`) to add those bounds. +/// - You can add on `+ Send` and/or `+ Sync` (e.g. `Map`) to add those bounds. /// /// ```rust /// # use anymap::AnyMap; @@ -120,7 +120,7 @@ pub mod raw; /// /// Values containing non-static references are not permitted. #[derive(Debug)] -pub struct Map { +pub struct Map { raw: RawMap, } @@ -139,7 +139,7 @@ impl Clone for Map where Box: Clone { /// Why is this a separate type alias rather than a default value for `Map`? `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; +pub type AnyMap = Map; impl_common_methods! { field: Map.raw; @@ -394,7 +394,7 @@ mod tests { } test_entry!(test_entry_any, AnyMap); - test_entry!(test_entry_cloneany, Map); + test_entry!(test_entry_cloneany, Map); #[test] fn test_default() { @@ -404,7 +404,7 @@ mod tests { #[test] fn test_clone() { - let mut map: Map = Map::new(); + let mut map: Map = Map::new(); let _ = map.insert(A(1)); let _ = map.insert(B(2)); let _ = map.insert(D(3)); @@ -428,25 +428,25 @@ mod tests { fn assert_sync() { } fn assert_clone() { } fn assert_debug() { } - assert_send::>(); - assert_send::>(); - assert_sync::>(); - assert_sync::>(); - assert_debug::>(); - assert_debug::>(); - assert_debug::>(); - assert_debug::>(); - assert_send::>(); - assert_send::>(); - assert_sync::>(); - assert_sync::>(); - assert_clone::>(); - assert_clone::>(); - assert_clone::>(); - assert_clone::>(); - assert_debug::>(); - assert_debug::>(); - assert_debug::>(); - assert_debug::>(); + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_sync::>(); + assert_clone::>(); + assert_clone::>(); + assert_clone::>(); + assert_clone::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); } } diff --git a/src/raw.rs b/src/raw.rs index 07dccf8..aa3d6dc 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -56,7 +56,7 @@ fn type_id_hasher() { /// contents of an `Map`. However, because you will then be dealing with `Any` trait objects, it /// doesn’t tend to be so very useful. Still, if you need it, it’s here. #[derive(Debug)] -pub struct RawMap { +pub struct RawMap { inner: HashMap, BuildHasherDefault>, }