Skip to content

Commit

Permalink
Merge pull request #223 from mobusoperandi/insert_move
Browse files Browse the repository at this point in the history
feat: return type does not have to be Clone
  • Loading branch information
mightyiam authored Jun 18, 2022
2 parents b2f40ca + 044862d commit c5e4543
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 29 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,10 @@ The following apply to the key type and to the function's return type:
- [`'static`]: key and return values are owned by a store which is owned by a static.
- [`Send`] and [`Sync`]: for parallel access.

And the return type must be [`Clone`] because it is cloned for insertion into the store.

## Store bounds

Another source of bounds on the key type and the return type is the implementation of [`MemoizationStore`] for the store type.
By the way, the provided implementation of [`MemoizationStore`] for the default store type [`HashMap`] bounds `K: Eq + Hash`.
By the way, the provided implementation of [`MemoizationStore`] for the default store type [`HashMap`] bounds `K: Eq + Hash, R: Clone`.

# Generic functions

Expand Down
5 changes: 2 additions & 3 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn expand_fn_block(original_fn_block: Block, return_type: Type, attr_args: AttrA
// However, since the concrete store is already obtained and since presumably the
// following `::get` should be cheap, releasing the exclusive lock, obtaining a read lock
// and obtaining the store again does not seem reasonable.
let attempt: ::core::option::Option<#return_type> = ::michie::MemoizationStore::get(store, #key_ref).cloned();
let attempt: ::core::option::Option<#return_type> = ::michie::MemoizationStore::get(store, #key_ref);
::core::mem::drop(type_map_mutex_guard);
if let ::core::option::Option::Some(hit) = attempt {
hit
Expand All @@ -170,8 +170,7 @@ fn expand_fn_block(original_fn_block: Block, return_type: Type, attr_args: AttrA
}
downcast_mut_with_inference_hint::<#store_type>(store, || #store_init).unwrap()
};
::michie::MemoizationStore::insert(store, #key, ::core::clone::Clone::clone(&miss));
miss
::michie::MemoizationStore::insert(store, #key, miss)
}
}}
}
Expand Down
24 changes: 14 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,34 @@ use std::{
pub use michie_macro::memoized;

pub trait MemoizationStore<K, R> {
fn insert(&mut self, key: K, value: R);
fn get(&self, key: &K) -> Option<&R>;
fn insert(&mut self, key: K, value: R) -> R;
fn get(&self, key: &K) -> Option<R>;
}

impl<K, R> MemoizationStore<K, R> for HashMap<K, R>
where
K: Eq + Hash,
R: Clone,
{
fn insert(&mut self, key: K, value: R) {
HashMap::insert(self, key, value);
fn insert(&mut self, key: K, value: R) -> R {
HashMap::insert(self, key, value.clone());
value
}
fn get(&self, key: &K) -> Option<&R> {
HashMap::get(self, key)
fn get(&self, key: &K) -> Option<R> {
HashMap::get(self, key).cloned()
}
}

impl<K, R> MemoizationStore<K, R> for BTreeMap<K, R>
where
K: Ord,
R: Clone,
{
fn insert(&mut self, key: K, value: R) {
BTreeMap::insert(self, key, value);
fn insert(&mut self, key: K, value: R) -> R {
BTreeMap::insert(self, key, value.clone());
value
}
fn get(&self, key: &K) -> Option<&R> {
BTreeMap::get(self, key)
fn get(&self, key: &K) -> Option<R> {
BTreeMap::get(self, key).cloned()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ use michie::{memoized, MemoizationStore};

struct Store;
impl MemoizationStore<usize, usize> for Store {
fn insert(&mut self, _key: usize, _value: usize) {}
fn get(&self, _key: &usize) -> Option<&usize> {
fn insert(&mut self, _key: usize, value: usize) -> usize {
value
}
fn get(&self, _key: &usize) -> Option<usize> {
None
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error[E0277]: the trait bound `Store: Default` is not satisfied
--> tests/compile_fail/store_init_omitted_and_default_not_implemented.rs:10:1
--> tests/compile_fail/store_init_omitted_and_default_not_implemented.rs:12:1
|
10 | #[memoized(key_expr = input, store_type = Store)]
12 | #[memoized(key_expr = input, store_type = Store)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Store`
|
= note: this error originates in the attribute macro `memoized` (in Nightly builds, run with -Z macro-backtrace for more info)
26 changes: 17 additions & 9 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ fn store_init_is_omitted() {
}
}
impl MemoizationStore<usize, usize> for Store {
fn insert(&mut self, _key: usize, _value: usize) {}
fn get(&self, _key: &usize) -> Option<&usize> {
fn insert(&mut self, _key: usize, value: usize) -> usize {
value
}
fn get(&self, _key: &usize) -> Option<usize> {
None
}
}
Expand All @@ -110,8 +112,10 @@ fn store_init_is_used_instead_of_implementation_of_the_default_trait() {
}
}
impl MemoizationStore<usize, usize> for Store {
fn insert(&mut self, _key: usize, _value: usize) {}
fn get(&self, _key: &usize) -> Option<&usize> {
fn insert(&mut self, _key: usize, value: usize) -> usize {
value
}
fn get(&self, _key: &usize) -> Option<usize> {
None
}
}
Expand Down Expand Up @@ -142,8 +146,10 @@ fn store_init_includes_a_concrete_store_type() {
}
}
impl<K, R> MemoizationStore<K, R> for Store<K, R> {
fn insert(&mut self, _key: K, _value: R) {}
fn get(&self, _key: &K) -> Option<&R> {
fn insert(&mut self, _key: K, value: R) -> R {
value
}
fn get(&self, _key: &K) -> Option<R> {
None
}
}
Expand All @@ -165,8 +171,10 @@ fn store_init_includes_function_from_impl_block_that_has_bound_on_k_and_v() {
}
}
impl MemoizationStore<usize, usize> for Store<()> {
fn insert(&mut self, _key: usize, _value: usize) {}
fn get(&self, _key: &usize) -> Option<&usize> {
fn insert(&mut self, _key: usize, value: usize) -> usize {
value
}
fn get(&self, _key: &usize) -> Option<usize> {
None
}
}
Expand All @@ -193,7 +201,7 @@ fn trait_functions_are_called_explicitly() {
}
impl MemoizationStore<(), ()> for Store {
fn insert(&mut self, _key: (), _value: ()) {}
fn get(&self, _key: &()) -> Option<&()> {
fn get(&self, _key: &()) -> Option<()> {
None
}
}
Expand Down

0 comments on commit c5e4543

Please sign in to comment.