Skip to content

Commit 7cc7b8f

Browse files
committed
Execute all parallel blocks even if they panic in a single-threaded compiler
1 parent 01f7450 commit 7cc7b8f

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

src/librustc/hir/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use syntax::util::parser::ExprPrecedence;
3030
use crate::ty::AdtKind;
3131
use crate::ty::query::Providers;
3232

33-
use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync};
33+
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
3434
use rustc_data_structures::thin_vec::ThinVec;
3535

3636
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
@@ -782,15 +782,15 @@ impl Crate {
782782
where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
783783
{
784784
parallel!({
785-
par_iter(&self.items).for_each(|(_, item)| {
785+
par_for_each_in(&self.items, |(_, item)| {
786786
visitor.visit_item(item);
787787
});
788788
}, {
789-
par_iter(&self.trait_items).for_each(|(_, trait_item)| {
789+
par_for_each_in(&self.trait_items, |(_, trait_item)| {
790790
visitor.visit_trait_item(trait_item);
791791
});
792792
}, {
793-
par_iter(&self.impl_items).for_each(|(_, impl_item)| {
793+
par_for_each_in(&self.impl_items, |(_, impl_item)| {
794794
visitor.visit_impl_item(impl_item);
795795
});
796796
});

src/librustc_data_structures/sync.rs

+41-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ cfg_if! {
6565
}
6666

6767
use std::ops::Add;
68+
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
6869

6970
#[derive(Debug)]
7071
pub struct Atomic<T: Copy>(Cell<T>);
@@ -130,7 +131,19 @@ cfg_if! {
130131
#[macro_export]
131132
macro_rules! parallel {
132133
($($blocks:tt),*) => {
133-
$($blocks)*;
134+
let mut panic = None;
135+
$(
136+
if let Err(p) = ::std::panic::catch_unwind(
137+
::std::panic::AssertUnwindSafe(|| $blocks)
138+
) {
139+
if panic.is_none() {
140+
panic = Some(p);
141+
}
142+
}
143+
)*
144+
if let Some(panic) = panic {
145+
::std::panic::resume_unwind(panic);
146+
}
134147
}
135148
}
136149

@@ -140,6 +153,24 @@ cfg_if! {
140153
t.into_iter()
141154
}
142155

156+
pub fn par_for_each_in<T: IntoIterator>(
157+
t: T,
158+
for_each:
159+
impl Fn(<<T as IntoIterator>::IntoIter as Iterator>::Item) + Sync + Send
160+
) {
161+
let mut panic = None;
162+
t.into_iter().for_each(|i| {
163+
if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
164+
if panic.is_none() {
165+
panic = Some(p);
166+
}
167+
}
168+
});
169+
if let Some(panic) = panic {
170+
resume_unwind(panic);
171+
}
172+
}
173+
143174
pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>;
144175

145176
pub use std::rc::Rc as Lrc;
@@ -308,6 +339,15 @@ cfg_if! {
308339
t.into_par_iter()
309340
}
310341

342+
pub fn par_for_each_in<T: IntoParallelIterator>(
343+
t: T,
344+
for_each: impl Fn(
345+
<<T as IntoParallelIterator>::Iter as ParallelIterator>::Item
346+
) + Sync + Send
347+
) {
348+
t.into_par_iter().for_each(for_each)
349+
}
350+
311351
pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>;
312352

313353
/// This makes locks panic if they are already held.

0 commit comments

Comments
 (0)