gpt4 book ai didi

rust - 如何将标识符 (`proc_macro::Ident` ) 存储为常量以避免重复?

转载 作者:行者123 更新时间:2023-12-04 23:35:19 25 4
gpt4 key购买 nike

我正在编写一个程序宏,我需要多次发出一个很长的标识符(例如,可能是 because of hygiene )。我用 quote!创建 TokenStream s,但我不想一遍又一遍地重复这个长标识符!

例如,我想生成此代码:

let very_long_ident_is_very_long_indeed = 3;
println!("{}", very_long_ident_is_very_long_indeed);
println!("twice: {}", very_long_ident_is_very_long_indeed + very_long_ident_is_very_long_indeed);

我知道我可以创建一个 Ident并将其插入 quote! :
let my_ident = Ident::new("very_long_ident_is_very_long_indeed", Span::call_site());
quote! {
let #my_ident = 3;
println!("{}", #my_ident);
println!("twice: {}", #my_ident + #my_ident);
}

到目前为止一切顺利,但我需要在我的代码库中的许多函数中使用该标识符。我希望它是一个 const我可以在任何地方使用。但是,这失败了:
const FOO: Ident = Ident::new("very_long_ident_is_very_long_indeed", Span::call_site());

出现此错误:

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> src/lib.rs:5:70
|
5 | const FOO: Ident = Ident::new("very_long_ident_is_very_long_indeed", Span::call_site());
| ^^^^^^^^^^^^^^^^^

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> src/lib.rs:5:20
|
5 | const FOO: Ident = Ident::new("very_long_ident_is_very_long_indeed", Span::call_site());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我怀疑这些函数是否会被标记为 const任何时候很快。

我可以使字符串本身成为一个常量:
const IDENT: &str = "very_long_ident_is_very_long_indeed";

但是无论我想在哪里使用标识符,我都需要调用 Ident::new(IDENT, Span::call_site()) ,这会很烦人。我只想写 #IDENT在我的 quote!调用。我能以某种方式使它工作吗?

最佳答案

幸运的是,有办法!

插值通过 #quote!作品来自 the ToTokens trait .实现该特性的所有内容都可以插入。所以我们只需要创建一个可以构造成常量并实现 ToTokens 的类型。 .该特征使用来自 proc-macro2 的类型而不是标准 proc-macro一。

use proc_macro2::{Ident, Span, TokenStream};


struct IdentHelper(&'static str);

impl quote::ToTokens for IdentHelper {
fn to_tokens(&self, tokens: &mut TokenStream) {
Ident::new(self.0, Span::call_site()).to_tokens(tokens)
}
}

现在您可以定义您的标识符:
const IDENT: IdentHelper = IdentHelper("very_long_ident_is_very_long_indeed");

并直接在 quote!中使用:
quote! {
let #IDENT = 3;
}

( Full example )

关于rust - 如何将标识符 (`proc_macro::Ident` ) 存储为常量以避免重复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59619244/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com