1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
//! Tells you what type things are. //! //! This crate provides the `what!` macro. This is functionally similar to the //! [`todo!`] macro, except that it also tells you type information. //! //! ``` rust //! # use cargo_what::what; //! # use std::error::Error; //! fn hello() -> Result<(), Box<dyn Error>> { //! what!() //! } //! ``` //! //! Just like [`todo!`], `what!` passes all type-checks and makes it easy to //! write/build/test unfinished code. If it ever ends up in a compiled program, //! attempted to execute a `what!` will panic. //! //! The fun part happens when you run `cargo what`. //! //! ``` bash //! $ cargo what //! hole: expecting `std::result::Result<(), Box<dyn std::error::Error>>` //! --> src/hello.rs //! | //! 2 | what!() //! | ^^^^^^^ //! ``` //! //! Unfortunately, custom diagnostics aren't really available to Rust libraries, //! requiring the extra command. `cargo what` can be installed with `cargo`: //! //! ``` bash //! $ cargo install cargo-what //! ``` //! //! `cargo what` wraps `cargo build` to show the type-info of any `what!`s //! you have in your code. //! //! `what!` also accepts arguments and shows their types, which can be useful //! for reducing the "unused variable" noise. //! //! ``` rust //! # use cargo_what::what; //! fn hello(a: usize, b: usize) -> usize { //! let c = a..b; //! what!(a, b, c) //! } //! ``` //! //! And with `cargo what`: //! //! ```bash //! $ cargo what //! hole: expecting `usize` //! --> src/hello.rs //! | //! 3 | what!(a, b, c) //! | ^^^^^^^^^^^^^^ //! | //! = note: a is `usize` //! = note: b is `usize` //! = note: c is `std::ops::Range<usize>` //! ``` //! //! Emacs keybindings left as an exercise to the reader. //! //! [`todo!`]: https://doc.rust-lang.org/std/macro.todo.html //! // we need this for token pasting #[doc(hidden)] pub use paste as __paste; /// This is the core `what!` macro. /// /// It behaves similarly to [`todo!`], passes all type-checks, /// and panics if executed. /// /// ```rust /// # use cargo_what::what; /// # use std::error::Error; /// fn hello() -> Result<(), Box<dyn Error>> { /// what!() /// } /// ``` /// /// One difference from [`todo!`] is that `what!` also accepts /// arbitrary arguments, which can help reduce "unused variable" /// noise. /// /// ``` rust /// # use cargo_what::what; /// fn hello(a: usize, b: usize) -> usize { /// let c = a..b; /// what!(a, b, c) /// } /// ``` /// /// See the [crate-level documentation](/cargo_what) for more info /// on how you can show the type-info of `what!`s in a program. /// /// [`todo!`]: https://doc.rust-lang.org/std/macro.todo.html /// // cargo build => todo #[cfg(not(cargo_what_query))] #[macro_export] macro_rules! what { ($($args:expr),* $(,)*) => { ({ $( let _ = $args; )* todo!() }) }; } // cargo what => query type info #[cfg(cargo_what_query)] #[macro_export] macro_rules! what { (@[$($n:expr)*] $(,)*) => {}; (@[$($n:expr)*] $arg:ident, $($args:tt)*) => { // we can use ident directly as a special case $crate::__paste::paste! { trait [<What_ $arg>] {}; let _: &dyn [<What_ $arg>] = &$arg; } what!(@[$($n)* 0] $($args)*); }; (@[$($n:expr)*] $arg:expr, $($args:tt)*) => { $crate::__paste::paste! { trait [<What_ $($n)*>] {}; // yes you need these parens (tt munching?) let _: &dyn [<What_ $($n)*>] = &($arg); } what!(@[$($n)* 0] $($args)*); }; // actual macro ($($args:tt)*) => { ({ todo!(); #[allow(unreachable_code)] { what!(@[0] $($args)*,); trait What {}; match true { true => { let what; let _: &dyn What = &what; what } false => { struct WhatTrait {}; impl What for WhatTrait {}; WhatTrait{} } } } }) }; }