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

pur*_*tii 9 macros rust

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

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

impl Boundable<u8> for u8 {
    fn max_value() -> u8 { u8::MAX }
}
Run Code Online (Sandbox Code Playgroud)

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

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

impl_boundable!(i8);
Run Code Online (Sandbox Code Playgroud)

尤其,<$a>::MAX。没有它,编译器会给我错误missing angle brackets in associated item path。我很困惑为什么宏代码需要与非宏代码不同。

操场

Jef*_*ett 15

语法是_path_::item, 不是_type_::item<T>有效路径包括类型的标识符和T

在 中u8::MAXu8允许使用 ,因为它是标识符,而不是因为它是类型。[u8; 1]::item不允许。

如果您的宏采用$a:ident, 而不是$a:ty,它将按原样使用也是标识符(如 )的类型u8。但是,接受类型时$a:ty,从类型创建路径的通用方法是使用尖括号<$a>

这也是您的宏直接接受路径的一个选项:$a:path。但是您可能会遇到错误#48067:解析器无法弄清楚如何从较小的路径段组成路径。的票证中有针对这种情况的解决方法use $a as base; base::MAX