Impl Trait for any struct with a specific field

Is it possible to implement a Trait generically for any struct that contains a specified field name?

Something like:

impl<T> MyTrait for T
    where T.fieldname

No, it's not possible.

In general, structural typing is against Rust philosophy. Can you elaborate why you want to do this?

2 Likes

What do you mean by "structural typing?"

I have bunch of structs that are similar and all need some common traits, but for which certain subsets will need additional traits.

You can often fall back on macros. It's not uncommon to see impl_foo! macros:

macro_rules! impl_foo {
    ($type:ty) => {
        impl Foo for $type {
            fn get_foo(&self) -> u8 { self.foo }
        }
    }
}

I've used this in the past when I was using the bitflags crate, which generates structs that all have a fn bits(&self) -> u8 method, but I wanted to write code that was generic over different bitflag types.

3 Likes

In the sense of structural vs. nominal type systems, Rust follows the latter. Just having particular methods or fields is never enough to implement a trait. Even blanket declarations like impl<T> Foo for T only work if you can express type constraints that are sufficient to implement Foo abstractly.

Macros are ok if that set of structs is a fixed list. Another option is to compose those structs around a shared inner struct, then define accessor methods as needed to reach it, or perhaps a generic AsRef<Inner> so you can write foo.as_ref().do_common_thing().

4 Likes
macro_rules! impl_foo {
    ($type:ty) => {
        impl Foo for $type {
            fn get_foo(&self) -> &str { self.foo }
        }
    }
}

impl_foo!(My_Struct); //=> "missing lifetime specifier: expected lifetime parameter"

impl_foo!(My_Struct<'a>); //=> "use of undeclared lifetime name `'a`: undeclared lifetime"

How would I circumvent this issue, or is it not possible?

1 Like

You’d pass the lifetime param as a separate token: example

2 Likes

ah, brilliant, cheers.

1 Like