问题标签 [rust-proc-macros]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
rust - 如何在类型上而不是在类型内部使用自定义命名空间派生宏属性?
我想创建一个使用新命名空间属性语法的自定义派生宏:example::attr
. 我已经能够让它与类型内的属性一起工作(例如,在结构字段或枚举变体上),但不适用于类型本身。
src/main.rs
过程宏本身什么也不做,除了声明它example::attr
是一个有效的属性。
复制衍生/src/lib.rs
编译产量:
切换到属性 ( ) 的非命名空间形式example_attr
可以正常工作。
我正在使用 Rust 1.32.0。项目布局为
货运.toml
repro-derive/Cargo.toml
rust - 如何从选项中获得 T什么时候用syn?
我syn
用来解析 Rust 代码。当我使用 读取命名字段的类型field.ty
时,我得到一个syn::Type
. 当我使用打印它时,quote!{#ty}.to_string()
我得到"Option<String>"
.
我怎样才能得到公正"String"
?我想使用#ty
inquote!
来打印"String"
而不是"Option<String>"
.
我想生成如下代码:
从...开始
我的尝试:
rust - 是否可以判断一个字段是某种类型还是在过程宏中实现某种方法?
我创建了一个实现特征的过程宏,但为了使其工作,我需要获取每个字段的原始字节。问题是如何获取字段的字节取决于字段的类型。
是否有某种方法可以测试一个函数是否存在于一个字段中并且它是否不尝试另一个函数?
例如这样的:
目前,我正在考虑创建另一个特征/成员函数,我只需要为所有原语创建它,并为更大的字段(例如结构)创建一个过程宏。例如:
对于字符串,它有一个as_bytes
成员函数,而i32
没有。这意味着当结构的成员字段不是字符串时,我需要额外的代码。我可能需要 amatch
而不是 a if
,但是if
对于这个例子来说就足够了。
rust - 如何让我的自定义派生宏接受特征泛型参数?
我正在尝试为我的特征实现自定义派生宏,它们确实有效!
但是我有一个小问题。我似乎找不到将通用参数包含到特征的方法。
具体来说,我想做这样的事情:#[derive(MyCustomDerive<'a, B, C>)]
相反,现在我正在对泛型进行硬编码,如下所示:
如您所见,我将'a、V和E固定在引用块中,而不是我想要实现的东西,它能够灵活地用我想要的泛型类型派生特征。
我想要的是类似于这样的东西:
#[derive(MyCustomDerive<'a, B, C>)]
产生与此等价的东西
这将允许我保留(当然如果有必要)V 和 E 用于其他事情,并且在我看来使代码更可控。感谢您的帮助!
更新 1:这就是我的派生函数的外观
rust - 什么是存储程序宏工件的合适位置,以便通过“cargo clean”清理它们?
我正在研究一个程序宏,它需要一个地方来在运行它的系统上存储状态。运行时应清理状态cargo clean
。
过去,我假设该target
目录是正确的位置。但是,我的假设可能不正确,因为:
- 我的文件和目录可能与 和 的文件和目录
rustc
冲突cargo
。 - 目标目录的位置可以从默认值更改。
为了避免这些问题,我一直在尝试确定一种正确定位位置的方法,但没有成功。我发现最接近的是OUT_DIR
Cargo 为构建脚本设置的环境变量,不幸的是,它没有为程序宏运行设置。
请注意,此问题与是否可以在 Rust 的过程宏中存储状态?. 该问题通常涵盖程序宏状态,而该问题是关于确定 crate 文件结构中的合适位置。
rust - 如何在过程宏中确定编译属性?
我正在研究一个过程宏,它做了很多工作,可以大大减慢编译速度。所做的工作不会影响函数的语义;也就是说,如果给定相同的参数集,则返回值不会根据是否应用宏而改变。
为了使 edit-comp-test 循环更快,我想根据与 crate 的编译方式相关的条件使宏成为无操作。我希望能够特别确定两个属性:
- 为什么要执行宏:构建/运行、文档、测试
- 是否为优化构建执行宏。
Cargo将优化级别暴露给构建脚本(通过环境变量OPT_LEVEL
和PROFILE
),但不暴露模式(构建、文档、..)。但是,这些信息似乎根本没有暴露给过程宏。
rust - 使用过程宏将具有命名数据的枚举变量转换为单独的结构
我正在编写一个过程宏来将枚举的变体转换为单独的结构并为该结构实现一些特征。
这适用于单元和未命名的变体,但具有命名数据的变体将导致它静默失败:)。
这是一个示例 proc_macro 定义:
当我在这段代码上运行它时:
我得到这个扩展代码(通过cargo expand
):
然而,预期的结果是:
rust - 如何处理 Rust 过程宏中的“Self”?
我试图在 Rust 中创建一个派生宏来创建实例,例如,它应该实现以下特征:
我使用syn
andquote
来解析和生成 AST,如下所示:
由于编译器在编译时不知道是什么Self
,上述会导致错误:
我的问题是:
- 是否可以在中使用 Self
proc_macro_derive
? - 如何?
顺便说一句,我正在尝试改用 ident,稍后会在此处发布进度。
更新:
- 事实证明,错误是由 trait 声明引起的,而不是
proc_macro_derive
. 要修复,Sized
应添加到特征名称。
rust - 如何为 syn::parse 找到正确的返回类型?
我有一个TokenStream
来自 Rust 函数的定义。我想用syn::parse
(和.unrwap()
)解析它。但是,我不知道返回类型应该是什么:
类型应该ast
是什么?
compilation - proc 宏可以确定调用编译的目标吗?
过程宏存在于它们自己的 crate 中,这些 crate 是为开发机器编译的(以便在编译使用它们的 crate 时可以执行它们)。过程宏 crate 中的任何条件编译指令将相应地基于它们的编译环境,而不是调用 crate 的编译环境。
当然,这样的宏可以扩展到包含条件编译指令的标记,然后将在调用 crate 的编译的上下文中对其进行评估——然而,这并不总是可行或可取的。
如果希望扩展令牌本身成为调用板条箱编译环境的某个功能,则需要宏在其运行时确定该环境(这当然是调用板条箱的编译时间)。std::env
显然是该模块的完美用例。
但是, rustc 没有设置任何环境变量。而 Cargo 集只有有限的几个。特别是,一些关键信息(如目标架构/操作系统等)根本不存在。
我很欣赏调用板条箱中的构建脚本可以为宏设置环境变量然后读取,但这给调用板条箱的作者带来了不令人满意的负担。
proc 宏作者有什么方法可以获得有关调用 crate 的编译环境的运行时信息(我最感兴趣的目标架构和操作系统)?