Replace Cargo features with arcane DST magicks.
authorChris Morgan <me@chrismorgan.info>
committerChris Morgan <me@chrismorgan.info>
(It was a toss-up between “arcane” and “eldritch” there; “arcane” won
this time. “Eldritch”, maybe you can be it next time.)
.travis.yml
Cargo.toml
README.md
src/any.rs [new file with mode: 0644]
src/lib.rs
src/raw.rs [moved from src/raw/mod.rs with 63% similarity]
src/raw/any.rs [deleted file]
src/unchecked_any.rs [deleted file]

index 64c99e0e49994ec95b42dbc9e513ed769516f073..0b7902ca81d159f416ef1821e0a4127d454404de 100644 (file)
@@ -4,12 +4,6 @@ env:
     - secure: nR+DJRUQ9v03nNZMpMu1tGKLKBAqdQsTIAr8ffdl+DUEh3b2jvQ+vLLNFLPjsloqhoOXo7cWO7qVpiE4ZOq2lNDURQjdiZGFjh/Y5+xKy2BqFdV7qQ1JoBzsMyx28tQTYz0mtBsACiCYKKb+ddNX5hpwrsjp8cS7htZktA5kbiU=
 script:
   - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features nightly; else ! cargo test --features nightly; fi
-  - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'clone nightly'; else ! cargo test --features 'clone nightly'; fi
-  - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'concurrent nightly'; else ! cargo test --features 'concurrent nightly'; fi
-  - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'clone concurrent nightly'; else ! cargo test --features 'clone concurrent nightly'; fi
-  - cargo test --features clone
-  - cargo test --features concurrent
-  - cargo test --features 'clone concurrent'
   - cargo test
   - cargo doc
 after_script:
index 85f18cbcbcb25b5beb2e888e288bfa013a1960e8..2cd16010d2d861d2cd2c6b4d85aa941603458767 100644 (file)
@@ -11,6 +11,4 @@ keywords = ["container", "data-structure", "map"]
 license = "MIT/Apache-2.0"
 
 [features]
-clone = []
-concurrent = []
 nightly = []
index a498edd50367a2e7fcaf0de00a2f953fc4ca849d..77b147b876a869833156022fdb296013adcc30f8 100644 (file)
--- a/README.md
+++ b/README.md
@@ -18,14 +18,6 @@ Instructions
 
 Cargo all the way: it is `anymap` on crates.io.
 
-There are a couple of optional features on the `anymap` crate:
-
-- `clone`: if enabled, your `AnyMap` will require contained types to implement `Clone` and will itself satisfy `Clone`.
-
-- `concurrent`: if enabled, your `AnyMap` will require contained types to satisfy `Send` and `Sync` and will itself satisfy `Send` and `Sync`.
-
-These can be combined if desired.
-
 For users of the nightly instead of the beta of rustc there are a couple of things behind the `nightly` feature like a `drain` method on the `RawAnyMap` and a more efficient hashing technique which makes lookup in the map a tad faster.
 
 Author
diff --git a/src/any.rs b/src/any.rs
new file mode 100644 (file)
index 0000000..45ad5cc
--- /dev/null
@@ -0,0 +1,167 @@
+//! The different types of `Any` for use in a map.
+//!
+//! This stuff is all based on `std::any`, but goes a little further, with `CloneAny` being a
+//! cloneable `Any` and with the `Send` and `Sync` bounds possible on both `Any` and `CloneAny`.
+
+use std::mem;
+use std::fmt;
+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<CloneAny + Send>` object.
+    fn clone_to_any_send(&self) -> Box<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<CloneAny + Send + Sync>` object.
+    fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync;
+}
+
+impl<T: Any + Clone> CloneToAny for T {
+    fn clone_to_any(&self) -> Box<CloneAny> {
+        Box::new(self.clone())
+    }
+
+    fn clone_to_any_send(&self) -> Box<CloneAny + Send> where Self: Send {
+        Box::new(self.clone())
+    }
+
+    fn clone_to_any_sync(&self) -> Box<CloneAny + Sync> where Self: Sync {
+        Box::new(self.clone())
+    }
+
+    fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync {
+        Box::new(self.clone())
+    }
+}
+
+macro_rules! define {
+    (CloneAny) => {
+        /// A type to emulate dynamic typing.
+        ///
+        /// Every type with no non-`'static` references implements `Any`.
+        define!(CloneAny remainder);
+    };
+    (Any) => {
+        /// A type to emulate dynamic typing with cloning.
+        ///
+        /// Every type with no non-`'static` references that implements `Clone` implements `Any`.
+        define!(Any remainder);
+    };
+    ($t:ident remainder) => {
+        /// See the [`std::any` documentation](https://doc.rust-lang.org/std/any/index.html) for
+        /// more details on `Any` in general.
+        ///
+        /// This trait is not `std::any::Any` but rather a type extending that for this library’s
+        /// purposes so that it can be combined with marker traits like 
+        /// <code><a class=trait title=core::marker::Send
+        /// href=http://doc.rust-lang.org/std/marker/trait.Send.html>Send</a></code> and
+        /// <code><a class=trait title=core::marker::Sync
+        /// href=http://doc.rust-lang.org/std/marker/trait.Sync.html>Sync</a></code>.
+        ///
+        define!($t trait);
+    };
+    (CloneAny trait) => {
+        /// See also [`Any`](trait.Any.html) for a version without the `Clone` requirement.
+        pub trait CloneAny: Any + CloneToAny { }
+        impl<T: StdAny + Clone> CloneAny for T { }
+    };
+    (Any trait) => {
+        /// See also [`CloneAny`](trait.CloneAny.html) for a cloneable version of this trait.
+        pub trait Any: StdAny { }
+        impl<T: StdAny> Any for T { }
+    };
+}
+
+macro_rules! impl_clone {
+    ($t:ty, $method:ident) => {
+        impl Clone for Box<$t> {
+            fn clone(&self) -> Box<$t> {
+                (**self).$method()
+            }
+        }
+    }
+}
+
+#[cfg(feature = "nightly")]
+use std::raw::TraitObject;
+
+#[cfg(not(feature = "nightly"))]
+#[repr(C)]
+#[allow(raw_pointer_derive)]
+#[derive(Copy, Clone)]
+struct TraitObject {
+    pub data: *mut (),
+    pub vtable: *mut (),
+}
+
+#[allow(missing_docs)]  // Bogus warning (it’s not public outside the crate), ☹
+pub trait UncheckedAnyExt: Any {
+    unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T;
+    unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T;
+    unsafe fn downcast_unchecked<T: Any>(self: Box<Self>) -> Box<T>;
+}
+
+#[doc(hidden)]
+/// A trait for the conversion of an object into a boxed trait object.
+pub trait IntoBox<A: ?Sized + UncheckedAnyExt>: Any {
+    /// Convert self into the appropriate boxed form.
+    fn into_box(self) -> Box<A>;
+}
+
+macro_rules! implement {
+    ($base:ident, $(+ $bounds:ident)*) => {
+        impl<'a> fmt::Debug for &'a ($base $(+ $bounds)*) {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                f.pad(stringify!(&($base $(+ $bounds)*)))
+            }
+        }
+
+        impl<'a> fmt::Debug for Box<$base $(+ $bounds)*> {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                f.pad(stringify!(Box<$base $(+ $bounds)*>))
+            }
+        }
+
+        impl UncheckedAnyExt for $base $(+ $bounds)* {
+            unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
+                mem::transmute(mem::transmute::<_, TraitObject>(self).data)
+            }
+
+            unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
+                mem::transmute(mem::transmute::<_, TraitObject>(self).data)
+            }
+
+            unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T> {
+                mem::transmute(mem::transmute::<_, TraitObject>(self).data)
+            }
+        }
+
+        impl<T: $base $(+ $bounds)*> IntoBox<$base $(+ $bounds)*> for T {
+            fn into_box(self) -> Box<$base $(+ $bounds)*> {
+                Box::new(self)
+            }
+        }
+    }
+}
+
+define!(Any);
+implement!(Any,);
+implement!(Any, + Send);
+implement!(Any, + Sync);
+implement!(Any, + Send + Sync);
+implement!(CloneAny,);
+implement!(CloneAny, + Send);
+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);
index d32af5f2aa4327826844727c183a09f47c247fb7..8e83babc6336be0b566c0dc8bf7cdb98f9c2ed3e 100644 (file)
@@ -10,8 +10,8 @@ extern crate test;
 use std::any::TypeId;
 use std::marker::PhantomData;
 
-use raw::{RawAnyMap, Any};
-use unchecked_any::UncheckedAnyExt;
+use raw::RawMap;
+use any::{UncheckedAnyExt, IntoBox, Any};
 
 macro_rules! impl_common_methods {
     (
@@ -19,10 +19,10 @@ macro_rules! impl_common_methods {
         new() => $new:expr;
         with_capacity($with_capacity_arg:ident) => $with_capacity:expr;
     ) => {
-        impl $t {
+        impl<A: ?Sized + UncheckedAnyExt> $t<A> {
             /// Create an empty collection.
             #[inline]
-            pub fn new() -> $t {
+            pub fn new() -> $t<A> {
                 $t {
                     $field: $new,
                 }
@@ -30,7 +30,7 @@ macro_rules! impl_common_methods {
 
             /// Creates an empty collection with the given initial capacity.
             #[inline]
-            pub fn with_capacity($with_capacity_arg: usize) -> $t {
+            pub fn with_capacity($with_capacity_arg: usize) -> $t<A> {
                 $t {
                     $field: $with_capacity,
                 }
@@ -83,12 +83,18 @@ macro_rules! impl_common_methods {
     }
 }
 
-mod unchecked_any;
+pub mod any;
 pub mod raw;
 
 /// A collection containing zero or one values for any given type and allowing convenient,
 /// type-safe access to those values.
 ///
+/// The type parameter `A` allows you to use a different value type; normally you will want it to
+/// 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.
+///
 /// ```rust
 /// # use anymap::AnyMap;
 /// let mut data = AnyMap::new();
@@ -112,27 +118,42 @@ pub mod raw;
 ///
 /// Values containing non-static references are not permitted.
 #[derive(Debug)]
-#[cfg_attr(feature = "clone", derive(Clone))]
-pub struct AnyMap {
-    raw: RawAnyMap,
+pub struct Map<A: ?Sized + UncheckedAnyExt = Any> {
+    raw: RawMap<A>,
+}
+
+// #[derive(Clone)] would want A to implement Clone, but in reality it’s only Box<A> that can.
+impl<A: ?Sized + UncheckedAnyExt> Clone for Map<A> where Box<A>: Clone {
+    fn clone(&self) -> Map<A> {
+        Map {
+            raw: self.raw.clone(),
+        }
+    }
 }
 
+/// The most common type of `Map`: just using `Any`.
+///
+/// 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>;
+
 impl_common_methods! {
-    field: AnyMap.raw;
-    new() => RawAnyMap::new();
-    with_capacity(capacity) => RawAnyMap::with_capacity(capacity);
+    field: Map.raw;
+    new() => RawMap::new();
+    with_capacity(capacity) => RawMap::with_capacity(capacity);
 }
 
-impl AnyMap {
+impl<A: ?Sized + UncheckedAnyExt> Map<A> {
     /// Returns a reference to the value stored in the collection for the type `T`, if it exists.
-    pub fn get<T: Any>(&self) -> Option<&T> {
+    pub fn get<T: IntoBox<A>>(&self) -> Option<&T> {
         self.raw.get(&TypeId::of::<T>())
             .map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
     }
 
     /// Returns a mutable reference to the value stored in the collection for the type `T`,
     /// if it exists.
-    pub fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
+    pub fn get_mut<T: IntoBox<A>>(&mut self) -> Option<&mut T> {
         self.raw.get_mut(&TypeId::of::<T>())
             .map(|any| unsafe { any.downcast_mut_unchecked::<T>() })
     }
@@ -140,28 +161,28 @@ impl AnyMap {
     /// Sets the value stored in the collection for the type `T`.
     /// If the collection already had a value of type `T`, that value is returned.
     /// Otherwise, `None` is returned.
-    pub fn insert<T: Any>(&mut self, value: T) -> Option<T> {
+    pub fn insert<T: IntoBox<A>>(&mut self, value: T) -> Option<T> {
         unsafe {
-            self.raw.insert(TypeId::of::<T>(), Box::new(value))
+            self.raw.insert(TypeId::of::<T>(), value.into_box())
                 .map(|any| *any.downcast_unchecked::<T>())
         }
     }
 
     /// Removes the `T` value from the collection,
     /// returning it if there was one or `None` if there was not.
-    pub fn remove<T: Any>(&mut self) -> Option<T> {
+    pub fn remove<T: IntoBox<A>>(&mut self) -> Option<T> {
         self.raw.remove(&TypeId::of::<T>())
             .map(|any| *unsafe { any.downcast_unchecked::<T>() })
     }
 
     /// Returns true if the collection contains a value of type `T`.
     #[inline]
-    pub fn contains<T: Any>(&self) -> bool {
+    pub fn contains<T: IntoBox<A>>(&self) -> bool {
         self.raw.contains_key(&TypeId::of::<T>())
     }
 
     /// Gets the entry for the given type in the collection for in-place manipulation
-    pub fn entry<T: Any>(&mut self) -> Entry<T> {
+    pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<A, T> {
         match self.raw.entry(TypeId::of::<T>()) {
             raw::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
                 inner: e,
@@ -175,45 +196,45 @@ impl AnyMap {
     }
 }
 
-impl AsRef<RawAnyMap> for AnyMap {
-    fn as_ref(&self) -> &RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> AsRef<RawMap<A>> for Map<A> {
+    fn as_ref(&self) -> &RawMap<A> {
         &self.raw
     }
 }
 
-impl AsMut<RawAnyMap> for AnyMap {
-    fn as_mut(&mut self) -> &mut RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> AsMut<RawMap<A>> for Map<A> {
+    fn as_mut(&mut self) -> &mut RawMap<A> {
         &mut self.raw
     }
 }
 
-impl Into<RawAnyMap> for AnyMap {
-    fn into(self) -> RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> Into<RawMap<A>> for Map<A> {
+    fn into(self) -> RawMap<A> {
         self.raw
     }
 }
 
-/// A view into a single occupied location in an `AnyMap`.
-pub struct OccupiedEntry<'a, V: 'a> {
-    inner: raw::OccupiedEntry<'a>,
+/// A view into a single occupied location in an `Map`.
+pub struct OccupiedEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
+    inner: raw::OccupiedEntry<'a, A>,
     type_: PhantomData<V>,
 }
 
-/// A view into a single empty location in an `AnyMap`.
-pub struct VacantEntry<'a, V: 'a> {
-    inner: raw::VacantEntry<'a>,
+/// A view into a single empty location in an `Map`.
+pub struct VacantEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
+    inner: raw::VacantEntry<'a, A>,
     type_: PhantomData<V>,
 }
 
-/// A view into a single location in an `AnyMap`, which may be vacant or occupied.
-pub enum Entry<'a, V: 'a> {
+/// A view into a single location in an `Map`, which may be vacant or occupied.
+pub enum Entry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
     /// An occupied Entry
-    Occupied(OccupiedEntry<'a, V>),
+    Occupied(OccupiedEntry<'a, A, V>),
     /// A vacant Entry
-    Vacant(VacantEntry<'a, V>),
+    Vacant(VacantEntry<'a, A, V>),
 }
 
-impl<'a, V: Any + Clone> Entry<'a, V> {
+impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A> + Clone> Entry<'a, A, V> {
     /// Ensures a value is in the entry by inserting the default if empty, and returns
     /// a mutable reference to the value in the entry.
     pub fn or_insert(self, default: V) -> &'a mut V {
@@ -233,7 +254,7 @@ impl<'a, V: Any + Clone> Entry<'a, V> {
     }
 }
 
-impl<'a, V: Any> OccupiedEntry<'a, V> {
+impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> OccupiedEntry<'a, A, V> {
     /// Gets a reference to the value in the entry
     pub fn get(&self) -> &V {
         unsafe { self.inner.get().downcast_ref_unchecked() }
@@ -252,7 +273,7 @@ impl<'a, V: Any> OccupiedEntry<'a, V> {
 
     /// Sets the value of the entry, and returns the entry's old value
     pub fn insert(&mut self, value: V) -> V {
-        unsafe { *self.inner.insert(Box::new(value)).downcast_unchecked() }
+        unsafe { *self.inner.insert(value.into_box()).downcast_unchecked() }
     }
 
     /// Takes the value out of the entry, and returns it
@@ -261,11 +282,11 @@ impl<'a, V: Any> OccupiedEntry<'a, V> {
     }
 }
 
-impl<'a, V: Any> VacantEntry<'a, V> {
+impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> VacantEntry<'a, A, V> {
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it
     pub fn insert(self, value: V) -> &'a mut V {
-        unsafe { self.inner.insert(Box::new(value)).downcast_mut_unchecked() }
+        unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() }
     }
 }
 
@@ -303,7 +324,8 @@ fn bench_get_present(b: &mut ::test::Bencher) {
 
 #[cfg(test)]
 mod tests {
-    use {AnyMap, Entry};
+    use {Map, AnyMap, Entry};
+    use any::{Any, CloneAny};
 
     #[derive(Clone, Debug, PartialEq)] struct A(i32);
     #[derive(Clone, Debug, PartialEq)] struct B(i32);
@@ -380,10 +402,9 @@ mod tests {
         assert_eq!(map.len(), 7);
     }
 
-    #[cfg(feature = "clone")]
     #[test]
     fn test_clone() {
-        let mut map = AnyMap::new();
+        let mut map: Map<CloneAny> = Map::new();
         let _ = map.insert(A(1));
         let _ = map.insert(B(2));
         let _ = map.insert(D(3));
@@ -401,10 +422,22 @@ mod tests {
         assert_eq!(map2.get::<J>(), Some(&J(6)));
     }
 
-    #[cfg(feature = "concurrent")]
     #[test]
-    fn test_concurrent() {
-        fn assert_concurrent<T: Send + Sync>() { }
-        assert_concurrent::<AnyMap>();
+    fn test_varieties() {
+        fn assert_send<T: Send>() { }
+        fn assert_sync<T: Sync>() { }
+        fn assert_clone<T: Clone>() { }
+        assert_send::<Map<Any + Send>>();
+        assert_send::<Map<Any + Send + Sync>>();
+        assert_sync::<Map<Any + Sync>>();
+        assert_sync::<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>>();
     }
 }
similarity index 63%
rename from src/raw/mod.rs
rename to src/raw.rs
index 1ae1a6c09d6e7b53bd6e60876cccaec3a83cb37e..6439771093976a12ac1ccf40904471d981d7bede 100644 (file)
@@ -1,6 +1,6 @@
-//! The raw form of an AnyMap, allowing untyped access.
+//! The raw form of a `Map`, allowing untyped access.
 //!
-//! All relevant details are in the `RawAnyMap` struct.
+//! All relevant details are in the `RawMap` struct.
 
 use std::any::TypeId;
 use std::borrow::Borrow;
@@ -18,16 +18,14 @@ use std::ops::{Index, IndexMut};
 #[cfg(feature = "nightly")]
 use std::ptr;
 
-pub use self::any::Any;
-
-mod any;
+use any::{Any, UncheckedAnyExt};
 
 #[cfg(feature = "nightly")]
 struct TypeIdHasher {
     value: u64,
 }
 
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Clone)]
 #[cfg(feature = "nightly")]
 struct TypeIdState;
 
@@ -56,105 +54,113 @@ impl Hasher for TypeIdHasher {
 }
 
 
-/// The raw, underlying form of an AnyMap.
+/// The raw, underlying form of a `Map`.
 ///
 /// At its essence, this is a wrapper around `HashMap<TypeId, Box<Any>>`, with the portions that
 /// would be memory-unsafe removed or marked unsafe. Normal people are expected to use the safe
-/// `AnyMap` interface instead, but there is the occasional use for this such as iteration over the
-/// contents of an `AnyMap`. However, because you will then be dealing with `Any` trait objects, it
+/// `Map` interface instead, but there is the occasional use for this such as iteration over the
+/// 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)]
-#[cfg_attr(feature = "clone", derive(Clone))]
-pub struct RawAnyMap {
+pub struct RawMap<A: ?Sized + UncheckedAnyExt = Any> {
     #[cfg(feature = "nightly")]
-    inner: HashMap<TypeId, Box<Any>, TypeIdState>,
+    inner: HashMap<TypeId, Box<A>, TypeIdState>,
 
     #[cfg(not(feature = "nightly"))]
-    inner: HashMap<TypeId, Box<Any>>,
+    inner: HashMap<TypeId, Box<A>>,
 }
 
-impl Default for RawAnyMap {
-    fn default() -> RawAnyMap {
-        RawAnyMap::new()
+// #[derive(Clone)] would want A to implement Clone, but in reality it’s only Box<A> that can.
+impl<A: ?Sized + UncheckedAnyExt> Clone for RawMap<A> where Box<A>: Clone {
+    fn clone(&self) -> RawMap<A> {
+        RawMap {
+            inner: self.inner.clone(),
+        }
+    }
+}
+
+impl<A: ?Sized + UncheckedAnyExt> Default for RawMap<A> {
+    fn default() -> RawMap<A> {
+        RawMap::new()
     }
 }
 
 #[cfg(feature = "nightly")]
 impl_common_methods! {
-    field: RawAnyMap.inner;
+    field: RawMap.inner;
     new() => HashMap::with_hash_state(TypeIdState);
     with_capacity(capacity) => HashMap::with_capacity_and_hash_state(capacity, TypeIdState);
 }
 
 #[cfg(not(feature = "nightly"))]
 impl_common_methods! {
-    field: RawAnyMap.inner;
+    field: RawMap.inner;
     new() => HashMap::new();
     with_capacity(capacity) => HashMap::with_capacity(capacity);
 }
 
-/// RawAnyMap iterator.
+/// RawMap iterator.
 #[derive(Clone)]
-pub struct Iter<'a> {
-    inner: hash_map::Iter<'a, TypeId, Box<Any>>,
+pub struct Iter<'a, A: ?Sized + UncheckedAnyExt> {
+    inner: hash_map::Iter<'a, TypeId, Box<A>>,
 }
-impl<'a> Iterator for Iter<'a> {
-    type Item = &'a Any;
-    #[inline] fn next(&mut self) -> Option<&'a Any> { self.inner.next().map(|x| &**x.1) }
+impl<'a, A: ?Sized + UncheckedAnyExt> Iterator for Iter<'a, A> {
+    type Item = &'a A;
+    #[inline] fn next(&mut self) -> Option<&'a A> { self.inner.next().map(|x| &**x.1) }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-impl<'a> ExactSizeIterator for Iter<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> ExactSizeIterator for Iter<'a, A> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-/// RawAnyMap mutable iterator.
-pub struct IterMut<'a> {
-    inner: hash_map::IterMut<'a, TypeId, Box<Any>>,
+/// RawMap mutable iterator.
+pub struct IterMut<'a, A: ?Sized + UncheckedAnyExt> {
+    inner: hash_map::IterMut<'a, TypeId, Box<A>>,
 }
-impl<'a> Iterator for IterMut<'a> {
-    type Item = &'a mut Any;
-    #[inline] fn next(&mut self) -> Option<&'a mut Any> { self.inner.next().map(|x| &mut **x.1) }
+impl<'a, A: ?Sized + UncheckedAnyExt> Iterator for IterMut<'a, A> {
+    type Item = &'a mut A;
+    #[inline] fn next(&mut self) -> Option<&'a mut A> { self.inner.next().map(|x| &mut **x.1) }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-impl<'a> ExactSizeIterator for IterMut<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> ExactSizeIterator for IterMut<'a, A> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-/// RawAnyMap move iterator.
-pub struct IntoIter {
-    inner: hash_map::IntoIter<TypeId, Box<Any>>,
+/// RawMap move iterator.
+pub struct IntoIter<A: ?Sized + UncheckedAnyExt> {
+    inner: hash_map::IntoIter<TypeId, Box<A>>,
 }
-impl Iterator for IntoIter {
-    type Item = Box<Any>;
-    #[inline] fn next(&mut self) -> Option<Box<Any>> { self.inner.next().map(|x| x.1) }
+impl<A: ?Sized + UncheckedAnyExt> Iterator for IntoIter<A> {
+    type Item = Box<A>;
+    #[inline] fn next(&mut self) -> Option<Box<A>> { self.inner.next().map(|x| x.1) }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-impl ExactSizeIterator for IntoIter {
+impl<A: ?Sized + UncheckedAnyExt> ExactSizeIterator for IntoIter<A> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-/// RawAnyMap drain iterator.
+/// RawMap drain iterator.
 #[cfg(feature = "nightly")]
-pub struct Drain<'a> {
-    inner: hash_map::Drain<'a, TypeId, Box<Any>>,
+pub struct Drain<'a, A: ?Sized + UncheckedAnyExt> {
+    inner: hash_map::Drain<'a, TypeId, Box<A>>,
 }
 #[cfg(feature = "nightly")]
-impl<'a> Iterator for Drain<'a> {
-    type Item = Box<Any>;
-    #[inline] fn next(&mut self) -> Option<Box<Any>> { self.inner.next().map(|x| x.1) }
+impl<'a, A: ?Sized + UncheckedAnyExt> Iterator for Drain<'a, A> {
+    type Item = Box<A>;
+    #[inline] fn next(&mut self) -> Option<Box<A>> { self.inner.next().map(|x| x.1) }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 #[cfg(feature = "nightly")]
-impl<'a> ExactSizeIterator for Drain<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> ExactSizeIterator for Drain<'a, A> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-impl RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> RawMap<A> {
     /// An iterator visiting all entries in arbitrary order.
     ///
     /// Iterator element type is `&Any`.
     #[inline]
-    pub fn iter(&self) -> Iter {
+    pub fn iter(&self) -> Iter<A> {
         Iter {
             inner: self.inner.iter(),
         }
@@ -164,24 +170,12 @@ impl RawAnyMap {
     ///
     /// Iterator element type is `&mut Any`.
     #[inline]
-    pub fn iter_mut(&mut self) -> IterMut {
+    pub fn iter_mut(&mut self) -> IterMut<A> {
         IterMut {
             inner: self.inner.iter_mut(),
         }
     }
 
-    /// Creates a consuming iterator, that is, one that moves each item
-    /// out of the map in arbitrary order. The map cannot be used after
-    /// calling this.
-    ///
-    /// Iterator element type is `Box<Any>`.
-    #[inline]
-    pub fn into_iter(self) -> IntoIter {
-        IntoIter {
-            inner: self.inner.into_iter(),
-        }
-    }
-
     /// Clears the map, returning all items as an iterator.
     ///
     /// Iterator element type is `Box<Any>`.
@@ -189,14 +183,14 @@ impl RawAnyMap {
     /// Keeps the allocated memory for reuse.
     #[inline]
     #[cfg(feature = "nightly")]
-    pub fn drain(&mut self) -> Drain {
+    pub fn drain(&mut self) -> Drain<A> {
         Drain {
             inner: self.inner.drain(),
         }
     }
 
     /// Gets the entry for the given type in the collection for in-place manipulation.
-    pub fn entry(&mut self, key: TypeId) -> Entry {
+    pub fn entry(&mut self, key: TypeId) -> Entry<A> {
         match self.inner.entry(key) {
             hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
                 inner: e,
@@ -211,7 +205,7 @@ impl RawAnyMap {
     ///
     /// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
     /// form *must* match those for the key type.
-    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&Any>
+    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&A>
     where TypeId: Borrow<Q>, Q: Hash + Eq {
         self.inner.get(k).map(|x| &**x)
     }
@@ -229,7 +223,7 @@ impl RawAnyMap {
     ///
     /// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
     /// form *must* match those for the key type.
-    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut Any>
+    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut A>
     where TypeId: Borrow<Q>, Q: Hash + Eq {
         self.inner.get_mut(k).map(|x| &mut **x)
     }
@@ -239,7 +233,7 @@ impl RawAnyMap {
     ///
     /// It is the caller’s responsibility to ensure that the key corresponds with the type ID of
     /// the value. If they do not, memory safety may be violated.
-    pub unsafe fn insert(&mut self, key: TypeId, value: Box<Any>) -> Option<Box<Any>> {
+    pub unsafe fn insert(&mut self, key: TypeId, value: Box<A>) -> Option<Box<A>> {
         self.inner.insert(key, value)
     }
 
@@ -248,61 +242,63 @@ impl RawAnyMap {
     ///
     /// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
     /// form *must* match those for the key type.
-    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<Box<Any>>
+    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<Box<A>>
     where TypeId: Borrow<Q>, Q: Hash + Eq {
         self.inner.remove(k)
     }
 
 }
 
-impl<Q> Index<Q> for RawAnyMap where TypeId: Borrow<Q>, Q: Eq + Hash {
-    type Output = Any;
+impl<A: ?Sized + UncheckedAnyExt, Q> Index<Q> for RawMap<A> where TypeId: Borrow<Q>, Q: Eq + Hash {
+    type Output = A;
 
-    fn index<'a>(&'a self, index: Q) -> &'a Any {
+    fn index<'a>(&'a self, index: Q) -> &'a A {
         self.get(&index).expect("no entry found for key")
     }
 }
 
-impl<Q> IndexMut<Q> for RawAnyMap where TypeId: Borrow<Q>, Q: Eq + Hash {
-    fn index_mut<'a>(&'a mut self, index: Q) -> &'a mut Any {
+impl<A: ?Sized + UncheckedAnyExt, Q> IndexMut<Q> for RawMap<A> where TypeId: Borrow<Q>, Q: Eq + Hash {
+    fn index_mut<'a>(&'a mut self, index: Q) -> &'a mut A {
         self.get_mut(&index).expect("no entry found for key")
     }
 }
 
-impl IntoIterator for RawAnyMap {
-    type Item = Box<Any>;
-    type IntoIter = IntoIter;
+impl<A: ?Sized + UncheckedAnyExt> IntoIterator for RawMap<A> {
+    type Item = Box<A>;
+    type IntoIter = IntoIter<A>;
 
-    fn into_iter(self) -> IntoIter {
-        self.into_iter()
+    fn into_iter(self) -> IntoIter<A> {
+        IntoIter {
+            inner: self.inner.into_iter(),
+        }
     }
 }
 
-/// A view into a single occupied location in a `RawAnyMap`.
-pub struct OccupiedEntry<'a> {
-    inner: hash_map::OccupiedEntry<'a, TypeId, Box<Any>>,
+/// A view into a single occupied location in a `RawMap`.
+pub struct OccupiedEntry<'a, A: ?Sized + UncheckedAnyExt> {
+    inner: hash_map::OccupiedEntry<'a, TypeId, Box<A>>,
 }
 
-/// A view into a single empty location in a `RawAnyMap`.
-pub struct VacantEntry<'a> {
-    inner: hash_map::VacantEntry<'a, TypeId, Box<Any>>,
+/// A view into a single empty location in a `RawMap`.
+pub struct VacantEntry<'a, A: ?Sized + UncheckedAnyExt> {
+    inner: hash_map::VacantEntry<'a, TypeId, Box<A>>,
 }
 
-/// A view into a single location in an AnyMap, which may be vacant or occupied.
-pub enum Entry<'a> {
+/// A view into a single location in a `RawMap`, which may be vacant or occupied.
+pub enum Entry<'a, A: ?Sized + UncheckedAnyExt> {
     /// An occupied Entry
-    Occupied(OccupiedEntry<'a>),
+    Occupied(OccupiedEntry<'a, A>),
     /// A vacant Entry
-    Vacant(VacantEntry<'a>),
+    Vacant(VacantEntry<'a, A>),
 }
 
-impl<'a> Entry<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> Entry<'a, A> {
     /// Ensures a value is in the entry by inserting the default if empty, and returns
     /// a mutable reference to the value in the entry.
     ///
     /// It is the caller’s responsibility to ensure that the key of the entry corresponds with
     /// the type ID of `value`. If they do not, memory safety may be violated.
-    pub unsafe fn or_insert(self, default: Box<Any>) -> &'a mut Any {
+    pub unsafe fn or_insert(self, default: Box<A>) -> &'a mut A {
         match self {
             Entry::Occupied(inner) => inner.into_mut(),
             Entry::Vacant(inner) => inner.insert(default),
@@ -314,7 +310,7 @@ impl<'a> Entry<'a> {
     ///
     /// It is the caller’s responsibility to ensure that the key of the entry corresponds with
     /// the type ID of `value`. If they do not, memory safety may be violated.
-    pub unsafe fn or_insert_with<F: FnOnce() -> Box<Any>>(self, default: F) -> &'a mut Any {
+    pub unsafe fn or_insert_with<F: FnOnce() -> Box<A>>(self, default: F) -> &'a mut A {
         match self {
             Entry::Occupied(inner) => inner.into_mut(),
             Entry::Vacant(inner) => inner.insert(default()),
@@ -322,20 +318,20 @@ impl<'a> Entry<'a> {
     }
 }
 
-impl<'a> OccupiedEntry<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> OccupiedEntry<'a, A> {
     /// Gets a reference to the value in the entry.
-    pub fn get(&self) -> &Any {
+    pub fn get(&self) -> &A {
         &**self.inner.get() 
     }
 
     /// Gets a mutable reference to the value in the entry.
-    pub fn get_mut(&mut self) -> &mut Any {
+    pub fn get_mut(&mut self) -> &mut A {
         &mut **self.inner.get_mut()
     }
 
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
     /// with a lifetime bound to the collection itself.
-    pub fn into_mut(self) -> &'a mut Any {
+    pub fn into_mut(self) -> &'a mut A {
         &mut **self.inner.into_mut()
     }
 
@@ -343,23 +339,23 @@ impl<'a> OccupiedEntry<'a> {
     ///
     /// It is the caller’s responsibility to ensure that the key of the entry corresponds with
     /// the type ID of `value`. If they do not, memory safety may be violated.
-    pub unsafe fn insert(&mut self, value: Box<Any>) -> Box<Any> {
+    pub unsafe fn insert(&mut self, value: Box<A>) -> Box<A> {
         self.inner.insert(value)
     }
 
     /// Takes the value out of the entry, and returns it.
-    pub fn remove(self) -> Box<Any> {
+    pub fn remove(self) -> Box<A> {
         self.inner.remove()
     }
 }
 
-impl<'a> VacantEntry<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> VacantEntry<'a, A> {
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it
     ///
     /// It is the caller’s responsibility to ensure that the key of the entry corresponds with
     /// the type ID of `value`. If they do not, memory safety may be violated.
-    pub unsafe fn insert(self, value: Box<Any>) -> &'a mut Any {
+    pub unsafe fn insert(self, value: Box<A>) -> &'a mut A {
         &mut **self.inner.insert(value)
     }
 }
diff --git a/src/raw/any.rs b/src/raw/any.rs
deleted file mode 100644 (file)
index d908040..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-use std::fmt;
-use std::any::Any as StdAny;
-
-#[cfg(feature = "clone")]
-#[doc(hidden)]
-pub trait CloneToAny {
-    /// Clone `self` into a new `Box<Any>` object.
-    fn clone_to_any(&self) -> Box<Any>;
-}
-
-#[cfg(feature = "clone")]
-impl<T: Any + Clone> CloneToAny for T {
-    fn clone_to_any(&self) -> Box<Any> {
-        Box::new(self.clone())
-    }
-}
-
-macro_rules! define_any {
-    (#[$m:meta] $t:item $i:item) => {
-        /// A type to emulate dynamic typing.
-        ///
-        /// Every suitable type with no non-`'static` references implements `Any`. See the
-        /// [`std::any` documentation](https://doc.rust-lang.org/std/any/index.html) for more
-        /// details on `Any` in general.
-        ///
-        /// This trait is not `std::any::Any` but rather a type extending that for this library’s
-        /// purposes; most specifically, there are a couple of Cargo features that can be enabled
-        /// which will alter the constraints of what comprises a suitable type:
-        ///
-        /// <table>
-        ///     <thead>
-        ///         <tr>
-        ///             <th title="The name of the Cargo feature to enable">Feature name</th>
-        ///             <th title="If a type doesn’t satisfy these bounds, it won’t implement Any">Additional bounds</th>
-        ///             <th title="Were these docs built with this feature enabled?">Enabled in these docs?</th>
-        ///         </tr>
-        ///     </thead>
-        ///     <tbody>
-        ///         <tr>
-        ///             <th><code>clone</code></th>
-        ///             <td><code><a class=trait title=core::clone::Clone
-        ///             href=http://doc.rust-lang.org/std/clone/trait.Clone.html
-        ///             >Clone</a></code></td>
-        #[cfg_attr(feature = "clone", doc = "             <td>Yes</td>")]
-        #[cfg_attr(not(feature = "clone"), doc = "             <td>No</td>")]
-        ///         </tr>
-        ///         <tr>
-        ///             <th><code>concurrent</code></th>
-        ///             <td><code><a class=trait title=core::marker::Send
-        ///             href=http://doc.rust-lang.org/std/marker/trait.Send.html
-        ///             >Send</a> + <a class=trait title=core::marker::Sync
-        ///             href=http://doc.rust-lang.org/std/marker/trait.Sync.html
-        ///             >Sync</a></code></td>
-        #[cfg_attr(feature = "concurrent", doc = "             <td>Yes</td>")]
-        #[cfg_attr(not(feature = "concurrent"), doc = "             <td>No</td>")]
-        ///         </tr>
-        ///     </tbody>
-        /// </table>
-        #[$m] $t
-        #[$m] $i
-    }
-}
-
-define_any! {
-    #[cfg(all(not(feature = "clone"), not(feature = "concurrent")))]
-    pub trait Any: StdAny { }
-    impl<T: StdAny> Any for T { }
-}
-
-define_any! {
-    #[cfg(all(feature = "clone", not(feature = "concurrent")))]
-    pub trait Any: StdAny + CloneToAny { }
-    impl<T: StdAny + Clone> Any for T { }
-}
-
-define_any! {
-    #[cfg(all(not(feature = "clone"), feature = "concurrent"))]
-    pub trait Any: StdAny + Send + Sync { }
-    impl<T: StdAny + Send + Sync> Any for T { }
-}
-
-define_any! {
-    #[cfg(all(feature = "clone", feature = "concurrent"))]
-    pub trait Any: StdAny + CloneToAny + Send + Sync { }
-    impl<T: StdAny + Clone + Send + Sync> Any for T { }
-}
-
-#[cfg(feature = "clone")]
-impl Clone for Box<Any> {
-    fn clone(&self) -> Box<Any> {
-        (**self).clone_to_any()
-    }
-}
-
-impl<'a> fmt::Debug for &'a Any {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("&Any")
-    }
-}
-
-impl<'a> fmt::Debug for Box<Any> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("Box<Any>")
-    }
-}
diff --git a/src/unchecked_any.rs b/src/unchecked_any.rs
deleted file mode 100644 (file)
index 52dee67..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-use raw::Any;
-use std::mem;
-#[cfg(feature = "nightly")]
-use std::raw::TraitObject;
-
-#[cfg(not(feature = "nightly"))]
-#[repr(C)]
-#[allow(raw_pointer_derive)]
-#[derive(Copy, Clone)]
-struct TraitObject {
-    pub data: *mut (),
-    pub vtable: *mut (),
-}
-
-#[allow(missing_docs)]  // Bogus warning (it’s not public outside the crate), ☹
-pub trait UncheckedAnyExt {
-    unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T;
-    unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T;
-    unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T>;
-}
-
-impl UncheckedAnyExt for Any {
-    unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
-        mem::transmute(mem::transmute::<_, TraitObject>(self).data)
-    }
-
-    unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
-        mem::transmute(mem::transmute::<_, TraitObject>(self).data)
-    }
-
-    unsafe fn downcast_unchecked<T: 'static>(self: Box<Any>) -> Box<T> {
-        mem::transmute(mem::transmute::<_, TraitObject>(self).data)
-    }
-}