hobofan / ambassador

Delegation of trait implementations via procedural macros
Apache License 2.0
251 stars 13 forks source link

Delegating a trait with type parameters for a specific value of the parameters #56

Closed vigna closed 3 months ago

vigna commented 3 months ago

I have a trait with a const parameter. I need to delegate the trait for a specific value of the parameter, and I have made a few tentatives, but I coulnd't find how. There are no examples about this case in documentation, so I was wondering if there's any better way.

Note that this is different from deleting a trait with a parameter: I have a trait S<const P: usize> and I need to delegate S<10>, say.

Analogously, I'd like to delegate AsRef<[usize]> and I tried several different solutions, but none works.

dewert99 commented 3 months ago

Sorry, this seems to be an issue with const generics. I'll try to fix this in the next update.

vigna commented 3 months ago

Ok—but what about delegating AsRef<[usize]>?

dewert99 commented 3 months ago

Did you try delegatable_trait_remote? It is needed since AsRef is an existing trait. ambassador supports doing:

use ambassador::{delegatable_trait_remote, Delegate};

#[delegatable_trait_remote]
pub trait AsRef<T: ?Sized> {
    fn as_ref(&self) -> &T;
}

#[derive(Delegate)]
#[delegate(AsRef<[usize]>)]
struct MyVec(Vec<usize>);

fn main() {
    let v = MyVec(vec![1, 2, 3]);
    println!("{:?}", v.as_ref()) // prints: [1, 2, 3]
}
vigna commented 3 months ago

Yes, the problem is once again cross-module behavior. If I put

#[delegatable_trait_remote]
pub trait AsRef<T: ?Sized> {
    fn as_ref(&self) -> &T;
}

in lib.rs,

#[delegate(crate::AsRef<[usize]>, target = "bits")]

gives

error: cannot find macro `ambassador_impl_AsRef` in this scope
   --> src/rank_sel/rank9.rs:77:19
    |
77  | #[delegate(crate::AsRef<[usize]>, target = "bits")]
    |                   ^^^^^
    |
   ::: src/traits/rank_sel.rs:185:1
    |
185 | #[delegatable_trait]
    | -------------------- similarly named macro `ambassador_impl_Select` defined here
    |
    = help: have you added the `#[macro_use]` on the module/import?
help: a macro with a similar name exists
    |
77  | #[delegate(crate::ambassador_impl_Select<[usize]>, target = "bits")]
    |                   ~~~~~~~~~~~~~~~~~~~~~~
help: consider importing this macro through its public re-export
    |
9   + use crate::ambassador_impl_AsRef;
    |

error[E0405]: cannot find trait `AsRef` in the crate root
  --> src/rank_sel/rank9.rs:77:19
   |
77 | #[delegate(crate::AsRef<[usize]>, target = "bits")]
   |                   ^^^^^ not found in the crate root
   |
help: consider importing this trait
   |
9  + use std::convert::AsRef;
   |
help: if you import `AsRef`, refer to it directly
   |
77 - #[delegate(crate::AsRef<[usize]>, target = "bits")]
77 + #[delegate(AsRef<[usize]>, target = "bits")]
   |

When I try to pub use ambassador_impl_AsRef;, however, I get

error[E0255]: the name `ambassador_impl_AsRef` is defined multiple times
  --> src/lib.rs:78:9
   |
74 | #[delegatable_trait_remote]
   | --------------------------- previous definition of the macro `ambassador_impl_AsRef` here
...
78 | pub use ambassador_impl_AsRef;
   |         ^^^^^^^^^^^^^^^^^^^^^ `ambassador_impl_AsRef` reimported here
   |
   = note: `ambassador_impl_AsRef` must be defined only once in the macro namespace of this module

I tried to delegate also to AsRef and to std::convert::AsRef, but I always get errors.

vigna commented 3 months ago

Actually, there's no such ambassador_impl_AsRef macro in cargo expand, but I can find the others.

dewert99 commented 3 months ago

Sorry, I think issue be comes from using delegatable_trait_remote (same issue for delegatable_trait) in the crate root (lib.rs). Fixing this will be a breaking change so I will try to fix the const generics issue first and then this.

vigna commented 3 months ago

Ok. It's not a blocker for us as we are just replacing our own handmade delegation macros, but ambassador is a much better solution.

vigna commented 3 months ago

Everything is now working as expected. Thanks!