@@ -17,6 +17,7 @@ use errors::DiagnosticBuilder;
17
17
use errors:: Level ;
18
18
use ty:: tls;
19
19
use ty:: { TyCtxt } ;
20
+ use ty:: maps:: Query ;
20
21
use ty:: maps:: config:: QueryDescription ;
21
22
use ty:: maps:: job:: { QueryResult , QueryInfo } ;
22
23
use ty:: item_path;
@@ -63,6 +64,7 @@ pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
63
64
64
65
#[ derive( Clone ) ]
65
66
pub ( super ) struct CycleError < ' tcx > {
67
+ /// The span of the reason the first query in `cycle` ran the last query in `cycle`
66
68
pub ( super ) span : Span ,
67
69
pub ( super ) cycle : Vec < QueryInfo < ' tcx > > ,
68
70
}
@@ -79,27 +81,31 @@ pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
79
81
}
80
82
81
83
impl < ' a , ' gcx , ' tcx > TyCtxt < ' a , ' gcx , ' tcx > {
82
- pub ( super ) fn report_cycle ( self , CycleError { span, cycle : stack } : CycleError )
84
+ pub ( super ) fn report_cycle ( self , CycleError { span, cycle : stack } : CycleError < ' gcx > )
83
85
-> DiagnosticBuilder < ' a >
84
86
{
85
87
assert ! ( !stack. is_empty( ) ) ;
86
88
89
+ let fix_span = |span : Span , query : & Query < ' gcx > | {
90
+ self . sess . codemap ( ) . def_span ( query. default_span ( self , span) )
91
+ } ;
92
+
87
93
// Disable naming impls with types in this path, since that
88
94
// sometimes cycles itself, leading to extra cycle errors.
89
95
// (And cycle errors around impls tend to occur during the
90
96
// collect/coherence phases anyhow.)
91
97
item_path:: with_forced_impl_filename_line ( || {
92
- let span = self . sess . codemap ( ) . def_span ( span ) ;
98
+ let span = fix_span ( span , & stack . first ( ) . unwrap ( ) . query ) ;
93
99
let mut err =
94
100
struct_span_err ! ( self . sess, span, E0391 ,
95
101
"cyclic dependency detected" ) ;
96
102
err. span_label ( span, "cyclic reference" ) ;
97
103
98
- err. span_note ( self . sess . codemap ( ) . def_span ( stack[ 0 ] . span ) ,
104
+ err. span_note ( fix_span ( stack[ 0 ] . span , & stack [ 0 ] . query ) ,
99
105
& format ! ( "the cycle begins when {}..." , stack[ 0 ] . query. describe( self ) ) ) ;
100
106
101
107
for & QueryInfo { span, ref query, .. } in & stack[ 1 ..] {
102
- err. span_note ( self . sess . codemap ( ) . def_span ( span) ,
108
+ err. span_note ( fix_span ( span, query ) ,
103
109
& format ! ( "...which then requires {}..." , query. describe( self ) ) ) ;
104
110
}
105
111
@@ -266,6 +272,22 @@ macro_rules! define_maps {
266
272
r
267
273
}
268
274
}
275
+
276
+ // FIXME(eddyb) Get more valid Span's on queries.
277
+ pub fn default_span( & self , tcx: TyCtxt <' _, $tcx, ' _>, span: Span ) -> Span {
278
+ if span != DUMMY_SP {
279
+ return span;
280
+ }
281
+ // The def_span query is used to calculate default_span,
282
+ // so exit to avoid infinite recursion
283
+ match * self {
284
+ Query :: def_span( ..) => return span,
285
+ _ => ( )
286
+ }
287
+ match * self {
288
+ $( Query :: $name( key) => key. default_span( tcx) , ) *
289
+ }
290
+ }
269
291
}
270
292
271
293
pub mod queries {
@@ -303,7 +325,7 @@ macro_rules! define_maps {
303
325
/// If the query already executed and panicked, this will fatal error / silently panic
304
326
fn try_get_lock(
305
327
tcx: TyCtxt <' a, $tcx, ' lcx>,
306
- mut span: Span ,
328
+ span: Span ,
307
329
key: & $K
308
330
) -> TryGetLock <' a, $tcx, $V, Self >
309
331
{
@@ -329,21 +351,14 @@ macro_rules! define_maps {
329
351
} ;
330
352
mem:: drop( lock) ;
331
353
332
- // This just matches the behavior of `try_get_with` so the span when
333
- // we await matches the span we would use when executing.
334
- // See the FIXME there.
335
- if span == DUMMY_SP && stringify!( $name) != "def_span" {
336
- span = key. default_span( tcx) ;
337
- }
338
-
339
354
if let Err ( cycle) = job. await ( tcx, span) {
340
355
return TryGetLock :: JobCompleted ( Err ( cycle) ) ;
341
356
}
342
357
}
343
358
}
344
359
345
360
fn try_get_with( tcx: TyCtxt <' a, $tcx, ' lcx>,
346
- mut span: Span ,
361
+ span: Span ,
347
362
key: $K)
348
363
-> Result <$V, CycleError <$tcx>>
349
364
{
@@ -377,18 +392,6 @@ macro_rules! define_maps {
377
392
378
393
let mut lock = get_lock_or_return!( ) ;
379
394
380
- // FIXME(eddyb) Get more valid Span's on queries.
381
- // def_span guard is necessary to prevent a recursive loop,
382
- // default_span calls def_span query internally.
383
- if span == DUMMY_SP && stringify!( $name) != "def_span" {
384
- // This might deadlock if we hold the map lock since we might be
385
- // waiting for the def_span query and switch to some other fiber
386
- // So we drop the lock here and reacquire it
387
- mem:: drop( lock) ;
388
- span = key. default_span( tcx) ;
389
- lock = get_lock_or_return!( ) ;
390
- }
391
-
392
395
// Fast path for when incr. comp. is off. `to_dep_node` is
393
396
// expensive for some DepKinds.
394
397
if !tcx. dep_graph. is_fully_enabled( ) {
0 commit comments