-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shorten lifetime of panic temporaries in panic_fmt case #104134
Conversation
(rustbot has picked a reviewer for you, use r? to override) |
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
This seems very similar to #64856, but I'm not sure if this case has observable drop-order effects. |
Maybe I should know better after #99689, but I was not able to come up with any program where this PR would cause a change in drop order at runtime. |
This seems like a reasonable change to me. I'd want to see it pass a crater run (either directly or as part of the normal beta crater runs) but otherwise 👍. |
Beta craters are going to be sufficient here I think. |
a968c88
to
ea4865a
Compare
|
☔ The latest upstream changes (presumably #106745) made this pull request unmergeable. Please resolve the merge conflicts. |
ea4865a
to
24a3c6e
Compare
|
@bors r+ If any beta crater issues point to this it can be reverted. |
📌 Commit 24a3c6e9f3f3bbdc4056f9a17ec71132305a6ff1 has been approved by It is now in the queue for this repository. |
⌛ Testing commit 24a3c6e9f3f3bbdc4056f9a17ec71132305a6ff1 with merge 2843a0374d879599f630d965f729636bd632ab30... |
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
The failure in src/tools/clippy/tests/ui/diverging_sub_expression.stderr is related to rust-lang/rust-clippy#10776. I think this is okay to land without fixing that in clippy first. |
@bors r=joshtriplett |
@@ -53,9 +55,11 @@ pub macro panic_2021 { | |||
("{}", $arg:expr $(,)?) => ( | |||
$crate::panicking::panic_display(&$arg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the same be done here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Followup: #111590.
☀️ Test successful - checks-actions |
I’m gonna be honest, I completely forgot what the original issue was about but I’m THRILLED an issue this old finally has a resolution. Thanks so much everyone! |
Finished benchmarking commit (eda41ad): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 641.664s -> 642.273s (0.09%) |
Shorten even more panic temporary lifetimes Followup to rust-lang#104134. As pointed out by `@bjorn3` in rust-lang#104134 (review), there are other cases in the panic macros which would also benefit from dropping their non-Send temporaries as soon as possible, avoiding pointlessly holding them across an await point. For the tests added in this PR, here are the failures you get today on master without the macro changes in this PR: <details> <summary>tests/ui/macros/panic-temporaries-2018.rs</summary> ```console error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:52:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:52:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:53:18 | LL | require_send(panic_str()); | ^^^^^^^^^^^ future returned by `panic_str` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:40:36 | LL | f(panic!((NOT_SEND, "...").1)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:54:18 | LL | require_send(unreachable_display()); | ^^^^^^^^^^^^^^^^^^^^^ future returned by `unreachable_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:45:31 | LL | f(unreachable!(NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:54:18 | LL | require_send(unreachable_display()); | ^^^^^^^^^^^^^^^^^^^^^ future returned by `unreachable_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:45:31 | LL | f(unreachable!(NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: aborting due to 5 previous errors ``` </details> <details> <summary>tests/ui/macros/panic-temporaries.rs</summary> ```console error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries.rs:42:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries.rs:38:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries.rs:42:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries.rs:38:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: aborting due to 2 previous errors ``` </details> r? bjorn3
Shorten even more panic temporary lifetimes Followup to #104134. As pointed out by `@bjorn3` in rust-lang/rust#104134 (review), there are other cases in the panic macros which would also benefit from dropping their non-Send temporaries as soon as possible, avoiding pointlessly holding them across an await point. For the tests added in this PR, here are the failures you get today on master without the macro changes in this PR: <details> <summary>tests/ui/macros/panic-temporaries-2018.rs</summary> ```console error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:52:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:52:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:53:18 | LL | require_send(panic_str()); | ^^^^^^^^^^^ future returned by `panic_str` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:40:36 | LL | f(panic!((NOT_SEND, "...").1)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:54:18 | LL | require_send(unreachable_display()); | ^^^^^^^^^^^^^^^^^^^^^ future returned by `unreachable_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:45:31 | LL | f(unreachable!(NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:54:18 | LL | require_send(unreachable_display()); | ^^^^^^^^^^^^^^^^^^^^^ future returned by `unreachable_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:45:31 | LL | f(unreachable!(NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: aborting due to 5 previous errors ``` </details> <details> <summary>tests/ui/macros/panic-temporaries.rs</summary> ```console error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries.rs:42:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries.rs:38:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries.rs:42:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries.rs:38:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: aborting due to 2 previous errors ``` </details> r? bjorn3
Shorten even more panic temporary lifetimes Followup to #104134. As pointed out by `@bjorn3` in rust-lang/rust#104134 (review), there are other cases in the panic macros which would also benefit from dropping their non-Send temporaries as soon as possible, avoiding pointlessly holding them across an await point. For the tests added in this PR, here are the failures you get today on master without the macro changes in this PR: <details> <summary>tests/ui/macros/panic-temporaries-2018.rs</summary> ```console error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:52:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:52:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:53:18 | LL | require_send(panic_str()); | ^^^^^^^^^^^ future returned by `panic_str` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:40:36 | LL | f(panic!((NOT_SEND, "...").1)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:54:18 | LL | require_send(unreachable_display()); | ^^^^^^^^^^^^^^^^^^^^^ future returned by `unreachable_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:45:31 | LL | f(unreachable!(NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries-2018.rs:54:18 | LL | require_send(unreachable_display()); | ^^^^^^^^^^^^^^^^^^^^^ future returned by `unreachable_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries-2018.rs:45:31 | LL | f(unreachable!(NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries-2018.rs:48:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: aborting due to 5 previous errors ``` </details> <details> <summary>tests/ui/macros/panic-temporaries.rs</summary> ```console error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries.rs:42:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | -------- ^^^^^- `NOT_SEND` is later dropped here | | | | | await occurs here, with `NOT_SEND` maybe used later | has type `NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries.rs:38:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely --> tests/ui/macros/panic-temporaries.rs:42:18 | LL | require_send(panic_display()); | ^^^^^^^^^^^^^^^ future returned by `panic_display` is not `Send` | = help: within `NotSend`, the trait `Sync` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> tests/ui/macros/panic-temporaries.rs:35:31 | LL | f(panic!("{}", NOT_SEND)).await; | ---------------------- ^^^^^- the value is later dropped here | | | | | await occurs here, with the value maybe used later | has type `&NotSend` which is not `Send` note: required by a bound in `require_send` --> tests/ui/macros/panic-temporaries.rs:38:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: aborting due to 2 previous errors ``` </details> r? bjorn3
This fixes an issue called out by @fasterthanlime in https://octodon.social/@fasterthanlime/109304454114856561. Macros like
todo!("…")
andpanic!("…", …)
drop theirformat_args
temporary at the nearest enclosing semicolon outside the macro invocation, not inside the macro invocation. Due to the formatting internals being type-erased in a way that is not thread-safe, this blocks futures from beingSend
if there is anawait
anywhere between the panic call and the nearest enclosing semicolon.Example:
Before:
After: works.
Arguably there is a rustc fix that could work here too, instead of a standard library change. Rustc could be taught that the code shown above is fine to compile because the
await
is unreachable and so temporaries before theawait
do not need to get put in the anonymous compiler-generatedFuture
struct, regardless of syntactically where they're supposed to be dropped according to the language semantics.I would be open to that, though my recollection is that in the past we have been very hesitant about introducing any smarts into Drop placement. People want the language rules about where temporaries are dropped to be as simplistic and predictable as possible.