@@ -62,7 +62,7 @@ pub struct QueryJob<'tcx> {
62
62
pub diagnostics : Lock < Vec < Diagnostic > > ,
63
63
64
64
#[ cfg( parallel_queries) ]
65
- latch : QueryLatch ,
65
+ latch : QueryLatch < ' tcx > ,
66
66
}
67
67
68
68
impl < ' tcx > QueryJob < ' tcx > {
@@ -146,41 +146,45 @@ impl<'tcx> QueryJob<'tcx> {
146
146
///
147
147
/// This does nothing for single threaded rustc,
148
148
/// as there are no concurrent jobs which could be waiting on us
149
- pub fn signal_complete ( & self , tcx : TyCtxt < ' _ , ' tcx , ' _ > ) {
149
+ pub fn signal_complete ( & self ) {
150
150
#[ cfg( parallel_queries) ]
151
- self . latch . set ( tcx ) ;
151
+ self . latch . set ( ) ;
152
152
}
153
153
}
154
154
155
155
#[ cfg( parallel_queries) ]
156
- struct QueryWaiter < ' a , ' tcx : ' a > {
157
- query : & ' a Option < Lrc < QueryJob < ' tcx > > > ,
156
+ struct QueryWaiter < ' tcx > {
157
+ query : * const Option < Lrc < QueryJob < ' tcx > > > ,
158
158
condvar : Condvar ,
159
159
span : Span ,
160
160
cycle : Option < CycleError < ' tcx > > ,
161
161
}
162
162
163
163
#[ cfg( parallel_queries) ]
164
- impl < ' a , ' tcx > QueryWaiter < ' a , ' tcx > {
165
- fn notify ( & self , tcx : TyCtxt < ' _ , ' _ , ' _ > , registry : & rayon_core:: Registry ) {
164
+ impl < ' tcx > QueryWaiter < ' tcx > {
165
+ fn notify ( & self , registry : & rayon_core:: Registry ) {
166
166
rayon_core:: mark_unblocked ( registry) ;
167
167
self . condvar . notify_one ( ) ;
168
168
}
169
169
}
170
170
171
171
#[ cfg( parallel_queries) ]
172
- struct QueryLatchInfo {
172
+ struct QueryLatchInfo < ' tcx > {
173
173
complete : bool ,
174
- waiters : Vec < & ' static mut QueryWaiter < ' static , ' static > > ,
174
+ waiters : Vec < * mut QueryWaiter < ' tcx > > ,
175
175
}
176
176
177
+ // Required because of raw pointers
177
178
#[ cfg( parallel_queries) ]
178
- struct QueryLatch {
179
- info : Mutex < QueryLatchInfo > ,
179
+ unsafe impl < ' tcx > Send for QueryLatchInfo < ' tcx > { }
180
+
181
+ #[ cfg( parallel_queries) ]
182
+ struct QueryLatch < ' tcx > {
183
+ info : Mutex < QueryLatchInfo < ' tcx > > ,
180
184
}
181
185
182
186
#[ cfg( parallel_queries) ]
183
- impl QueryLatch {
187
+ impl < ' tcx > QueryLatch < ' tcx > {
184
188
fn new ( ) -> Self {
185
189
QueryLatch {
186
190
info : Mutex :: new ( QueryLatchInfo {
@@ -190,44 +194,45 @@ impl QueryLatch {
190
194
}
191
195
}
192
196
193
- fn await ( & self , waiter : & mut QueryWaiter < ' _ , ' _ > ) {
197
+ fn await ( & self , waiter : & mut QueryWaiter < ' tcx > ) {
194
198
let mut info = self . info . lock ( ) ;
195
199
if !info. complete {
196
- let waiter = & * waiter;
197
- unsafe {
198
- #[ allow( mutable_transmutes) ]
199
- info. waiters . push ( mem:: transmute ( waiter) ) ;
200
- }
200
+ info. waiters . push ( waiter) ;
201
+ let condvar = & waiter. condvar ;
201
202
// If this detects a deadlock and the deadlock handler want to resume this thread
202
203
// we have to be in the `wait` call. This is ensured by the deadlock handler
203
204
// getting the self.info lock.
204
205
rayon_core:: mark_blocked ( ) ;
205
- waiter . condvar . wait ( & mut info) ;
206
+ condvar. wait ( & mut info) ;
206
207
}
207
208
}
208
209
209
- fn set ( & self , tcx : TyCtxt < ' _ , ' _ , ' _ > ) {
210
+ fn set ( & self ) {
210
211
let mut info = self . info . lock ( ) ;
211
212
debug_assert ! ( !info. complete) ;
212
213
info. complete = true ;
213
214
let registry = rayon_core:: Registry :: current ( ) ;
214
215
for waiter in info. waiters . drain ( ..) {
215
- waiter. notify ( tcx, & registry) ;
216
+ unsafe {
217
+ ( * waiter) . notify ( & registry) ;
218
+ }
216
219
}
217
220
}
218
221
219
222
fn resume_waiter (
220
223
& self ,
221
224
waiter : usize ,
222
- error : CycleError
223
- ) -> & ' static mut QueryWaiter < ' static , ' static > {
225
+ error : CycleError < ' tcx >
226
+ ) -> * mut QueryWaiter < ' tcx > {
224
227
let mut info = self . info . lock ( ) ;
225
228
debug_assert ! ( !info. complete) ;
226
229
// Remove the waiter from the list of waiters
227
230
let waiter = info. waiters . remove ( waiter) ;
228
231
229
232
// Set the cycle error it will be picked it up when resumed
230
- waiter. cycle = unsafe { Some ( mem:: transmute ( error) ) } ;
233
+ unsafe {
234
+ ( * waiter) . cycle = Some ( error) ;
235
+ }
231
236
232
237
waiter
233
238
}
@@ -250,10 +255,12 @@ where
250
255
return Some ( cycle) ;
251
256
}
252
257
}
253
- for ( i, waiter) in query. latch . info . lock ( ) . waiters . iter ( ) . enumerate ( ) {
254
- if let Some ( ref waiter_query) = waiter. query {
255
- if visit ( waiter. span , & * * waiter_query as Ref ) . is_some ( ) {
256
- return Some ( Some ( ( query_ref, i) ) ) ;
258
+ for ( i, & waiter) in query. latch . info . lock ( ) . waiters . iter ( ) . enumerate ( ) {
259
+ unsafe {
260
+ if let Some ( ref waiter_query) = * ( * waiter) . query {
261
+ if visit ( ( * waiter) . span , & * * waiter_query as Ref ) . is_some ( ) {
262
+ return Some ( Some ( ( query_ref, i) ) ) ;
263
+ }
257
264
}
258
265
}
259
266
}
@@ -322,7 +329,7 @@ fn query_entry<'tcx>(r: Ref<'tcx>) -> QueryInfo<'tcx> {
322
329
#[ cfg( parallel_queries) ]
323
330
fn remove_cycle < ' tcx > (
324
331
jobs : & mut Vec < Ref < ' tcx > > ,
325
- wakelist : & mut Vec < & ' static mut QueryWaiter < ' static , ' static > > ,
332
+ wakelist : & mut Vec < * mut QueryWaiter < ' tcx > > ,
326
333
tcx : TyCtxt < ' _ , ' tcx , ' _ >
327
334
) {
328
335
let mut visited = HashSet :: new ( ) ;
@@ -453,7 +460,9 @@ fn deadlock(tcx: TyCtxt<'_, '_, '_>, registry: &rayon_core::Registry) {
453
460
454
461
// FIXME: Ensure this won't cause a deadlock before we return
455
462
for waiter in wakelist. into_iter ( ) {
456
- waiter. notify ( tcx, registry) ;
463
+ unsafe {
464
+ ( * waiter) . notify ( registry) ;
465
+ }
457
466
}
458
467
459
468
on_panic. disable ( ) ;
0 commit comments