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}