< 返回版块

Aaron009 发表于 2021-01-28 14:39

教程地址: https://www.cnblogs.com/gyc567/p/12045350.html

我根据作者自定义派生宏custom derive,一步一步操作的,但是编译不通过。

代码目录结构如下

├── Cargo.toml
├── src
│   └── lib.rs
└── tests
    └── test.rs

Cargo.toml

[package]
name = "test_derive_macro"
version = "0.1.0"
authors = ["fang <x@qq.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc_macro = true

[dependencies]

lib.rs

extern crate proc_macro;
use self::proc_macro::TokenStream;

// 自定义派生属性
#[proc_macro_derive(A)]
pub fn derive(input: TokenStream) -> TokenStream {
    let _input = input.to_string();
    assert!(_input.contains("struct A;"));
    r#"
        impl A {
            fn a(&self) -> String{
               format!("hello from impl A")
           }
       }
   "#
        .parse()
        .unwrap()
}

test.rs

#[macro_use]
extern crate test_derive_macro;

#[derive(A)]
struct A;
#[test]
fn test_derive_a() {
    assert_eq!("hello from impl A".to_string(), A.a());
}

项目文件夹目录下,执行 cargo test,报错如下

   Compiling test_derive_macro v0.1.0 (/Volumes/data/rust_project/rust_study/exmaple/test_derive_macro)
error: proc-macro derive panicked
 --> tests/test.rs:4:10
  |
4 | #[derive(A)]
  |          ^
  |
  = help: message: assertion failed: _input.contains("struct A;")

error[E0599]: no method named `a` found for struct `A` in the current scope
 --> tests/test.rs:8:51
  |
5 | struct A;
  | --------- method `a` not found for this
...
8 |     assert_eq!("hello from impl A".to_string(), A.a());
  |                                                   ^ method not found in `A`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0599`.
error: could not compile `test_derive_macro`

To learn more, run the command again with --verbose.

评论区

写评论
johnmave126 2021-02-02 14:35

能调试,你直接println!,然后panic,我记得编译失败时会打印procedural macro的打印内容

--
👇
Aaron009: 谢谢确实通过了,但是这个还是让我有点云里雾里的。 我是第一次接触到编程里的宏这个概念,学下来之后。宏的意思是好像通过宏生成代码。

我遇到以下两个问题: 问题一: 宏编写的代码,没有办法调试。比如我想知道 let _input = input.to_string(); 这里的 _input我该如何知道,它值是多少。

问题二: 如何知道 宏生成的代码,是什么样的,有没有什么工具可以查看。

谢谢你 @uno

👇
uno:

去掉这一行 assert!(_input.contains("struct A;"));

Bai-Jinlin 2021-01-28 18:53

cargo expand来进行宏展开。宏就是一种元编程的概念,你可以写出能产生新代码的代码。

--
👇
Aaron009: 谢谢确实通过了,但是这个还是让我有点云里雾里的。 我是第一次接触到编程里的宏这个概念,学下来之后。宏的意思是好像通过宏生成代码。

我遇到以下两个问题: 问题一: 宏编写的代码,没有办法调试。比如我想知道 let _input = input.to_string(); 这里的 _input我该如何知道,它值是多少。

问题二: 如何知道 宏生成的代码,是什么样的,有没有什么工具可以查看。

谢谢你 @uno

👇
uno:

去掉这一行 assert!(_input.contains("struct A;"));

93996817 2021-01-28 17:22
// cargo expand 可以展开宏
 let _v=vec![1,2,3,4];
//会展开成如下代码:
 let _v = <[_]>::into_vec(box [1, 2, 3, 4]);

uno 2021-01-28 15:49

去看这个吧,这里面都有 https://github.com/dtolnay/syn

--
👇
Aaron009: 谢谢确实通过了,但是这个还是让我有点云里雾里的。 我是第一次接触到编程里的宏这个概念,学下来之后。宏的意思是好像通过宏生成代码。

我遇到以下两个问题: 问题一: 宏编写的代码,没有办法调试。比如我想知道 let _input = input.to_string(); 这里的 _input我该如何知道,它值是多少。

问题二: 如何知道 宏生成的代码,是什么样的,有没有什么工具可以查看。

作者 Aaron009 2021-01-28 15:23

谢谢确实通过了,但是这个还是让我有点云里雾里的。 我是第一次接触到编程里的宏这个概念,学下来之后。宏的意思是好像通过宏生成代码。

我遇到以下两个问题: 问题一: 宏编写的代码,没有办法调试。比如我想知道 let _input = input.to_string(); 这里的 _input我该如何知道,它值是多少。

问题二: 如何知道 宏生成的代码,是什么样的,有没有什么工具可以查看。

谢谢你 @uno

👇
uno:

去掉这一行 assert!(_input.contains("struct A;"));

uno 2021-01-28 15:01

去掉这一行 assert!(_input.contains("struct A;"));

1 共 6 条评论, 1 页