How to get the name for struct as string within derived function that is generated for wrapping struct that is generic?

The idea is to implement a derive macro for enum that wraps generic and prints wrapped struct name.

struct MyStruct {}

// #[derive(PrintWrapped)]
enum GenericStruct<X> {
    Variant1(X),
}

// I need so that derived code is something like this
impl<X> GenericStruct<X> {
    pub fn print_wrapped_name(&self) {
        // Somehow print here "MyStruct"
        print!("");
    }
}

fn main(){
    let x = GenericStruct::Variant1(MyStruct {});
    x.print_wrapped_name();
}

The challenge is that in proc-macro crate that implements PrintWrapped code generation, i can access only variants and fields for enum GenericStruct, so at that point in code i have only X available, there is no way to get MyStruct. There is a macro in quote crate format_ident, which almost does what i need, it can convert X to string, but i need to convert MyStruct to string somehow.

I could require MyStruct to implement specific trait, i.e. StructNameAsString and then use specific method in derived code, but that would force to write extra code for MyStruct (not convenient for library users) and would incur extra cost on performance for extra function call where the string in reality is const (maybe this is negligible, but... ).

Theoretically at some point compiler is filling in MyStruct in generic definition. Practically i do not know a way how could i get that info.

How would you solve this? If requiring specific trait bound is the only option in this situation, is there already an existing trait available (in a way it is similar to Display/Debug)?

Yes, it is.

Why couldn't you write a derive macro for it?

No, why? Isn't an associated const or even a const fn sufficient?

1 Like

Thanks for the fast response.

Yes, i could write a derive macro. Was just looking for some alternatives to pick the best solution from and maybe learn something new along the way.

you can use any::type_name(). for example:

impl<X> GenericStruct<X> {
    pub fn print_wrapped_name(&self) {
        print!("{}", any::type_name::<X>());
    }
}

just keep in mind, how well it works depends on your intended usage. to quote the documentation:

Note

This is intended for diagnostic use. The exact contents and format of the string returned are not specified, other than being a best-effort description of the type. For example, amongst the strings that type_name::<Option<String>>() might return are "Option<String>" and "std::option::Option<std::string::String>".

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.