デバッグ

rustc は構文拡張全般をデバッグするためのツールをいくつか提供しています。さらに、宣言的マクロと手続き的マクロのそれぞれに合わせたより特化したツールも提供します。

普段は展開後のコードを見ることはないため、構文拡張の展開結果がよく分からなくなることがあります。 ありがたいことに、rustc のunstableな -Zunpretty=expanded 引数を使って展開後のコードを見ることができます。 次のようなコードがあるとします:

// Shorthand for initializing a `String`.
// `String` 初期化の略記法
macro_rules! S {
    ($e:expr) => {String::from($e)};
}

fn main() {
    let world = S!("World");
    println!("Hello, {}!", world);
}

これを次のコマンドでコンパイルすると:

rustc +nightly -Zunpretty=expanded hello.rs

次のような結果が得られます(結果を整形しています):

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2018::*;
#[macro_use]
extern crate std;
// Shorthand for initializing a `String`.
// `String` 初期化の略記法
macro_rules! S { ($e : expr) => { String :: from($e) } ; }

fn main() {
    let world = String::from("World");
    {
        ::std::io::_print(
            ::core::fmt::Arguments::new_v1(
                &["Hello, ", "!\n"],
                &match (&world,) {
                    (arg0,) => [
                        ::core::fmt::ArgumentV1::new(arg0, ::core::fmt::Display::fmt)
                    ],
                }
            )
        );
    };
}

構文拡張のデバッグを支援する手段を提供しているのは rustc だけではありません。 dtolnay氏cargo-expandという名前の素晴らしい cargo プラグインを制作しています。これは基本的には前述した -Zunpretty=expanded オプションの単なるラッパーです。

Playgroundを利用することもできます。右上にある TOOLS ボタンをクリックすると、構文拡張を展開するオプションが選択できます。