turbo_tasks/debug/
vdbg.rs

1// NOTE(alexkirsz) Implementation and comments are based on the `dbg!` macro
2// from the Rust standard library.
3/// This macro supports the same syntax as `dbg!`, but also supports
4/// pretty-printing `Vc` types.
5///
6/// Beware: this macro should only be used for debugging purposes. Its behavior
7/// around dependency tracking is not well-defined and could lead to unexpected
8/// results.
9#[macro_export]
10macro_rules! vdbg {
11    // NOTE: We cannot use `concat!` to make a static string as a format argument
12    // of `eprintln!` because `file!` could contain a `{` or
13    // `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
14    // will be malformed.
15    () => {
16        eprintln!("[{}:{}]", file!(), line!())
17    };
18
19    (__init $depth:expr ; [ $val:expr $(, $rest:expr)* ] [ $($tt:tt)* ] ) => {
20        {
21            let valstr = stringify!($val);
22            // We move the value into a new binding so we may refer to it multiple
23            // times without re-evaluating the expression.
24            let valmove = $val;
25            // We convert the value to an owned value which will be moved into the
26            // spawned thread. This is necessary in order to ensure a 'static lifetime
27            // for the value, but it may require a clone.
28            let valowned = valmove.to_owned();
29            $crate::vdbg!(__init $depth ; [ $($rest),* ] [ $($tt)* valstr valmove valowned ])
30        }
31    };
32    (__init $depth:expr ; [ ] [ $($valstr:ident $valmove:ident $valowned:ident)* ] ) => {
33        {
34            use $crate::debug::ValueDebugFormat;
35            let depth = $depth;
36            $crate::macro_helpers::spawn_detached_for_testing(async move {
37                $crate::vdbg!(__expand depth ; [ $($valstr $valowned)* ] []);
38                Ok(())
39            });
40            ($($valmove),*)
41        }
42    };
43
44    (__expand $depth:ident ; [ $valstr:ident $val:ident $($rest:tt)* ] [ $($tt:tt)* ]) => {
45        let valdbg = (&$val).value_debug_format($depth).try_to_string().await?;
46        $crate::vdbg!(__expand $depth ; [ $($rest)* ] [ $($tt)* $valstr valdbg ]);
47    };
48    (__expand $depth:ident ; [] [ $( $valstr:ident $valdbg:ident )* ]) => {
49        // By pre-awaiting, then printing everything at once, we ensure that the
50        // output won't be interleaved with output from other threads, and that
51        // it will always appear in the order that the macro was invoked.
52        eprint!(
53            $crate::vdbg!(__repeat "[{file}:{line}] {} = {}\n" $($valstr)*),
54            $(
55                $valstr,
56                $valdbg,
57            )*
58            file = file!(),
59            line = line!(),
60        );
61    };
62
63    // Sub-macro for repeating a string N times, where N is controlled by the number of identifiers
64    // passed to the macro.
65    (__repeat $str:literal $x:ident $($rest:ident)*) => { concat!($str, $crate::vdbg!(__repeat $str $($rest)*)) };
66    (__repeat $str:literal) => { "" };
67
68    ($($val:expr),* ; depth = $depth:expr) => {
69        $crate::vdbg!(__init $depth ; [ $($val),* ] [])
70    };
71    ($($val:expr),+ $(,)?) => {
72        $crate::vdbg!(__init usize::MAX ; [ $($val),* ] [])
73    };
74}