给定一个字符串 ( str),如何TokenStream在 Rust 中将其转换为 a ?
我试过使用quote!宏。
let str = "4";
let tokens = quote! { let num = #str; }; // #str is a str not i32
Run Code Online (Sandbox Code Playgroud)
这里的目标是为一些未知的代码字符串生成令牌。
let thing = "4";
let tokens = quote! { let thing = #thing }; // i32
Run Code Online (Sandbox Code Playgroud)
或者
let thing = ""4"";
let tokens = quote! { let thing = #thing }; // str
Run Code Online (Sandbox Code Playgroud) 我有一个TokenStream来自 Rust 函数的定义。我想用syn::parse(和.unrwap())解析它。但是,我不知道返回类型应该是什么:
let ast: ??? = syn::parse(token_stream_from_function_definition).unwrap();
Run Code Online (Sandbox Code Playgroud)
应该是什么类型ast?
我正在尝试构建一个简单的属性,它将在函数的开头注入一个 let 绑定,因此结果将是:
#[foo]
fn bar(){
// start injected code
let x = 0;
// end injected code
...
}
Run Code Online (Sandbox Code Playgroud)
我已经做到了:
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, ItemFn, Item, Stmt};
#[proc_macro_attribute]
pub fn hello(attr: TokenStream, stream: TokenStream) -> TokenStream {
let input = parse_macro_input!(stream as ItemFn);
let block = input.block;
let res = quote! {let x = 1;};
// doesn't work, can't convert TokenStream into Stmt
block.stmts.insert(0, res.into());
TokenStream::from(input.into_token_stream())
}
Run Code Online (Sandbox Code Playgroud)
但是,我在处理这些物品时遇到了麻烦。例如,blockis 类型,现在一个语句由 ( , , )Vec<Stmt> …
我将这两个问题合二为一,因为它们可能是相关的。几天前,我开始在 main 函数之前的 [#actix_rt::main] 行中出现此错误:
proc macro `main` not expanded: cannot find proc-macro server in sysroot `C:\Users\zerok\.rustup\toolchains\stable-x86_64-pc-windows-gnu`
Run Code Online (Sandbox Code Playgroud)
与此同时,在 VSCode 中,我的 rust-analyzer 扩展开始失败。我卸载了它,重新启动 VSCode,然后重新安装。它不断地给出同样的错误:
Failed to spawn one or more proc-macro servers.
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?
我syn用来解析Rust代码。当我使用读取命名字段的类型时field.ty,得到一个syn::Type。当我使用打印时,quote!{#ty}.to_string()我得到了"Option<String>"。
我怎样才能得到"String"?我想用#ty在quote!打印"String"代替"Option<String>"。
我想生成如下代码:
impl Foo {
pub set_bar(&mut self, v: String) {
self.bar = Some(v);
}
}
Run Code Online (Sandbox Code Playgroud)
从...开始
struct Foo {
bar: Option<String>
}
Run Code Online (Sandbox Code Playgroud)
我的尝试:
let ast: DeriveInput = parse_macro_input!(input as DeriveInput);
let data: Data = ast.data;
match data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref fields) => {
fields.named.iter().for_each(|field| {
let name = &field.ident.clone().unwrap();
let ty = &field.ty; …Run Code Online (Sandbox Code Playgroud) 我收到此错误:
该特征
quote::to_tokens::ToTokens未实现proc_macro::Ident
当我尝试运行此代码时:
#[proc_macro_hack]
pub fn between(input: TokenStream) -> TokenStream {
let idents = input
.into_iter()
.map(|i| match i {
TokenTree::Ident(b) => {
b
},
_ => panic!()
})
.collect::<Vec<_>>();
let new_token_stream = quote! {
(#(#idents),*)
};
new_token_stream.into()
}
Run Code Online (Sandbox Code Playgroud)
这就是我想使用它的方式:
fn main() {
let a = 1;
let b = 2;
// Expand to (a, b);
between!(a, b);
}
Run Code Online (Sandbox Code Playgroud)
我还有一个包含上述代码的小项目: https: //bitbucket.org/JoshSinne/pm/src/master/。为什么我无法转换Ident内部令牌?我尝试使用parse,into但这对我来说没有成功。谢谢!
我正在尝试在我正在使用的库中调试复杂的程序宏。
由于我不能使用带有宏的调试器,并且各种宏扩展工具在这里被证明是无用的,我正在寻找替代方案。
程序宏是否可以像经过适当调试的函数一样运行?我想象将结果存储proc_macro::TokenStream在一个变量中。
我正在编写我的第一个 proc 宏,尽管尝试通读此错误、structopt 和derive_more 的源代码,但我似乎无法准确找到我正在寻找的内容。我想改变这个:
#[derive(Attach)]
#[attach(foo(SomeType, OtherType))]
#[attach(bar(OtherType))]
struct Plugin {}
Run Code Online (Sandbox Code Playgroud)
进入这个:
impl Attach for Plugin {
fn attach(self, srv: &mut Server) {
let this = Arc::new(self);
srv.foo_order(this.clone(), &[TypeId::of::<SomeType>(), TypeId::of::<OtherType>()]);
srv.bar_order(this, &[TypeId::of::<OtherType>()]);
}
}
Run Code Online (Sandbox Code Playgroud)
我已经开始编写一个 proc 宏,但在尝试解析属性时遇到了麻烦:
extern crate proc_macro;
use proc_macro::{Span, TokenStream};
use quote::quote;
use std::any::TypeId;
use syn::{
parse::ParseStream, parse_macro_input, Attribute, AttributeArgs, DeriveInput, Ident, Result,
};
#[proc_macro_derive(Attach, attributes(attach))]
pub fn register_macro(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
impl_register(input)
}
fn impl_register(input: DeriveInput) -> TokenStream …Run Code Online (Sandbox Code Playgroud) 我已经实现了以下 proc_macro ,它需要
builtin_method!(hello_world(a, b, c) {
println!("{} {} {}", a, b, c);
}
Run Code Online (Sandbox Code Playgroud)
并且应该生成
pub fn hello_world(args: Vec<String>) {
let a = args.get(0).unwrap();
let b = args.get(1).unwrap();
let c = args.get(2).unwrap();
println!("{} {} {}", a, b, c);
}
Run Code Online (Sandbox Code Playgroud)
这是我当前的代码。
builtin_method!(hello_world(a, b, c) {
println!("{} {} {}", a, b, c);
}
Run Code Online (Sandbox Code Playgroud)
在变量插值内部,我需要某种枚举变量进行计数。根据文档,没有这样的方法。
我怎样才能更好地实现这一点而不是向上计数_i?
pub fn hello_world(args: Vec<String>) {
let a = args.get(0).unwrap();
let b = args.get(1).unwrap();
let c = args.get(2).unwrap();
println!("{} {} {}", a, b, c); …Run Code Online (Sandbox Code Playgroud) 我正在摆弄 Rust 的过程宏,我想制作一个自定义的有趣属性,将 TokenStream 中的所有字符串文字转换为 SHOUTING CASE。
到目前为止,我的 proc-macro 库中的内容如下amplify:
// lib.rs
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, File};
#[proc_macro_attribute]
pub fn amplify(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as File);
// TODO: modify string literals (LitStr) in token tree to be upper case
let quoted = quote! {#input};
println!("{:#?}", quoted); // just print at compile time to see what is produced
quoted.into()
}
Run Code Online (Sandbox Code Playgroud)
当应用于简单的 hello-world 程序时,它应该变成“Hello, World!” 字符串文字转换为“HELLO, WORLD!” 在编译时。例子: …
我收到以下错误:
\n error[E0635]: unknown feature `proc_macro_span_shrink`\n --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.50/src/lib.rs:92:30\n |\n92 | feature(proc_macro_span, proc_macro_span_shrink)\n | ^^^^^^^^^^^^^^^^^^^^^^\n\nFor more information about this error, try `rustc --explain E0635`.\nerror: could not compile `proc-macro2` (lib) due to previous error\nRun Code Online (Sandbox Code Playgroud)\n我通过将我的 Rust 版本设置为特定的旧版夜间构建找到了解决方案,但这不适用于另一个项目,我真的想要一个更好的解决方案。我假设我正在使用某些东西的过时版本,或者也许我可以摆脱我的 Cargo.toml 文件中的依赖项,但该错误并没有告诉我有关哪个版本的任何信息。
\n经过一番搜索后,我尝试运行cargo tree -e features -i proc-macro2,但是虽然输出了很多涉及多个依赖项的内容,但没有任何具体涉及proc_macro_span_shrink.
proc-macro2 v1.0.50\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 quote v1.0.17\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 syn v1.0.90\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 proc-macro-error v1.0.4\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 proc-macro-error feature "default"\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 clap_derive v4.1.8 (proc-macro)\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 clap_derive feature "default"\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 clap v4.1.8\n\xe2\x94\x82 …Run Code Online (Sandbox Code Playgroud)