元编程技术大概分为:
- 简单文本替换
- 类型模板
- 反射
- 语法扩展
- 代码自动生成
Rust语言通过反射和AST语法扩展两种手段来支持元编程。
反射
反射机制一般是指程序自我访问、检测和修改其自身状态或行为的能力。Rust标准库提供了std::any::Any来支持运行时反射。可以先看下代码结构:

Any定义:
| |
- 该 trait 加上了
'static生命周期限定,意味着该 trait 不能被非静态生命周期的类型实现。impl<T: 'static + ?Sized> Any for T表示 Rust 中满足'static生命周期的类型均实现了它。 type_id方法返回TypeId类型,代表 Rust 中某个类型的全局唯一标识,它是在编译时生成的。
| |
- 每个
TypeId都是一个“黑盒”,不能检查其内部内容,但是允许复制、比较、打印等操作。TypeId当前仅适用于归因于'static的类型,但是可以在 future 中消除此限制。
通过 is 函数判断类型
| |
- 因为
Any是一个 trait ,所以这里的is方法的&self必然是一个 trait 对象。 TypeId::of函数用来获取类型T的全局唯一标识符t。
| |
输出结果:
| |
TypeId是一个结构体,其字段t存储了一串数字,这就是全局唯一类型标识符,实际上是 u64 类型。代表唯一标识符的这串数字,在不同的编译环境中,产生的结果是不同的。所以在实际开发中,最好不要将TypeId暴露到外部接口中被当作依赖。
转换到具体类型
Any 提供了 downcast_ref 和 downcast_mut 两个成对的泛型方法,用于将泛型T向下转换为具体的类型,返回值分别是 Option<&T> 和 Option<&mut T> 类型。
| |
非静态生命周期类型
| |
- 带引用字段的结构体
Unstatic<'a>,其生命周期不是静态的,编译会报错。
修改:
| |
Any 的应用
Remark
在2018 Edition 中,以下语句不会报错:
| |
但是在2021 Edition中,必须加上 dyn 。
| |
宏系统
Rust编译过程:

声明宏
宏展开命令: cargo rustc – -Z unstable-options –pretty=expanded
示例1:
| |
支持token类型:
| |
hashmap 1.0
| |
hashmap 2.0:可以匹配结尾有逗号
| |
hashmap 3.0
| |
hashmap 4.0 : 节省存储空间
| |
hashmap 5.0:将声明宏放在一起
| |
示例:
| |
- 注意这里会报错,宏里面的
a变量是局部的。
过程宏
过程宏三件套:
介绍:
- Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree of Rust source code. 将 token 流转换成语法树。
- quote: This crate provides the
quote!macro for turning Rust syntax tree data structures into tokens of source code. 将语法树转换成 token 源码。 - proc-macro2 比 proc-macro 更加的灵活。TokenStream API接口。
| |
参考资料
- 《Rust编程之道》