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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
//! 标准库宏
//!
//! 该模块包含一组从标准库导出的宏。
//! 当链接到标准库时,每个宏都可以使用。
//!

#[doc = include_str!("../../core/src/macros/panic.md")]
#[macro_export]
#[cfg_attr(bootstrap, rustc_builtin_macro = "std_panic")]
#[cfg_attr(not(bootstrap), rustc_builtin_macro(std_panic))]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(edition_panic)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
macro_rules! panic {
    // 根据调用者的版本扩展为 `$crate::panic::panic_2015` 或 `$crate::panic::panic_2021`。
    //
    ($($arg:tt)*) => {
        /* compiler built-in */
    };
}

/// 打印到标准输出。
///
/// 等效于 [`println!`] 宏,只是在消息末尾不打印换行符。
///
/// 注意,默认情况下,stdout 通常是行缓冲的,因此可能有必要使用 [`io::stdout().flush()`][flush] 以确保立即发出输出。
///
///
/// `print!` 仅用于程序的主要输出。请改用 [`eprint!`] 打印错误和进度消息。
///
/// [flush]: crate::io::Write::flush
///
/// # Panics
///
/// 如果写入 `io::stdout()` 失败,则为 Panics。
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// print!("this ");
/// print!("will ");
/// print!("be ");
/// print!("on ");
/// print!("the ");
/// print!("same ");
/// print!("line ");
///
/// io::stdout().flush().unwrap();
///
/// print!("this string has a newline, why not choose println! instead?\n");
///
/// io::stdout().flush().unwrap();
/// ```
///
///
///
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! print {
    ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
}

/// 用换行符打印到标准输出。
///
/// 在所有平台上,换行符仅是 LINE FEED 字符 (`\n`/`U+000A`) (没有其他的 CARRIAGE RETURN (`\r`/`U+000D`))。
///
///
/// 使用 [`format!`] 语法将数据写入标准输出。
/// 有关更多信息,请参见 [`std::fmt`]。
///
/// `println!` 仅用于程序的主要输出。请改用 [`eprintln!`] 打印错误和进度消息。
///
/// [`std::fmt`]: crate::fmt
///
/// # Panics
///
/// 如果写入 [`io::stdout`] 失败,则为 Panics。
///
/// [`io::stdout`]: crate::io::stdout
///
/// # Examples
///
/// ```
/// println!(); // 只打印换行符
/// println!("hello there!");
/// println!("format {} arguments", "some");
/// ```
///
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_print($crate::format_args_nl!($($arg)*));
    })
}

/// 打印到标准错误。
///
/// 等效于 [`print!`] 宏,除了输出转到 [`io::stderr`] 而不是 [`io::stdout`]。
///
/// 有关用法示例,请参见 [`print!`]。
///
/// 仅将 `eprint!` 用于错误和进度消息。
/// 改用 `print!` 作为程序的主要输出。
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// 如果写入 `io::stderr` 失败,则为 Panics。
///
/// # Examples
///
/// ```
/// eprint!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! eprint {
    ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
}

/// 用换行符打印到标准错误。
///
/// 等效于 [`println!`] 宏,除了输出转到 [`io::stderr`] 而不是 [`io::stdout`]。
///
/// 有关用法示例,请参见 [`println!`]。
///
/// 仅将 `eprintln!` 用于错误和进度消息。
/// 改用 `println!` 作为程序的主要输出。
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// 如果写入 `io::stderr` 失败,则为 Panics。
///
/// # Examples
///
/// ```
/// eprintln!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! eprintln {
    () => ($crate::eprint!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_eprint($crate::format_args_nl!($($arg)*));
    })
}

/// 打印并返回给定表达式的值,以进行快速而肮脏的调试。
///
/// 一个例子:
///
/// ```rust
/// let a = 2;
/// let b = dbg!(a * 2) + 1;
/// // ^-- 打印: [src/main.rs:2] a * 2 = 4
/// assert_eq!(b, 5);
/// ```
///
/// 宏通过使用给定表达式的类型的 `Debug` 实现将值与宏调用的源位置以及表达式的源代码一起打印到 [stderr] 来工作。
///
///
/// 调用表达式上的宏会移动并获取它的所有权,然后再返回不变的求值表达式。
/// 如果表达式的类型未实现 `Copy`,并且您不想放弃所有权,则可以改用 `dbg!(&expr)` 借用某些表达式 `expr`。
///
/// `dbg!` 宏在发行版中的工作原理完全相同。
/// 当仅在发行版本中发生的调试问题或在发行模式下进行的调试明显更快时,此功能很有用。
///
/// 请注意,宏的目的是作为调试工具,因此您应该避免在版本控制中长时间使用它 (测试和类似的情况除外)。
/// 使用其他工具 (例如 [`log`] crate 的 [`debug!`] 宏) 可以更好地完成生产代码的调试输出。
///
/// # Stability
///
/// 不应依赖此宏打印的确切输出,并且可能会受到 future 的更改。
///
/// # Panics
///
/// 如果写入 `io::stderr` 失败,则为 Panics。
///
/// # 进一步的例子
///
/// 用一种方法:
///
/// ```rust
/// fn foo(n: usize) {
///     if let Some(_) = dbg!(n.checked_sub(4)) {
///         // ...
///     }
/// }
///
/// foo(3)
/// ```
///
/// 打印到 [stderr]:
///
/// ```text,ignore
/// [src/main.rs:4] n.checked_sub(4) = None
/// ```
///
/// 单纯的析因实现:
///
/// ```rust
/// fn factorial(n: u32) -> u32 {
///     if dbg!(n <= 1) {
///         dbg!(1)
///     } else {
///         dbg!(n * factorial(n - 1))
///     }
/// }
///
/// dbg!(factorial(4));
/// ```
///
/// 打印到 [stderr]:
///
/// ```text,ignore
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = true
/// [src/main.rs:4] 1 = 1
/// [src/main.rs:5] n * factorial(n - 1) = 2
/// [src/main.rs:5] n * factorial(n - 1) = 6
/// [src/main.rs:5] n * factorial(n - 1) = 24
/// [src/main.rs:11] factorial(4) = 24
/// ```
///
/// `dbg!(..)` 宏移动输入:
///
/// ```compile_fail
/// /// `usize` 的包装器,重要的是它不可复制。
/// #[derive(Debug)]
/// struct NoCopy(usize);
///
/// let a = NoCopy(42);
/// let _ = dbg!(a); // <-- `a` 移到这里了
/// let _ = dbg!(a); // <-- `a` 再次移动; error!
/// ```
///
/// 您也可以使用不带任何值的 `dbg!()` 来仅在到达文件和行时打印它。
///
/// 最后,如果要 `dbg!(..)` 多个值,它将把它们视为一个元组 (并返回它) :
///
/// ```
/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
/// ```
///
/// 但是,遵循在宏调用中忽略尾部逗号的约定,带有尾部逗号的单个参数仍不会被视为元组。如果需要一个,可以直接使用一个 1 元组:
///
/// ```
/// assert_eq!(1, dbg!(1u32,)); // 尾部逗号被忽略
/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
/// ```
///
/// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
/// [`log`]: https://crates.io/crates/log
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
#[macro_export]
#[stable(feature = "dbg_macro", since = "1.32.0")]
macro_rules! dbg {
    // NOTE: 我们不能使用 `concat!` 作为 `eprintln!` 的格式参数来生成静态字符串,因为 `file!` 可能包含 `{` 或 `$val` 表达式可能是一个块 (`{。
    // }`),在这种情况下 `eprintln!` 的格式将不正确。
    //
    //
    () => {
        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
    };
    ($val:expr $(,)?) => {
        // 在此使用 `match` 是有意的,因为它会影响临时人员的生命周期 - https://stackoverflow.com/a/48732525/1063961
        //
        match $val {
            tmp => {
                $crate::eprintln!("[{}:{}] {} = {:#?}",
                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($($crate::dbg!($val)),+,)
    };
}

#[cfg(test)]
macro_rules! assert_approx_eq {
    ($a:expr, $b:expr) => {{
        let (a, b) = (&$a, &$b);
        assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
    }};
}