Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with creating an impl-block using a macro in Rust

I want to create a macro generating a given formatter (Display, Debug,...) for a struct containing a single generic type.

macro_rules! create_formatter {
    ($type_name:ident<$gen_param:ident>, $trait:path) => {
        impl<$gen_param: $trait> $trait for $type_name<$gen_param> {
            fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                // isn't yet implemented 
            }
        }
    };
}

When I call the macro later in the code (create_formatter!(MyStruct<T>, std::fmt::Display);), the compiler gives the following feedback:

error: expected one of `,`, `=`, `>`, or `?`, found `std::fmt::Display`
--> test.rs:6:26
 |
6|         impl<$gen_param: $trait> $trait for $type_name<$gen_param> {
 |                          ^^^^^^^^

What am I doing wrong?

like image 785
Benedikt Schumacher Avatar asked Jan 07 '17 16:01

Benedikt Schumacher


People also ask

Why use macros instead of functions rust?

Rust has excellent support for macros. Macros enable you to write code that writes other code, which is known as metaprogramming. Macros provide functionality similar to functions but without the runtime cost. There is some compile-time cost, however, since macros are expanded during compile time.

What is an implementation block in Rust?

impl: An impl is an implementation block that has the keyword “impl” followed by the same name as that of the struct. It is used to comprise methods, and functions. A struct is allowed to have multiple impl blocks.


1 Answers

This does seem mysterious! It seems the problem is down to the way that the output of a macro is parsed: since it's been partly pre-parsed as a path during the macro processing, it no longer matches the parse rule for a trait bound. There was a bug raised a few weeks ago about this.

However, there is good news - it's been fixed! The example actually works in the beta or nightly compilers (playground), though note I had to rename $trait to $t as trait is a keyword.

like image 104
Chris Emerson Avatar answered Oct 26 '22 00:10

Chris Emerson