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

`}

`