"Visitor" for types?

Assume I have:

trait X{
    fn x();
}

I now have implemented X for a number of structs, e.g. A, B, and C.
Ideally, I would love to be able to derive a method of the form

fn all_x()
{
    A::x();
    B::x();
    C::x();
}

Is that possible in some way? I have found any::TypeID, but I did not find a way of resolving TypeIDs back to types.

Edit: Eurgh, I managed to accidentally submit before my post was complete.
Edit 2: Formatting.

No. Rust doesn’t have runtime type information, and the type information it does have at compile time can’t be accessed in any way from your code.

More edits: OK, OK… I mean, you can introspect types, but that requires a lint, which is a compiler plugin, which means the interface is effectively unsupported and changes on a regular basis. Also, lints can’t generate code, so you’d have to pull some TeX shenanigans to use that information.

What you could do is write a custom derive that you add to each type that implements X, and write those out to a file, which you then re-import on the next compile to generate all_x… but again, yuck.

Or, if you’re super desperate, you could use syn in a build script to parse your source code, find all the implementations of X (keeping in mind that you don’t have access to name or type resolution), and generate all_x that way.

But, honestly, I’d just write all_x by hand.

Hmm. I think this should be possible with a macro, though, right?

No. Macros are purely syntactic. As far as they’re concerned, types don’t exist.

Hmm. It would be fine to repeat the list of types I want to be visited in this way, though.

I actually need a number of different methods that’ll visit all the relevant types in this way, and what I want to achieve is not to have to repeat the same list over and over again.

Well, that depends on what exactly you’re trying to do. The most general approach would be something like:

macro_rules! x_impls {
    ($cb:ident!{ $($cb_args:tt)* }) => {
        $cb!{
            $($cb_args)*
            A, B, C
        }
    };
}

macro_rules! invoke_method {
    ($method:ident; $($ty_name:ident),*) => {
        fn all_x() {
            $(
                $ty_name::$method();
            )*
        }
    };
}

x_impls! { invoke_method! { x; } }

That way, you can pass the list to any number of macros.

Thank you very much for your quick and competent help! I like this idea. If I may, I’ll use your code as building blocks for a bigger macro that’ll generate all the necessary methods.