jaemk / cached

Rust cache structures and easy function memoization
MIT License
1.57k stars 95 forks source link

lifetime `'static` required? #84

Closed realuser closed 3 years ago

realuser commented 3 years ago

I'm getting the following error:

 #[cached::proc_macro::cached(time = 240, result = true)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
72 | pub fn get_data(data1: &str, data2: &str) -> Result<Vec<MyStruct>, reqwest::Error> {
   |                                  ---- help: add explicit lifetime `'static` to the type of `data1`: `&'static str`
   |

Why is it suggesting a static lifetime? Adding a static lifetime propagates the static requirement up the call chain. Where I finally get error[E0759]: `data1` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement

How can I fix this?

jaemk commented 3 years ago

This is because the cache key is generated by making a tuple out of the function arguments, and the resulting cache key needs to be Clone + Hash. You can pass a convert block to the macro to tell it how to create the cache key from your arguments (ex from the readme, you can ignore the type and create blocks)

use std::thread::sleep;
use std::time::Duration;
use cached::proc_macro::cached;
use cached::SizedCache;

/// Use an explicit cache-type with a custom creation block and custom cache-key generating block
#[cached(
    type = "SizedCache<String, usize>",
    create = "{ SizedCache::with_size(100) }",
    convert = r#"{ format!("{}{}", a, b) }"#
)]
fn keyed(a: &str, b: &str) -> usize {
    let size = a.len() + b.len();
    sleep(Duration::new(size as u64, 0));
    size
}
realuser commented 3 years ago

By "you can ignore the type and create blocks" did you mean I don't need to include them? Or to ignore the ones from the example and include my own specific ones? When I leave them off I get:

error: custom attribute panicked     
  --> src\data.rs:72:1
   |
72 | / #[cached(
73 | |     time = 240,
74 | |     result = true,
75 | |     convert = r#"{ format!("{}-{}", a, b) }"#
76 | | )]
   | |__^
   |
   = help: message: convert requires key or type to be set

And if needed, do I need both type and create or will only type suffice?

jaemk commented 3 years ago

ah, right sorry - convert + key is enough, or convert + type. The macro just needs to know what to replace the cache type's key with instead of using the tuple of function arguments

#[cached(
    key = "String",
    convert = r#"{ format!("{}{}", a, b) }"#
)]
fn keyed(a: &str, b: &str) -> usize {
    let size = a.len() + b.len();
    sleep(Duration::new(size as u64, 0));
    size
}
realuser commented 3 years ago

That works thanks