Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cached proc macro doesn't keep where clause #217

Open
gerald-pinder-omnicell opened this issue Jul 29, 2024 · 2 comments
Open

Cached proc macro doesn't keep where clause #217

gerald-pinder-omnicell opened this issue Jul 29, 2024 · 2 comments

Comments

@gerald-pinder-omnicell
Copy link

gerald-pinder-omnicell commented Jul 29, 2024

Ran into an issue on a function that has a where clause on it. For some reason the where clause doesn't get copied over to the no_cache function but the primed_cache function and the replaced function has the where clause. I'm on version v0.53.1 using the features tokio and async.

Here's the function:

#[cached(
    result = true,
    sync_writes = true,
    key = "String",
    convert = r#"{ format!("{}:{}", path.as_ref(), path_key.as_ref()) }"#
)]
async fn get_secret_internal<T, U>(
    client: &VaultClient,
    path: T,
    path_key: U,
) -> Result<Zeroizing<String>>
where
    T: AsRef<str> + Send + Sync,
    U: AsRef<str> + Send + Sync,
{
    let path = path.as_ref();
    let path_key = path_key.as_ref();

    // ...
}

Here's the error:

error[E0599]: no method named `as_ref` found for type parameter `T` in the current scope
  --> src/vault.rs:84:21
   |
75 | async fn get_secret_internal<T, U>(
   |                              - method `as_ref` not found for this type parameter
...
84 |     let path = path.as_ref();
   |                     ^^^^^^ method not found in `T`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `as_ref`, perhaps you need to restrict type parameter `T` with it:
   |
75 | async fn get_secret_internal<T: AsRef, U>(
   |                               +++++++

error[E0599]: no method named `as_ref` found for type parameter `U` in the current scope
  --> src/vault.rs:85:29
   |
75 | async fn get_secret_internal<T, U>(
   |                                 - method `as_ref` not found for this type parameter
...
85 |     let path_key = path_key.as_ref();
   |                             ^^^^^^ method not found in `U`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `as_ref`, perhaps you need to restrict type parameter `U` with it:
   |
75 | async fn get_secret_internal<T, U: AsRef>(
   |                                  +++++++

For more information about this error, try `rustc --explain E0599`.

Here's the expanded rust using cargo expand:

    ///Cached static for the [`get_secret_internal`] function.
    static GET_SECRET_INTERNAL: ::cached::once_cell::sync::Lazy<
        ::cached::async_sync::Mutex<cached::UnboundCache<String, Zeroizing<String>>>,
    > = ::cached::once_cell::sync::Lazy::new(|| ::cached::async_sync::Mutex::new(
        cached::UnboundCache::new(),
    ));
    ///Origin of the cached function [`get_secret_internal`].
    async fn get_secret_internal_no_cache<T, U>(
        client: &VaultClient,
        path: T,
        path_key: U,
    ) -> Result<Zeroizing<String>> {
        let path = path.as_ref();
        let path_key = path_key.as_ref();
        
       // ...
    }
    ///This is a cached function that uses the [`GET_SECRET_INTERNAL`] cached static.
    async fn get_secret_internal<T, U>(
        client: &VaultClient,
        path: T,
        path_key: U,
    ) -> Result<Zeroizing<String>>
    where
        T: AsRef<str> + Send + Sync,
        U: AsRef<str> + Send + Sync,
    {
        use cached::Cached;
        use cached::CloneCached;
        let key = {
            {
                let res = ::alloc::fmt::format(
                    format_args!("{0}:{1}", path.as_ref(), path_key.as_ref()),
                );
                res
            }
        };
        let mut cache = GET_SECRET_INTERNAL.lock().await;
        if let Some(result) = cache.cache_get(&key) {
            return Ok(result.to_owned());
        }
        let result = get_secret_internal_no_cache(client, path, path_key).await;
        if let Ok(result) = &result {
            cache.cache_set(key, result.clone());
        }
        result
    }
    ///Primes the cached function [`get_secret_internal`].
    #[allow(dead_code)]
    ///This is a cached function that uses the [`GET_SECRET_INTERNAL`] cached static.
    async fn get_secret_internal_prime_cache<T, U>(
        client: &VaultClient,
        path: T,
        path_key: U,
    ) -> Result<Zeroizing<String>>
    where
        T: AsRef<str> + Send + Sync,
        U: AsRef<str> + Send + Sync,
    {
        use cached::Cached;
        let key = {
            {
                let res = ::alloc::fmt::format(
                    format_args!("{0}:{1}", path.as_ref(), path_key.as_ref()),
                );
                res
            }
        };
        let mut cache = GET_SECRET_INTERNAL.lock().await;
        let result = get_secret_internal_no_cache(client, path, path_key).await;
        if let Ok(result) = &result {
            cache.cache_set(key, result.clone());
        }
        result
    }
@gerald-pinder-omnicell
Copy link
Author

I can currently work around this limitation by putting trait bounds in the function generic type section (<T, U>).

@omid
Copy link
Contributor

omid commented Oct 17, 2024

@gerald-pinder-omnicell I forked this project and where works there:
https://crates.io/crates/kash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants