Crates.io | traitify-core |
lib.rs | traitify-core |
version | 0.1.0 |
source | src |
created_at | 2023-06-06 20:56:38.726573 |
updated_at | 2023-06-06 20:56:38.726573 |
description | A macro to turn an impl block into a trait. This is the logic behind the traitify crate. |
homepage | https://github.com/diondokter/traitify |
repository | https://github.com/diondokter/traitify |
max_upload_size | |
id | 884208 |
size | 12,714 |
No. Probably not.
Well, sometimes you have a type with generics and need to pass it to a function that cannot have generics. It would be awesome if Rust had syntax to the likes of this:
struct Foo<BAR, const FIZZ: usize>;
fn buzz(foo: &Foo<dyn, dyn>) {}
See what I did there? This imaginary syntax of dyn
in the place of a generic type would make this into a trait object on the fly! Cool right?
Sadly this syntax isn't real and there really isn't anything like it.
There are basically two thing I can come up with.
If you know all the different variants of your generics, you could create an enum and reimplement all Foo
functions on that enum.
If you don't, then you could create a trait with all the functions of Foo
and implement that trait for Foo
. But writing a trait that is only implemented by one type feels wrong. It feels like writing a C header file and I'm done with writing headers.
That's where this crate comes in!
This crate only contains a macro you can apply to an impl
block.
You tell it what the name of the trait needs to be and which generic types it should ignore.
use traitify::traitify;
struct Foo<BAR, const FIZZ: usize> {
data: [BAR; FIZZ],
};
#[traitify(FooDynFizz, dyn = [FIZZ])]
#[traitify(FooDynBAR, dyn = [BAR])]
#[traitify(FooDynAll, dyn = [FIZZ, BAR])]
impl<BAR, const FIZZ: usize> Foo<BAR, FIZZ> {
pub fn print_greeting(&self) {
println!("Hallo vriendjes en vriendinnetjes!");
}
}
#[test]
fn compiles() {
let foo = Foo::<u8, 4> { data: [0; 4] };
let dyn_foo: &dyn FooDynAll = &foo;
dyn_foo.print_greeting();
}
Now, I tried my best to make this macro handle as much syntax as possible. But if you find something that doesn't work that should, then please file an issue or PR!
Here's a (possibly incomplete) list of rules of which functions end up in the generated trait:
Self: Sized
bound for object safety. Not terribly useful for trait objects, but it was easy to add.You can't erase a lifetime. I think it should be possible, but I simply haven't done it yet.