No more bare trait objects: use `dyn Trait` syntax
authorChris Morgan <me@chrismorgan.info>
committerChris Morgan <me@chrismorgan.info>
README.md
src/any.rs
src/lib.rs
src/raw.rs

index cd88937d6d2c28ea466b83eeb982af452a0848f2..c4bbe6b8104adad6510ec9f3a4d4b5eb9d7e4422 100644 (file)
--- 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<TypeId, Box<Any>>``, exposing a nice, easy typed interface, perfectly safe and absolutely robust.
+The ``AnyMap`` type is a friendly wrapper around a ``HashMap<TypeId, Box<dyn Any>>``, 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).
 
index 976f768ec1a68b61646c18718a2f23671ad1d4a6..40458891e5e9b4ce357a40273c1f968c3d5e656f 100644 (file)
@@ -8,37 +8,37 @@ use std::any::Any as StdAny;
 
 #[doc(hidden)]
 pub trait CloneToAny {
-    /// Clone `self` into a new `Box<CloneAny>` object.
-    fn clone_to_any(&self) -> Box<CloneAny>;
+    /// Clone `self` into a new `Box<dyn CloneAny>` object.
+    fn clone_to_any(&self) -> Box<dyn CloneAny>;
 
-    /// Clone `self` into a new `Box<CloneAny + Send>` object.
-    fn clone_to_any_send(&self) -> Box<CloneAny + Send> where Self: Send;
+    /// Clone `self` into a new `Box<dyn CloneAny + Send>` object.
+    fn clone_to_any_send(&self) -> Box<dyn CloneAny + Send> where Self: Send;
 
-    /// Clone `self` into a new `Box<CloneAny + Sync>` object.
-    fn clone_to_any_sync(&self) -> Box<CloneAny + Sync> where Self: Sync;
+    /// Clone `self` into a new `Box<dyn CloneAny + Sync>` object.
+    fn clone_to_any_sync(&self) -> Box<dyn CloneAny + Sync> where Self: Sync;
 
-    /// Clone `self` into a new `Box<CloneAny + Send + Sync>` object.
-    fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync;
+    /// Clone `self` into a new `Box<dyn CloneAny + Send + Sync>` object.
+    fn clone_to_any_send_sync(&self) -> Box<dyn CloneAny + Send + Sync> where Self: Send + Sync;
 }
 
 impl<T: Any + Clone> CloneToAny for T {
     #[inline]
-    fn clone_to_any(&self) -> Box<CloneAny> {
+    fn clone_to_any(&self) -> Box<dyn CloneAny> {
         Box::new(self.clone())
     }
 
     #[inline]
-    fn clone_to_any_send(&self) -> Box<CloneAny + Send> where Self: Send {
+    fn clone_to_any_send(&self) -> Box<dyn CloneAny + Send> where Self: Send {
         Box::new(self.clone())
     }
 
     #[inline]
-    fn clone_to_any_sync(&self) -> Box<CloneAny + Sync> where Self: Sync {
+    fn clone_to_any_sync(&self) -> Box<dyn CloneAny + Sync> where Self: Sync {
         Box::new(self.clone())
     }
 
     #[inline]
-    fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync {
+    fn clone_to_any_send_sync(&self) -> Box<dyn CloneAny + Send + Sync> where Self: Send + Sync {
         Box::new(self.clone())
     }
 }
@@ -108,14 +108,14 @@ pub trait IntoBox<A: ?Sized + UncheckedAnyExt>: 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<T: 'static>(&self) -> &T {
                 &*(self as *const Self as *const T)
@@ -132,9 +132,9 @@ macro_rules! implement {
             }
         }
 
-        impl<T: $base $(+ $bounds)*> IntoBox<$base $(+ $bounds)*> for T {
+        impl<T: $base $(+ $bounds)*> IntoBox<dyn $base $(+ $bounds)*> for T {
             #[inline]
-            fn into_box(self) -> Box<$base $(+ $bounds)*> {
+            fn into_box(self) -> Box<dyn $base $(+ $bounds)*> {
                 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);
index de03fb6c74d0a7ea45c47cc8fcf717b6188c4d20..c9e027633b2e37fe06f828d1189ec20285757578 100644 (file)
@@ -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<Any + Send>`) to add those bounds.
+/// - You can add on `+ Send` and/or `+ Sync` (e.g. `Map<dyn Any + Send>`) 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<A: ?Sized + UncheckedAnyExt = Any> {
+pub struct Map<A: ?Sized + UncheckedAnyExt = dyn Any> {
     raw: RawMap<A>,
 }
 
@@ -139,7 +139,7 @@ impl<A: ?Sized + UncheckedAnyExt> Clone for Map<A> where Box<A>: Clone {
 /// 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.
-pub type AnyMap = Map<Any>;
+pub type AnyMap = Map<dyn Any>;
 
 impl_common_methods! {
     field: Map.raw;
@@ -394,7 +394,7 @@ mod tests {
     }
 
     test_entry!(test_entry_any, AnyMap);
-    test_entry!(test_entry_cloneany, Map<CloneAny>);
+    test_entry!(test_entry_cloneany, Map<dyn CloneAny>);
 
     #[test]
     fn test_default() {
@@ -404,7 +404,7 @@ mod tests {
 
     #[test]
     fn test_clone() {
-        let mut map: Map<CloneAny> = Map::new();
+        let mut map: Map<dyn CloneAny> = 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<T: Sync>() { }
         fn assert_clone<T: Clone>() { }
         fn assert_debug<T: ::std::fmt::Debug>() { }
-        assert_send::<Map<Any + Send>>();
-        assert_send::<Map<Any + Send + Sync>>();
-        assert_sync::<Map<Any + Sync>>();
-        assert_sync::<Map<Any + Send + Sync>>();
-        assert_debug::<Map<Any>>();
-        assert_debug::<Map<Any + Send>>();
-        assert_debug::<Map<Any + Sync>>();
-        assert_debug::<Map<Any + Send + Sync>>();
-        assert_send::<Map<CloneAny + Send>>();
-        assert_send::<Map<CloneAny + Send + Sync>>();
-        assert_sync::<Map<CloneAny + Sync>>();
-        assert_sync::<Map<CloneAny + Send + Sync>>();
-        assert_clone::<Map<CloneAny + Send>>();
-        assert_clone::<Map<CloneAny + Send + Sync>>();
-        assert_clone::<Map<CloneAny + Sync>>();
-        assert_clone::<Map<CloneAny + Send + Sync>>();
-        assert_debug::<Map<CloneAny>>();
-        assert_debug::<Map<CloneAny + Send>>();
-        assert_debug::<Map<CloneAny + Sync>>();
-        assert_debug::<Map<CloneAny + Send + Sync>>();
+        assert_send::<Map<dyn Any + Send>>();
+        assert_send::<Map<dyn Any + Send + Sync>>();
+        assert_sync::<Map<dyn Any + Sync>>();
+        assert_sync::<Map<dyn Any + Send + Sync>>();
+        assert_debug::<Map<dyn Any>>();
+        assert_debug::<Map<dyn Any + Send>>();
+        assert_debug::<Map<dyn Any + Sync>>();
+        assert_debug::<Map<dyn Any + Send + Sync>>();
+        assert_send::<Map<dyn CloneAny + Send>>();
+        assert_send::<Map<dyn CloneAny + Send + Sync>>();
+        assert_sync::<Map<dyn CloneAny + Sync>>();
+        assert_sync::<Map<dyn CloneAny + Send + Sync>>();
+        assert_clone::<Map<dyn CloneAny + Send>>();
+        assert_clone::<Map<dyn CloneAny + Send + Sync>>();
+        assert_clone::<Map<dyn CloneAny + Sync>>();
+        assert_clone::<Map<dyn CloneAny + Send + Sync>>();
+        assert_debug::<Map<dyn CloneAny>>();
+        assert_debug::<Map<dyn CloneAny + Send>>();
+        assert_debug::<Map<dyn CloneAny + Sync>>();
+        assert_debug::<Map<dyn CloneAny + Send + Sync>>();
     }
 }
index 07dccf8d248ab7f7655b07af79d918a245f02f35..aa3d6dc7dd83b1d3e159339c5abd5c2abdee86d2 100644 (file)
@@ -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<A: ?Sized + UncheckedAnyExt = Any> {
+pub struct RawMap<A: ?Sized + UncheckedAnyExt = dyn Any> {
     inner: HashMap<TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>,
 }