标签: rust-macros

如何在不为每个字段重复“pub”的情况下创建一个所有字段都是公共的公共结构?

如何在 Rust 中定义一个公共结构,其中所有字段都是公共的,而不必pub在每个字段前重复修饰符?

一个pub_struct宏将是理想的:

pub_struct! Foo {
    a: i32,
    b: f64,
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这相当于:

pub struct Foo {
    pub a: i32,
    pub b: f64,
    //...
}
Run Code Online (Sandbox Code Playgroud)

struct public rust rust-macros

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

#[should_panic] 不接受预期的常量恐慌消息

运行 rust 单元测试时,使用属性宏 #[should_panic(expect = )] 来断言测试因正确的错误消息而发生恐慌(这意味着它在您希望它发生恐慌的行处发生恐慌,而不是因为不同的错误。

但是,在使用在errors.rs 文件中定义的标准化错误消息的应用程序中,不可能将错误消息的常量作为expect 的参数传递。

这:

pub const ERR_001: &str = "ERR_001 message";

#[test]
#[should_panic(expected = ERR_001)]
fn test_function() {

        //test code here

}

Run Code Online (Sandbox Code Playgroud)

产生以下错误:

error: expected unsuffixed literal or identifier, found `ERR_001`
  --> staking/src/storage.rs:74:31
   |
74 |     #[should_panic(expected = ERR_001)]
   |                    
Run Code Online (Sandbox Code Playgroud)

有没有办法将常量或变量传递给 #[should_panic(expected = )] 宏?或者是否有必要总是写消息而不是?

testing unit-testing rust rust-macros

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

从父模块导入宏

我在箱子里重复使用宏时遇到了麻烦.

如果在以下位置定义了宏./src/macros.rs:

#[macro_export]
macro_rules! my_macro {
    ...
}
Run Code Online (Sandbox Code Playgroud)

用于./src/lib.rs:

#[macro_use]
pub mod macros;
Run Code Online (Sandbox Code Playgroud)

我看不到这个宏./src/submod/lib.rs:

my_macro!(...);
Run Code Online (Sandbox Code Playgroud)

它会产生错误消息error: macro undefined: 'my_macro!'.

有没有办法在这个子模块中导入这个宏submod

rust rust-macros rust-decl-macros

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

如何在宏派生中将字符串连接到 ident?

我需要创建一个宏派生,其中名称是函数名称的一部分。(这段代码不起作用,只是为了说明问题)

fn impl_logic(ast: &syn::DeriveInput) -> TokenStream {
    let name:&syn::Ident = &ast.ident;

    let gen = quote! {
       pub fn #name_logic() -> Arc<Mutex<UiAplicacion>> {
           ...
       }
    };

    gen.into()
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

rust rust-macros

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

如何在不知道其结构的情况下创建匹配枚举变体的宏?

我找到了以下解决方案来创建一个宏,该宏定义一个函数,如果枚举与变体匹配,该函数将返回 true:

macro_rules! is_variant {
    ($name: ident, $enum_type: ty, $enum_pattern: pat) => {
        fn $name(value: &$enum_type) -> bool {
            matches!(value, $enum_pattern)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

enum TestEnum {
    A,
    B(),
    C(i32, i32),
}

is_variant!(is_a, TestEnum, TestEnum::A);
is_variant!(is_b, TestEnum, TestEnum::B());
is_variant!(is_c, TestEnum, TestEnum::C(_, _));

assert_eq!(is_a(&TestEnum::A), true);
assert_eq!(is_a(&TestEnum::B()), false);
assert_eq!(is_a(&TestEnum::C(1, 1)), false);
Run Code Online (Sandbox Code Playgroud)

有没有办法定义这个宏,以避免为变体数据提供占位符?

换句话说,更改宏以便能够像这样使用它:

is_variant!(is_a, TestEnum, TestEnum::A);
is_variant!(is_a, TestEnum, TestEnum::B);
is_variant!(is_a, TestEnum, TestEnum::C);
Run Code Online (Sandbox Code Playgroud)

使用(如仅按变体而不是值比较枚举std::mem::discriminant中所述)没有帮助,因为它只能用于比较两个枚举实例。在这种情况下,只有一个对象和变体标识符。它还提到了匹配,但如果变体没有数据,则不起作用。TestEnum::A(..)

enums rust rust-macros

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

无法在宏中使用self,因为宏扩展忽略了令牌"self"

我想写一个打印"OK"然后在方法中返回self的宏.这是我的第一个宏,所以我尝试了这个,认为它只会像文本替换一样,但它失败了:

macro_rules! print_ok_and_return_self {
    () => {
        println!("OK");
        self
    }
}

fn main() {
    let a = A{};
    a.a().a();
}

struct A {}

impl A {
    fn a(self) -> Self {
        print_ok_and_return_self!()
    }
}
Run Code Online (Sandbox Code Playgroud)

错误:

error: macro expansion ignores token `self` and any following
 --> src/main.rs:4:13
  |
4 |             self
  |             ^^^^
  |
note: caused by the macro expansion here; the usage of `print_ok_and_return_self!` is likely invalid in expression context
 --> src/main.rs:17:13
  |
17|             print_ok_and_return_self!()
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

快速查看文档后,我知道这不仅仅是文本替换,但我仍然不知道如何使其工作.

rust rust-macros

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

如何在过程宏中提供有用的编译器错误?

我正在使用proc_macro和设计自定义HTML语法分析器syn.一个样品:

#[derive(Debug)]
struct BlockElement {
    stag: Ident,
    child: Vec<Element>,
    ctag: Ident
}

impl Synom for BlockElement {
     named!(parse -> Self, do_parse!(
         punct!(<) >>
         stag: syn!(Ident) >>
         punct!(>) >>
         child: syn!(ElementList) >>
         punct!(<) >>
         punct!(/) >>
         ctag: syn!(Ident) >>
         punct!(>) >>
         (BlockElement { stag, child: child.inner, ctag })
     ));
 }
Run Code Online (Sandbox Code Playgroud)

虽然我知道Span在解析之后如何使用错误,我无法在解析过程中弄清楚如何使用错误.它只是出错了failed to parse anything.如何确定解析失败的位置并给出适当的错误?

rust rust-macros

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

在Rust中创建宏的闭包环境

我正在尝试实现这样的(简化):

macro_rules! atest {
    ($closure:tt) => {
        let x = 5;
        println!("Result is {}", $closure())
    };
}

fn main() {
    //let x = 50;
    atest!((|| 5 + x));
}
Run Code Online (Sandbox Code Playgroud)

它不起作用,因为atest在宏评估之前编译器会考虑宏的参数:

error[E0425]: cannot find value `x` in this scope
  --> src/main.rs:10:20
   |
10 |     atest!((|| 5 + x));
   |                    ^ not found in this scope
Run Code Online (Sandbox Code Playgroud)

是否有可能使这项工作?我的理解是在编译之前扩展了宏.

rust rust-macros

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

是否有可能在纯Rust宏中编写像`print!`这样复杂的东西?

我开始学习Rust宏,但文档有些限制.哪个好 - 我猜他们是专家.虽然我可以进行基本的代码生成,特性的实现等等,但是一些内置的宏似乎远不止于此,例如各种打印宏,它们检查字符串文字并将其用于代码扩展.

我查看了源代码print!,它调用了另一个名为的宏format_args.不幸的是,这似乎并没有构建在"纯Rust"中,评论只是说"内置编译器".

是否可以编写像print!纯Rust宏一样复杂的东西?如果是这样,它会怎么做?

我实际上对构建"编译时间"感兴趣 - 基本上将某些固定字符串识别为在编译时修复的"关键字".这可能是高性能的(可能)但主要是我只对代码生成感兴趣.

code-generation rust rust-macros

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

当尝试使用“quote!”重复向量时,“找到结构‘ThereIsNoIteratorInRepetition’”

我正在尝试创建一个Vecof TokenStreams,然后在另一个quote!宏中使用该列表:

    let list: Vec<_> = some_data
        .iter()
        .map(
            |item| {
                quote!{/*...*/}
            },
        )
        .collect();

    let generated = quote! {
        fn hello_world() {
            #(list);*
        }
    };
Run Code Online (Sandbox Code Playgroud)

但是,在编译时,我收到此错误:

expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
Run Code Online (Sandbox Code Playgroud)

宏的文档来看,它似乎TokenStream在插值中应该有效,因为它实现了该ToTokens特征。此外,该列表是 a Vec,它也明确允许在循环插值中使用。

ThereIsNoIteratorInRepetition当我明确使用有效的迭代器时,为什么会收到错误?

rust rust-macros

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