Rustでマクロの引数の個数を数えてみようと思って以下のように書きました。
誤り
macro_rules! count_args {
    ($($elems: ident),*) => {
        count_args!(0; $($elems),*)
    };
    ($res: expr;) => {
        $res
    };
    ($res: expr; $elem: ident, $($rest: ident),*) => {
        count_args!($res + 1; $($rest),*)
    };
}
fn main() {
    println!("{}", count_args!(x, y, z));
}
error: no rules expected the token `z`
  --> src\main.rs:16:38
   |
16 |     println!("{}", count_args!(x, y, z));
   |
zで当てはまるルールがないと言われます。
理由
($res: expr; $elem: ident, $($rest: ident),*) => {
 このルールでx, y, zがxでyでzと順番に消費されて$restが0個になると思い込んでました。しかし実際には、$elem: identの次にあるコンマまできっちりマッチングできるかどうか確かめられます。つまり、$elem: ident,できっちり見られるのでx,とy,はマッチしますが、最後のzは$elem: ident,にマッチせず他に当てはまるルールがないのでエラーとなります。
 ちなみに、count_args!の呼び出しでzの次にコンマを入れてcount_args!(x, y, z,)にすると、この呼び出しの最後のコンマでunexpected end of macro invocationと言われてエラーになります。
正答例
以下のように($res: expr;)をコンマのない終端のトークンを受け入れられるように($res: expr; $elem: ident)と修正するとうまくいきました。もちろん$resも$res + 1にしています。
macro_rules! count_args {
    ($($elems: ident),*) => {
        count_args!(0; $($elems),*)
    };
    ($res: expr; $elem: ident) => {
        $res + 1
    };
    ($res: expr; $elem: ident, $($rest: ident),*) => {
        count_args!($res + 1; $($rest),*)
    };
}
fn main() {
    println!("{}", count_args!(x, y, z));
}
最後に
ルールにセミコロン使ってる時点で気づくべきだった。
