标签: rust-proc-macros

将字符串转换为 TokenStream

给定一个字符串 ( 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)

rust rust-macros rust-proc-macros

3
推荐指数
1
解决办法
2375
查看次数

如何为 syn::parse 找到正确的返回类型?

我有一个TokenStream来自 Rust 函数的定义。我想用syn::parse(和.unrwap())解析它。但是,我不知道返回类型应该是什么:

let ast: ??? = syn::parse(token_stream_from_function_definition).unwrap();
Run Code Online (Sandbox Code Playgroud)

应该是什么类型ast

macros rust rust-proc-macros

3
推荐指数
1
解决办法
628
查看次数

在程序宏中,如何检查字符串是否是有效的变量名而不是关键字?

在过程宏中,我希望能够检查字符串是否是有效的变量名而不是关键字。

proc_macro2::Ident如果尝试使用无效的变量名将使用户感到恐慌,但是它将允许我不想使用的关键字。在惊慌之前用一个很好的和有用的错误消息来处理错误也将更好。

是否有一些宏或函数(位于板条箱中或其他方式)将检查字符串是否遵守有关变量名规则?我可能可以使用正则表达式来做到这一点,但是龙却生活在正则表达式中。

这种情况的用例是处理用户输入字符串,其中可能包括垃圾字符串。

rust rust-macros rust-proc-macros

3
推荐指数
1
解决办法
54
查看次数

用于在函数开头注入代码的过程属性宏

我正在尝试构建一个简单的属性,它将在函数的开头注入一个 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> …

rust rust-macros rust-proc-macros

3
推荐指数
1
解决办法
3332
查看次数

Proc 宏“main”未扩展 + Rust 分析器未生成服务器

我将这两个问题合二为一,因为它们可能是相关的。几天前,我开始在 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)

我该如何解决这个问题?

rust rust-proc-macros rust-analyzer

3
推荐指数
1
解决办法
8105
查看次数

使用syn时如何从Option &lt;T&gt;获取T?

syn用来解析Rust代码。当我使用读取命名字段的类型时field.ty,得到一个syn::Type。当我使用打印时,quote!{#ty}.to_string()我得到了"Option<String>"

我怎样才能得到"String"?我想用#tyquote!打印"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)

metaprogramming rust rust-proc-macros

2
推荐指数
2
解决办法
452
查看次数

转换引用内的类型!给出特征错误

我收到此错误:

该特征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内部令牌?我尝试使用parseinto但这对我来说没有成功。谢谢!

rust rust-proc-macros

2
推荐指数
1
解决办法
1682
查看次数

程序宏可以作为函数进行调试吗?

我正在尝试在我正在使用的库中调试复杂的程序宏。

由于我不能使用带有宏的调试器,并且各种宏扩展工具在这里被证明是无用的,我正在寻找替代方案。

程序宏是否可以像经过适当调试的函数一样运行?我想象将结果存储proc_macro::TokenStream在一个变量中。

rust rust-macros rust-proc-macros

2
推荐指数
1
解决办法
363
查看次数

将属性转换为 proc 宏导出上的标识符

我正在编写我的第一个 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)

macros parsing rust rust-proc-macros

2
推荐指数
1
解决办法
3279
查看次数

如何使用 proc_macro 为引用中的宏插值函数提供枚举索引?

我已经实现了以下 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 rust-proc-macros

2
推荐指数
1
解决办法
616
查看次数

如何在 Rust 中使用 proc_macro_attribute 修改所有字符串文字?

我正在摆弄 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!” 在编译时。例子: …

rust rust-proc-macros

1
推荐指数
1
解决办法
1481
查看次数

如何判断为什么需要“未知功能”功能?

我收到以下错误:

\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\n
Run Code Online (Sandbox Code Playgroud)\n

我通过将我的 Rust 版本设置为特定的旧版夜间构建​​找到了解决方案,但这不适用于另一个项目,我真的想要一个更好的解决方案。我假设我正在使用某些东西的过时版本,或者也许我可以摆脱我的 Cargo.toml 文件中的依赖项,但该错误并没有告诉我有关哪个版本的任何信息。

\n

经过一番搜索后,我尝试运行cargo tree -e features -i proc-macro2,但是虽然输出了很多涉及多个依赖项的内容,但没有任何具体涉及proc_macro_span_shrink.

\n
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)

rust rust-cargo rust-proc-macros

1
推荐指数
1
解决办法
393
查看次数