Auto merge of #117557 - Zoxc:panic-prio, r=petrochenkov · rust-lang/rust@d8dbf7c (original) (raw)
`@@ -3,6 +3,8 @@
`
3
3
``
4
4
`#![allow(dead_code)]
`
5
5
``
``
6
`+
use crate::sync::IntoDynSyncSend;
`
``
7
`+
use crate::FatalErrorMarker;
`
6
8
`use parking_lot::Mutex;
`
7
9
`use std::any::Any;
`
8
10
`use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
`
`@@ -18,14 +20,17 @@ pub use enabled::*;
`
18
20
`/// continuing with unwinding. It's also used for the non-parallel code to ensure error message
`
19
21
`/// output match the parallel compiler for testing purposes.
`
20
22
`pub struct ParallelGuard {
`
21
``
`-
panic: Mutex<Option<Box<dyn Any + Send + 'static>>>,
`
``
23
`+
panic: Mutex<Option<IntoDynSyncSend<Box<dyn Any + Send + 'static>>>>,
`
22
24
`}
`
23
25
``
24
26
`impl ParallelGuard {
`
25
27
`pub fn run(&self, f: impl FnOnce() -> R) -> Option {
`
26
28
`catch_unwind(AssertUnwindSafe(f))
`
27
29
`.map_err(|err| {
`
28
``
`-
*self.panic.lock() = Some(err);
`
``
30
`+
let mut panic = self.panic.lock();
`
``
31
`+
if panic.is_none() || !(*err).is::() {
`
``
32
`+
*panic = Some(IntoDynSyncSend(err));
`
``
33
`+
}
`
29
34
`})
`
30
35
`.ok()
`
31
36
`}
`
`@@ -37,7 +42,7 @@ impl ParallelGuard {
`
37
42
`pub fn parallel_guard(f: impl FnOnce(&ParallelGuard) -> R) -> R {
`
38
43
`let guard = ParallelGuard { panic: Mutex::new(None) };
`
39
44
`let ret = f(&guard);
`
40
``
`-
if let Some(panic) = guard.panic.into_inner() {
`
``
45
`+
if let Some(IntoDynSyncSend(panic)) = guard.panic.into_inner() {
`
41
46
`resume_unwind(panic);
`
42
47
`}
`
43
48
` ret
`
`@@ -106,14 +111,20 @@ mod enabled {
`
106
111
` parallel!(impl fblock[fblock [fblock[block, (((c,)] [$($rest),])
`
107
112
`};
`
108
113
`(impl fblock:block[fblock:block [fblock:block[($blocks:expr,)*] []) => {
`
109
``
`-
::rustc_data_structures::sync::scope(|s| {
`
110
``
`-
(letblock=rustcdatastructures::sync::FromDyn::from(∣∣(let block = rustc_data_structures::sync::FromDyn::from(|| (letblock=rustcdatastructures::sync::FromDyn::from(∣∣blocks);
`
111
``
`-
s.spawn(move |_| block.into_inner()());)*
`
112
``
`-
(|| $fblock)();
`
``
114
`+
$crate::sync::parallel_guard(|guard| {
`
``
115
`+
$crate::sync::scope(|s| {
`
``
116
`+
$(
`
``
117
`+
let block = crate::sync::FromDyn::from(∣∣crate::sync::FromDyn::from(|| crate::sync::FromDyn::from(∣∣blocks);
`
``
118
`+
s.spawn(move |_| {
`
``
119
`+
guard.run(move || block.into_inner()());
`
``
120
`+
});
`
``
121
`+
)*
`
``
122
`+
guard.run(|| $fblock);
`
``
123
`+
});
`
113
124
`});
`
114
125
`};
`
115
126
`($fblock:block, (((blocks:block),*) => {
`
116
``
`-
if rustc_data_structures::sync::is_dyn_thread_safe() {
`
``
127
`+
if $crate::sync::is_dyn_thread_safe() {
`
117
128
`// Reverse the order of the later blocks since Rayon executes them in reverse order
`
118
129
`// when using a single thread. This ensures the execution order matches that
`
119
130
`// of a single threaded rustc.
`
`@@ -146,11 +157,13 @@ mod enabled {
`
146
157
`if mode::is_dyn_thread_safe() {
`
147
158
`let oper_a = FromDyn::from(oper_a);
`
148
159
`let oper_b = FromDyn::from(oper_b);
`
149
``
`-
let (a, b) = rayon::join(
`
150
``
`-
move || FromDyn::from(oper_a.into_inner()()),
`
151
``
`-
move || FromDyn::from(oper_b.into_inner()()),
`
152
``
`-
);
`
153
``
`-
(a.into_inner(), b.into_inner())
`
``
160
`+
let (a, b) = parallel_guard(|guard| {
`
``
161
`+
rayon::join(
`
``
162
`+
move || guard.run(move || FromDyn::from(oper_a.into_inner()())),
`
``
163
`+
move || guard.run(move || FromDyn::from(oper_b.into_inner()())),
`
``
164
`+
)
`
``
165
`+
});
`
``
166
`+
(a.unwrap().into_inner(), b.unwrap().into_inner())
`
154
167
`} else {
`
155
168
`super::disabled::join(oper_a, oper_b)
`
156
169
`}
`