@@ -184,7 +184,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
184
184
use rustc_data_structures:: sync:: { par_iter, MTLock , MTRef , ParallelIterator } ;
185
185
use rustc_errors:: { ErrorReported , FatalError } ;
186
186
use rustc_hir as hir;
187
- use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
187
+ use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId , LOCAL_CRATE } ;
188
188
use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
189
189
use rustc_hir:: lang_items:: LangItem ;
190
190
use rustc_index:: bit_set:: GrowableBitSet ;
@@ -342,7 +342,8 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
342
342
. collect ( )
343
343
}
344
344
345
- // Collect all monomorphized items reachable from `starting_point`
345
+ /// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
346
+ /// post-monorphization error is encountered during a collection step.
346
347
fn collect_items_rec < ' tcx > (
347
348
tcx : TyCtxt < ' tcx > ,
348
349
starting_point : Spanned < MonoItem < ' tcx > > ,
@@ -359,6 +360,31 @@ fn collect_items_rec<'tcx>(
359
360
let mut neighbors = Vec :: new ( ) ;
360
361
let recursion_depth_reset;
361
362
363
+ //
364
+ // Post-monomorphization errors MVP
365
+ //
366
+ // We can encounter errors while monomorphizing an item, but we don't have a good way of
367
+ // showing a complete stack of spans ultimately leading to collecting the erroneous one yet.
368
+ // (It's also currently unclear exactly which diagnostics and information would be interesting
369
+ // to report in such cases)
370
+ //
371
+ // This leads to suboptimal error reporting: a post-monomorphization error (PME) will be
372
+ // shown with just a spanned piece of code causing the error, without information on where
373
+ // it was called from. This is especially obscure if the erroneous mono item is in a
374
+ // dependency. See for example issue #85155, where, before minimization, a PME happened two
375
+ // crates downstream from libcore's stdarch, without a way to know which dependency was the
376
+ // cause.
377
+ //
378
+ // If such an error occurs in the current crate, its span will be enough to locate the
379
+ // source. If the cause is in another crate, the goal here is to quickly locate which mono
380
+ // item in the current crate is ultimately responsible for causing the error.
381
+ //
382
+ // To give at least _some_ context to the user: while collecting mono items, we check the
383
+ // error count. If it has changed, a PME occurred, and we trigger some diagnostics about the
384
+ // current step of mono items collection.
385
+ //
386
+ let error_count = tcx. sess . diagnostic ( ) . err_count ( ) ;
387
+
362
388
match starting_point. node {
363
389
MonoItem :: Static ( def_id) => {
364
390
let instance = Instance :: mono ( tcx, def_id) ;
@@ -411,6 +437,22 @@ fn collect_items_rec<'tcx>(
411
437
}
412
438
}
413
439
440
+ // Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the
441
+ // mono item graph where the PME diagnostics are currently the most problematic (e.g. ones
442
+ // involving a dependency, and the lack of context is confusing) in this MVP, we focus on
443
+ // diagnostics on edges crossing a crate boundary: the collected mono items which are not
444
+ // defined in the local crate.
445
+ if tcx. sess . diagnostic ( ) . err_count ( ) > error_count && starting_point. node . krate ( ) != LOCAL_CRATE
446
+ {
447
+ tcx. sess . span_note_without_error (
448
+ starting_point. span ,
449
+ & format ! (
450
+ "the above error was encountered while instantiating `{}`" ,
451
+ starting_point. node
452
+ ) ,
453
+ ) ;
454
+ }
455
+
414
456
record_accesses ( tcx, starting_point. node , neighbors. iter ( ) . map ( |i| & i. node ) , inlining_map) ;
415
457
416
458
for neighbour in neighbors {
0 commit comments