From cc49e87f43942ac4c38e273a7ec60a8d3a7fdcee Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 13 Sep 2017 08:17:01 +1000 Subject: [PATCH] add Shared type to fix inference fail on nightly --- src/conslist.rs | 33 +++++++++-------- src/lens.rs | 16 ++++---- src/lib.rs | 1 + src/list.rs | 33 +++++++++-------- src/map/mod.rs | 99 +++++++++++++++++++++++++------------------------ src/queue.rs | 15 ++++---- src/set.rs | 7 ++-- src/shared.rs | 20 ++++++++++ 8 files changed, 126 insertions(+), 98 deletions(-) create mode 100644 src/shared.rs diff --git a/src/conslist.rs b/src/conslist.rs index e74c79d..8879ed6 100644 --- a/src/conslist.rs +++ b/src/conslist.rs @@ -26,6 +26,7 @@ use std::ops::Deref; use std::hash::{Hash, Hasher}; use std::cmp::Ordering; use std::borrow::Borrow; +use shared::Shared; use self::ConsListNode::{Cons, Nil}; @@ -113,7 +114,7 @@ macro_rules! conslist { /// untrained ear. pub fn cons(car: RA, cdr: RD) -> ConsList where - Arc: From, + RA: Shared, RD: Borrow>, { cdr.borrow().cons(car) @@ -149,9 +150,9 @@ impl ConsList { /// Construct a list with a single element. pub fn singleton(v: R) -> ConsList where - Arc: From, + R: Shared, { - ConsList(Arc::new(Cons(1, Arc::from(v), conslist![]))) + ConsList(Arc::new(Cons(1, v.shared(), conslist![]))) } /// Construct a list by consuming an `IntoIterator`. @@ -176,9 +177,9 @@ impl ConsList { pub fn from(it: I) -> ConsList where I: IntoIterator, - Arc: From, + R: Shared, { - it.into_iter().map(|a| Arc::from(a)).collect() + it.into_iter().map(|a| a.shared()).collect() } /// Test whether a list is empty. @@ -197,9 +198,9 @@ impl ConsList { /// Time: O(1) pub fn cons(&self, car: R) -> ConsList where - Arc: From, + R: Shared, { - ConsList(Arc::new(Cons(self.len() + 1, Arc::from(car), self.clone()))) + ConsList(Arc::new(Cons(self.len() + 1, car.shared(), self.clone()))) } /// Get the first element of a list. @@ -491,9 +492,9 @@ where /// ``` pub fn insert(&self, item: T) -> ConsList where - Arc: From, + T: Shared, { - self.insert_ref(Arc::from(item)) + self.insert_ref(item.shared()) } fn insert_ref(&self, item: Arc) -> ConsList { @@ -709,7 +710,7 @@ impl Sum for ConsList { impl FromIterator for ConsList where - Arc: From, + T: Shared, { fn from_iter(source: I) -> Self where @@ -726,28 +727,28 @@ where impl<'a, A, R> From<&'a [R]> for ConsList where - Arc: From<&'a R>, + &'a R: Shared, { fn from(slice: &'a [R]) -> Self { - slice.into_iter().map(|a| Arc::from(a)).collect() + slice.into_iter().map(|a| a.shared()).collect() } } impl From> for ConsList where - Arc: From, + R: Shared, { fn from(vec: Vec) -> Self { - vec.into_iter().map(|a| Arc::from(a)).collect() + vec.into_iter().map(|a| a.shared()).collect() } } impl<'a, A, R> From<&'a Vec> for ConsList where - Arc: From<&'a R>, + &'a R: Shared, { fn from(vec: &'a Vec) -> Self { - vec.into_iter().map(|a| Arc::from(a)).collect() + vec.into_iter().map(|a| a.shared()).collect() } } diff --git a/src/lens.rs b/src/lens.rs index 060256d..0f5ab29 100644 --- a/src/lens.rs +++ b/src/lens.rs @@ -18,6 +18,8 @@ use std::marker::PhantomData; use std::sync::Arc; +use shared::Shared; + /// A lens from `From` to `To` where the focus of the lens isn't guaranteed to /// exist inside `From`. Operations on these lenses therefore return `Option`s. pub trait PartialLens: Clone { @@ -31,7 +33,7 @@ pub trait PartialLens: Clone { /// operation succeeded. fn try_put(&self, v: Option, s: &Self::From) -> Option where - Arc: From; + Convert: Shared; /// Compose this lens with a lens from `To` to a new type `Next`, yielding /// a lens from `From` to `Next`. @@ -57,7 +59,7 @@ pub trait Lens: PartialLens { /// Put a value into the lens, returning the updated `From` value. fn put(&self, v: Convert, s: &Self::From) -> Self::From where - Arc: From, + Convert: Shared, { self.try_put(Some(v), s).unwrap() } @@ -117,7 +119,7 @@ impl PartialLens for Compose fn try_put(&self, v: Option, s: &A) -> Option where - Arc: From, + FromC: Shared, { self.left .try_get(&s) @@ -184,9 +186,9 @@ impl PartialLens for GeneralLens { fn try_put(&self, v: Option, s: &A) -> Option where - Arc: From, + Convert: Shared, { - Some((self.put)(s, From::from(v.unwrap()))) + Some((self.put)(s, v.unwrap().shared())) } } @@ -197,9 +199,9 @@ impl Lens for GeneralLens { fn put(&self, v: Convert, s: &A) -> A where - Arc: From, + Convert: Shared, { - (self.put)(s, From::from(v)) + (self.put)(s, v.shared()) } } diff --git a/src/lib.rs b/src/lib.rs index 245487d..bd47283 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,6 +76,7 @@ pub mod list; pub mod queue; pub mod iter; pub mod lens; +pub mod shared; pub use conslist::ConsList; pub use map::Map; diff --git a/src/list.rs b/src/list.rs index b960ae0..749c2ea 100644 --- a/src/list.rs +++ b/src/list.rs @@ -20,6 +20,7 @@ use std::hash::{Hash, Hasher}; use std::fmt::{Debug, Formatter, Error}; use std::borrow::Borrow; use queue::Queue; +use shared::Shared; use self::ListNode::{Nil, Cons}; @@ -104,7 +105,7 @@ macro_rules! list { /// untrained ear. pub fn cons(car: RA, cdr: RD) -> List where - Arc: From, + RA: Shared, RD: Borrow>, { cdr.borrow().cons(car) @@ -138,7 +139,7 @@ impl List { /// Construct a list with a single value. pub fn singleton(a: R) -> Self where - Arc: From, + R: Shared, { List::new().push_front(a) } @@ -165,9 +166,9 @@ impl List { pub fn from(it: I) -> List where I: IntoIterator, - Arc: From, + R: Shared, { - it.into_iter().map(|a| Arc::from(a)).collect() + it.into_iter().map(|a| a.shared()).collect() } /// Test whether a list is empty. @@ -269,16 +270,16 @@ impl List { /// current list. pub fn cons(&self, a: R) -> Self where - Arc: From, + R: Shared, { - List(Arc::new(Cons(1, Arc::from(a), Queue::new()))).append(self) + List(Arc::new(Cons(1, a.shared(), Queue::new()))).append(self) } /// Construct a list with a new value prepended to the front of the /// current list. pub fn push_front(&self, a: R) -> Self where - Arc: From, + R: Shared, { self.cons(a) } @@ -292,16 +293,16 @@ impl List { /// doubt did, this method is also available as `List::push_back()`. pub fn snoc(&self, a: R) -> Self where - Arc: From, + R: Shared, { - self.append(&List(Arc::new(Cons(1, Arc::from(a), Queue::new())))) + self.append(&List(Arc::new(Cons(1, a.shared(), Queue::new())))) } /// Construct a list with a new value appended to the back of the /// current list. pub fn push_back(&self, a: R) -> Self where - Arc: From, + R: Shared, { self.snoc(a) } @@ -522,9 +523,9 @@ impl List { /// ``` pub fn insert(&self, item: T) -> Self where - Arc: From, + T: Shared, { - self.insert_ref(Arc::from(item)) + self.insert_ref(item.shared()) } fn insert_ref(&self, item: Arc) -> Self { @@ -698,7 +699,7 @@ impl Sum for List { impl FromIterator for List where - Arc: From, + T: Shared, { fn from_iter(source: I) -> Self where @@ -712,7 +713,7 @@ where impl<'a, A, T> From<&'a [T]> for List where - Arc: From<&'a T>, + &'a T: Shared, { fn from(slice: &'a [T]) -> List { slice.into_iter().collect() @@ -721,7 +722,7 @@ where impl From> for List where - Arc: From, + T: Shared, { fn from(vec: Vec) -> List { vec.into_iter().collect() @@ -730,7 +731,7 @@ where impl<'a, A, T> From<&'a Vec> for List where - Arc: From<&'a T>, + &'a T: Shared, { fn from(vec: &'a Vec) -> List { vec.into_iter().collect() diff --git a/src/map/mod.rs b/src/map/mod.rs index 68f286c..d48ec61 100644 --- a/src/map/mod.rs +++ b/src/map/mod.rs @@ -19,6 +19,7 @@ use std::ops::Add; use std::borrow::Borrow; use std::marker::PhantomData; +use shared::Shared; use lens::PartialLens; use self::MapNode::{Leaf, Two, Three}; @@ -97,10 +98,10 @@ impl Map { /// ``` pub fn singleton(k: RK, v: RV) -> Map where - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { - Map::two(map![], Arc::from(k), Arc::from(v), map![]) + Map::two(map![], k.shared(), v.shared(), map![]) } /// Test whether a map is empty. @@ -300,10 +301,10 @@ impl Map { /// ``` pub fn lens(key: RK) -> MapLens where - Arc: From, + RK: Shared, { MapLens { - key: Arc::from(key), + key: key.shared(), value: PhantomData, } } @@ -355,9 +356,9 @@ impl Map { /// ``` pub fn get_or(&self, k: &K, default: RV) -> Arc where - Arc: From, + RV: Shared, { - self.get(k).unwrap_or(Arc::from(default)) + self.get(k).unwrap_or(default.shared()) } /// Test for the presence of a key in a map. @@ -407,10 +408,10 @@ impl Map { /// ``` pub fn insert(&self, k: RK, v: RV) -> Self where - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { - walk::ins_down(conslist![], Arc::from(k), Arc::from(v), self.clone()) + walk::ins_down(conslist![], k.shared(), v.shared(), self.clone()) } fn insert_ref(&self, k: Arc, v: Arc) -> Self { @@ -426,12 +427,12 @@ impl Map { /// Time: O(log n) pub fn insert_with(self, k: RK, v: RV, f: F) -> Self where - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, F: Fn(Arc, Arc) -> Arc, { - let ak = Arc::from(k); - let av = Arc::from(v); + let ak = k.shared(); + let av = v.shared(); match self.pop_with_key(&ak) { None => self.insert_ref(ak, av), Some((_, v2, m)) => m.insert_ref(ak, f(v2, av)), @@ -448,11 +449,11 @@ impl Map { pub fn insert_with_key(self, k: RK, v: RV, f: F) -> Self where F: Fn(Arc, Arc, Arc) -> Arc, - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { - let ak = Arc::from(k); - let av = Arc::from(v); + let ak = k.shared(); + let av = v.shared(); match self.pop_with_key(&ak) { None => self.insert_ref(ak, av), Some((_, v2, m)) => m.insert_ref(ak.clone(), f(ak, v2, av)), @@ -470,11 +471,11 @@ impl Map { pub fn insert_lookup_with_key(self, k: RK, v: RV, f: F) -> (Option>, Self) where F: Fn(Arc, Arc, Arc) -> Arc, - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { - let ak = Arc::from(k); - let av = Arc::from(v); + let ak = k.shared(); + let av = v.shared(); match self.pop_with_key(&ak) { None => (None, self.insert_ref(ak, av)), Some((_, v2, m)) => (Some(v2.clone()), m.insert_ref(ak.clone(), f(ak, v2, av))), @@ -553,9 +554,9 @@ impl Map { pub fn alter(&self, f: F, k: RK) -> Self where F: Fn(Option>) -> Option>, - Arc: From, + RK: Shared, { - let ak = Arc::from(k); + let ak = k.shared(); let pop = self.pop_with_key(&*ak); match (f(pop.as_ref().map(|&(_, ref v, _)| v.clone())), pop) { (None, None) => self.clone(), @@ -1086,8 +1087,8 @@ impl Iterator for Values { impl FromIterator<(RK, RV)> for Map where - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { fn from_iter(i: T) -> Self where @@ -1144,9 +1145,9 @@ where fn try_put(&self, cv: Option, s: &Self::From) -> Option where - Arc: From, + Convert: Shared, { - Some(match cv.map(From::from) { + Some(match cv.map(Shared::shared) { None => s.remove(&self.key), Some(v) => s.insert(self.key.clone(), v), }) @@ -1161,84 +1162,84 @@ impl AsRef> for Map { impl<'a, K: Ord, V: Clone, RK, RV> From<&'a [(RK, RV)]> for Map where - Arc: From<&'a RK>, - Arc: From<&'a RV>, + &'a RK: Shared, + &'a RV: Shared, { fn from(m: &'a [(RK, RV)]) -> Map { m.into_iter() - .map(|&(ref k, ref v)| (Arc::from(k), Arc::from(v))) + .map(|&(ref k, ref v)| (k.shared(), v.shared())) .collect() } } impl From> for Map where - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { fn from(m: Vec<(RK, RV)>) -> Map { m.into_iter() - .map(|(k, v)| (Arc::from(k), Arc::from(v))) + .map(|(k, v)| (k.shared(), v.shared())) .collect() } } impl<'a, K: Ord, V, RK, RV> From<&'a Vec<(RK, RV)>> for Map where - Arc: From<&'a RK>, - Arc: From<&'a RV>, + &'a RK: Shared, + &'a RV: Shared, { fn from(m: &'a Vec<(RK, RV)>) -> Map { m.into_iter() - .map(|&(ref k, ref v)| (Arc::from(k), Arc::from(v))) + .map(|&(ref k, ref v)| (k.shared(), v.shared())) .collect() } } impl From> for Map where - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { fn from(m: HashMap) -> Map { m.into_iter() - .map(|(k, v)| (Arc::from(k), Arc::from(v))) + .map(|(k, v)| (k.shared(), v.shared())) .collect() } } impl<'a, K: Ord, V, RK: Eq + Hash, RV> From<&'a HashMap> for Map where - Arc: From<&'a RK>, - Arc: From<&'a RV>, + &'a RK: Shared, + &'a RV: Shared, { fn from(m: &'a HashMap) -> Map { m.into_iter() - .map(|(k, v)| (Arc::from(k), Arc::from(v))) + .map(|(k, v)| (k.shared(), v.shared())) .collect() } } impl From> for Map where - Arc: From, - Arc: From, + RK: Shared, + RV: Shared, { fn from(m: BTreeMap) -> Map { m.into_iter() - .map(|(k, v)| (Arc::from(k), Arc::from(v))) + .map(|(k, v)| (k.shared(), v.shared())) .collect() } } impl<'a, K: Ord, V, RK, RV> From<&'a BTreeMap> for Map where - Arc: From<&'a RK>, - Arc: From<&'a RV>, + &'a RK: Shared, + &'a RV: Shared, { fn from(m: &'a BTreeMap) -> Map { m.into_iter() - .map(|(k, v)| (Arc::from(k), Arc::from(v))) + .map(|(k, v)| (k.shared(), v.shared())) .collect() } } diff --git a/src/queue.rs b/src/queue.rs index fa39195..5e352d4 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use std::iter::FromIterator; use std::fmt; use conslist::ConsList; +use shared::Shared; /// A strict queue backed by a pair of linked lists. /// @@ -26,9 +27,9 @@ impl Queue { pub fn from(it: I) -> Queue where I: IntoIterator, - Arc: From, + R: Shared, { - it.into_iter().map(|a| Arc::from(a)).collect() + it.into_iter().map(|a| a.shared()).collect() } /// Test whether a queue is empty. @@ -51,7 +52,7 @@ impl Queue { /// Time: O(1) pub fn push(&self, v: R) -> Self where - Arc: From, + R: Shared, { Queue(self.0.clone(), self.1.cons(v)) } @@ -142,7 +143,7 @@ impl<'a, A> IntoIterator for &'a Queue { impl FromIterator for Queue where - Arc: From, + T: Shared, { fn from_iter(source: I) -> Self where @@ -156,7 +157,7 @@ where impl<'a, A, T> From<&'a [T]> for Queue where - Arc: From<&'a T>, + &'a T: Shared, { fn from(slice: &'a [T]) -> Queue { slice.into_iter().collect() @@ -165,7 +166,7 @@ where impl From> for Queue where - Arc: From, + T: Shared, { fn from(vec: Vec) -> Queue { vec.into_iter().collect() @@ -174,7 +175,7 @@ where impl<'a, A, T> From<&'a Vec> for Queue where - Arc: From<&'a T>, + &'a T: Shared, { fn from(vec: &'a Vec) -> Queue { vec.into_iter().collect() diff --git a/src/set.rs b/src/set.rs index ebc9832..3c89446 100644 --- a/src/set.rs +++ b/src/set.rs @@ -14,6 +14,7 @@ use std::hash::{Hash, Hasher}; use std::ops::{Add, Mul}; use std::borrow::Borrow; use map::{self, Map}; +use shared::Shared; /// Construct a set from a sequence of values. /// @@ -71,7 +72,7 @@ impl Set { /// ``` pub fn singleton(a: R) -> Self where - Arc: From, + R: Shared, { Set(Map::::singleton(a, ())) } @@ -155,7 +156,7 @@ impl Set { /// ``` pub fn insert(&self, a: R) -> Self where - Arc: From, + R: Shared, { Set(self.0.insert(a, ())) } @@ -369,7 +370,7 @@ impl Iterator for Iter { impl FromIterator for Set where - Arc: From, + RA: Shared, { fn from_iter(i: T) -> Self where diff --git a/src/shared.rs b/src/shared.rs new file mode 100644 index 0000000..3292ec6 --- /dev/null +++ b/src/shared.rs @@ -0,0 +1,20 @@ +// This module works around the fact that you can't rely on +// `Arc: From` to only have one possible implementation anymore (that is, where `U = T`). + +use std::sync::Arc; + +pub trait Shared { + fn shared(self) -> Arc; +} + +impl Shared for T { + fn shared(self) -> Arc { + Arc::from(self) + } +} + +impl Shared for Arc { + fn shared(self) -> Arc { + self + } +}