# Confusing macro error

Considering the following code:

``````macro_rules! inner {
(\$(<\$(\$ty:path : \$bound:path),*> \$struct:path),*) => {
\$(
impl<\$(\$ty : \$bound),*> Blanket for \$struct {}
)*
}
}
inner! {
<T1: Bound, T2: Bound> Pair<T1, T2>
}

// how is it expected to work:
trait Bound {}
trait Blanket {}
struct Pair<T1, T2>(std::marker::PhantomData<(T1, T2)>)
// then, the macro will do
// impl<T1: Bound, T2: Bound> Blanket for Patr<T1, T2>
``````

Errors:

``````error: expected one of `!`, `+`, `>`, or `as`, found `:`
--> src/lib.rs:4:24
|
4  |               impl<\$(\$ty : \$bound),*> Inner for \$struct {}
|                          ^ expected one of `!`, `+`, `>`, or `as` here
...
8  | / inner! {
9  | |     <T1: Bound, T2: Bound> Pair<T1, T2>
10 | | }
| |_- in this macro invocation
``````

The error simply doesn't make sense for me. What this could mean?

The grammar of Rust is quite strict, and things that look "alike" (`ident`, `ty` and `path`) are really different. Unless you use `\$(\$tt:tt)*` to capture a raw stream of tokens, you will force these Tokens to be preparsed as one of these categories. In your case you have made the stream of tokens "`T1`" become a `path`.

And the Rust reference states that (type) generics must be of the form:

``````\$(
\$T:ident \$(
: \$(
\$( for<...> )?
\$trait:path
)+* \$(+)?
)?
),* \$(,)
``````

So by changing your `inner!` macro to:

``````macro_rules! inner {(
\$(
<\$(\$ty:ident : \$bound:path),* \$(,)?> \$struct:path
),* \$(,)?
) => (
\$(
impl<\$(\$ty : \$bound),*> Blanket for \$struct {}
)*
)}
``````
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
{"extraction_info": {"found_math": false, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 0, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.9624764323234558, "perplexity": 29316.703164107068}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2020-16/segments/1585370495413.19/warc/CC-MAIN-20200329171027-20200329201027-00483.warc.gz"}