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<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
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::<FatalErrorMarker>() {
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<R>(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 [$block, $($c,)*] [$($rest),*])
107
112
};
108
113
(impl $fblock:block [$($blocks:expr,)*] []) => {
109
- ::rustc_data_structures::sync::scope(|s| {
110
- $(let block = rustc_data_structures::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(|| $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
}
0 commit comments