33
44#![allow(dead_code)]
55
6+ use crate::sync::IntoDynSyncSend;
7+ use crate::FatalErrorMarker;
68use parking_lot::Mutex;
79use std::any::Any;
810use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
@@ -18,14 +20,17 @@ pub use enabled::*;
1820/// continuing with unwinding. It's also used for the non-parallel code to ensure error message
1921/// output match the parallel compiler for testing purposes.
2022pub struct ParallelGuard {
21- panic: Mutex<Option<Box<dyn Any + Send + 'static>>>,
23+ panic: Mutex<Option<IntoDynSyncSend< Box<dyn Any + Send + 'static> >>>,
2224}
2325
2426impl ParallelGuard {
2527 pub fn run<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
2628 catch_unwind(AssertUnwindSafe(f))
2729 .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+ }
2934 })
3035 .ok()
3136 }
@@ -37,7 +42,7 @@ impl ParallelGuard {
3742pub fn parallel_guard<R>(f: impl FnOnce(&ParallelGuard) -> R) -> R {
3843 let guard = ParallelGuard { panic: Mutex::new(None) };
3944 let ret = f(&guard);
40- if let Some(panic) = guard.panic.into_inner() {
45+ if let Some(IntoDynSyncSend( panic) ) = guard.panic.into_inner() {
4146 resume_unwind(panic);
4247 }
4348 ret
@@ -106,14 +111,20 @@ mod enabled {
106111 parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
107112 };
108113 (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+ });
113124 });
114125 };
115126 ($fblock:block, $($blocks:block),*) => {
116- if rustc_data_structures ::sync::is_dyn_thread_safe() {
127+ if $crate ::sync::is_dyn_thread_safe() {
117128 // Reverse the order of the later blocks since Rayon executes them in reverse order
118129 // when using a single thread. This ensures the execution order matches that
119130 // of a single threaded rustc.
@@ -146,11 +157,13 @@ mod enabled {
146157 if mode::is_dyn_thread_safe() {
147158 let oper_a = FromDyn::from(oper_a);
148159 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())
154167 } else {
155168 super::disabled::join(oper_a, oper_b)
156169 }
0 commit comments