【问题标题】:How do I see the expanded macro code that's causing my compile error?如何查看导致编译错误的扩展宏代码?
【发布时间】:2015-04-19 06:19:36
【问题描述】:

我有一个涉及宏的编译错误:

<mdo macros>:6:19: 6:50 error: cannot move out of captured outer variable in an `FnMut` closure
<mdo macros>:6 bind ( $ e , move | $ p | mdo ! { $ ( $ t ) * } ) ) ; (
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<mdo macros>:1:1: 14:36 note: in expansion of mdo!
<mdo macros>:6:27: 6:50 note: expansion site
<mdo macros>:1:1: 14:36 note: in expansion of mdo!
<mdo macros>:6:27: 6:50 note: expansion site
<mdo macros>:1:1: 14:36 note: in expansion of mdo!
src/parser.rs:30:42: 37:11 note: expansion site
error: aborting due to previous error

不幸的是,宏是递归的,所以很难弄清楚编译器在抱怨什么,而且行号似乎是针对扩展宏而不是我的代码。

如何查看展开后的宏?有没有我可以传递给 rustc(或者更好的是 cargo)的标志来转储它?

(这个宏来自rust-mdo,虽然我觉得没关系。)

【问题讨论】:

    标签: debugging rust rust-macros rust-proc-macros rust-decl-macros


    【解决方案1】:

    是的,您可以将一个特殊标志传递给rustc,称为--pretty=expanded

    % cat test.rs
    fn main() {
        println!("Hello world");
    }
    % rustc -Z unstable-options --pretty=expanded test.rs
    #![feature(no_std)]
    #![no_std]
    #[prelude_import]
    use std::prelude::v1::*;
    #[macro_use]
    extern crate "std" as std;
    fn main() {
        ::std::old_io::stdio::println_args(::std::fmt::Arguments::new_v1({
                                                                             static __STATIC_FMTSTR:
                                                                                    &'static [&'static str]
                                                                                    =
                                                                                 &["Hello world"];
                                                                             __STATIC_FMTSTR
                                                                         },
                                                                         &match ()
                                                                              {
                                                                              ()
                                                                              =>
                                                                              [],
                                                                          }));
    }
    

    不过,您需要先通过 -Z unstable-options 来允许它。

    从 Rust 1.1 开始,您可以将这些参数传递给 Cargo,如下所示:

    cargo rustc -- -Z unstable-options --pretty=expanded
    

    【讨论】:

    • 从 1.19 开始,此命令 cargo rustc -- -Z unstable-options --pretty=expanded 现在仅在夜间可用。
    • 为什么只在夜间播放?(
    • @BogdanMart 因为它使用了一个不稳定的选项,但不用担心,您可以轻松使用它。运行rustup install nightly,然后运行rustup run nightly cargo rustc -- -Z unstable-options --pretty=expanded
    • 那么,三年来(而且还在继续),这种能力从未“稳定”过?
    • 可能不太关注稳定性,而更多的是他们不想承诺支持它。
    【解决方案2】:

    cargo rustc --profile=check -- -Zunpretty=expanded,但更简洁的选择是cargo-expand crate。它提供了一个 Cargo 子命令 cargo expand 打印宏扩展的结果。它还通过rustfmt 传递扩展代码,这通常会产生比 rustc 的默认输出更具可读性的代码。

    运行cargo install cargo-expand进行安装。

    【讨论】:

    • cargo install cargo-expand —features=prettyprint/regex-fancy 会稍微慢一些,但避免了 c++ 依赖,因此更有可能构建干净。
    • cargo-expand 不依赖于 prettyprint 或任何 C++ 依赖项。
    • 你应该提到你是箱子的作者
    • 现在是 2021 年,情况发生了一些变化。您现在可以使用:rustc -Zunpretty=expanded some.rs。有关详细信息,请参阅 Enselic 的答案。
    【解决方案3】:

    nightly-2021-07-28开始,必须通过-Zunpretty=expanded而不是-Zunstable-options --pretty=expanded,像这样:

    % rustc -Zunpretty=expanded test.rs
    

    或:

    % cargo rustc -- -Zunpretty=expanded
    

    相关的 rustc 提交

    --pretty 参数已通过 this commitnightly-2021-07-28 中删除。 对-Zunpretty=expanded 的支持已通过this commit 添加到nightly-2018-01-24

    【讨论】:

      猜你喜欢
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 2016-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      • 2017-04-27
      相关资源
      最近更新 更多