为什么在实现基于类型的宏时,<$a> 中需要尖括号?

Why do I need angle brackets in <$a> when implementing macro based on type?

我可以实现一个采用如下类型的宏:

trait Boundable<A> {
    fn max_value() -> A;
}

impl Boundable<u8> for u8 {
    fn max_value() -> u8 { u8::MAX }
}

当我将 impl 转换为宏时,为什么我需要用尖括号将类型本身括起来,如下所示?

macro_rules! impl_boundable {
    ($a:ty) => {
        impl Boundable<$a> for $a {
            fn max_value() -> $a { <$a>::MAX }
        }
    };
}

impl_boundable!(i8);

特别是 <$a>::MAX。没有它,编译器会给我错误 missing angle brackets in associated item path。很疑惑为什么宏代码需要和非宏代码不一样

playground

语法是_path_::item,不是_type_::item。有效路径包括类型 T.

的标识符和 <T>

u8::MAX中,u8是允许的,因为它是一个标识符,而不是因为它是一个类型。 [u8; 1]::item 不允许。

如果您的宏采用 $a:ident,而不是 $a:ty,它会像 u8 这样的标识符类型一样工作。但是,接受类型 $a:ty,从类型创建路径的通用方法是使用尖括号 <$a>.

您的宏也可以选择直接接受路径:$a:path。但是你很可能会遇到 bug #48067:解析器无法弄清楚如何从较小的路径段组成路径。在 use $a as base; base::MAX.

的票证中有针对这种情况的解决方法