]> git.proxmox.com Git - rustc.git/blobdiff - src/doc/edition-guide/src/rust-2021/panic-macro-consistency.md
New upstream version 1.55.0+dfsg1
[rustc.git] / src / doc / edition-guide / src / rust-2021 / panic-macro-consistency.md
index cf4265bcc575a25397432013c5b6380e3e1eeb18..0e3295186eab340399207144ece96ab383fc1f7a 100644 (file)
@@ -2,14 +2,21 @@
 
 ## Summary
 
-## Details
+- `panic!(..)` now always uses `format_args!(..)`, just like `println!()`.
+- `panic!("{")` is no longer accepted, without escaping the `{` as `{{`.
+- `panic!(x)` is no longer accepted if `x` is not a string literal.
+  - Use `std::panic::panic_any(x)` to panic with a non-string payload.
+  - Or use `panic!("{}", x)` to use `x`'s `Display` implementation.
+- The same applies to `assert!(expr, ..)`.
 
+## Details
 
 The `panic!()` macro is one of Rust's most well known macros.
 However, it has [some subtle surprises](https://github.com/rust-lang/rfcs/blob/master/text/3007-panic-plan.md)
 that we can't just change due to backwards compatibility.
 
 ```rust,ignore
+// Rust 2018
 panic!("{}", 1); // Ok, panics with the message "1"
 panic!("{}"); // Ok, panics with the message "{}"
 ```
@@ -18,12 +25,14 @@ The `panic!()` macro only uses string formatting when it's invoked with more tha
 When invoked with a single argument, it doesn't even look at that argument.
 
 ```rust,ignore
+// Rust 2018
 let a = "{";
 println!(a); // Error: First argument must be a format string literal
 panic!(a); // Ok: The panic macro doesn't care
 ```
 
-(It even accepts non-strings such as `panic!(123)`, which is uncommon and rarely useful.)
+It even accepts non-strings such as `panic!(123)`, which is uncommon and rarely useful since it
+produces a surprisingly unhelpful message: `panicked at 'Box<Any>'`.
 
 This will especially be a problem once
 [implicit format arguments](https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html)
@@ -39,6 +48,37 @@ Since `panic!()` will no longer accept arbitrary payloads,
 [`panic_any()`](https://doc.rust-lang.org/stable/std/panic/fn.panic_any.html)
 will be the only way to panic with something other than a formatted string.
 
+```rust,ignore
+// Rust 2021
+panic!("{}", 1); // Ok, panics with the message "1"
+panic!("{}"); // Error, missing argument
+panic!(a); // Error, must be a string literal
+```
+
 In addition, `core::panic!()` and `std::panic!()` will be identical in Rust 2021.
 Currently, there are some historical differences between those two,
-which can be noticable when switching `#![no_std]` on or off.
\ No newline at end of file
+which can be noticeable when switching `#![no_std]` on or off.
+
+## Migration
+
+A lint, `non_fmt_panics`, gets triggered whenever there is some call to `panic` that uses some 
+deprecated behavior that will error in Rust 2021. The `non_fmt_panics` lint has already been a warning 
+by default on all editions since the 1.50 release (with several enhancements made in later releases). 
+If your code is already warning free, then it should already be ready to go for Rust 2021!
+
+You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by
+running:
+
+```sh
+cargo fix --edition
+```
+
+Should you choose or need to manually migrate, you'll need to update all panic invocations to either use the same 
+formatting as `println` or use `std::panic::panic_any` to panic with non-string data.
+
+For example, in the case of `panic!(MyStruct)`, you'll need to convert to using `std::panic::panic_any` (note
+that this is a function not a macro): `std::panic::panic_any(MyStruct)`.
+
+In the case of panic messages that include curly braces but the wrong number of arguments (e.g., `panic!("Some curlies: {}")`), 
+you can panic with the string literal by either using the same syntax as `println!` (i.e., `panic!("{}", "Some curlies: {}")`) 
+or by escaping the curly braces (i.e., `panic!("Some curlies: {{}}")`).
\ No newline at end of file