diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index edf2e539765..0109580a0bb 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -186,6 +186,15 @@ impl<'tcx> MonoItem<'tcx> { pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode { crate::dep_graph::make_compile_mono_item(tcx, self) } + + /// Returns the item's `CrateNum` + pub fn krate(&self) -> CrateNum { + match self { + MonoItem::Fn(ref instance) => instance.def_id().krate, + MonoItem::Static(def_id) => def_id.krate, + MonoItem::GlobalAsm(..) => LOCAL_CRATE, + } + } } impl<'a, 'tcx> HashStable> for MonoItem<'tcx> { diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index ef79f36b3b5..afe4457bf43 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -184,7 +184,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; use rustc_errors::{ErrorReported, FatalError}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; +use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; @@ -342,7 +342,8 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec( tcx: TyCtxt<'tcx>, starting_point: Spanned>, @@ -359,6 +360,31 @@ fn collect_items_rec<'tcx>( let mut neighbors = Vec::new(); let recursion_depth_reset; + // + // Post-monomorphization errors MVP + // + // We can encounter errors while monomorphizing an item, but we don't have a good way of + // showing a complete stack of spans ultimately leading to collecting the erroneous one yet. + // (It's also currently unclear exactly which diagnostics and information would be interesting + // to report in such cases) + // + // This leads to suboptimal error reporting: a post-monomorphization error (PME) will be + // shown with just a spanned piece of code causing the error, without information on where + // it was called from. This is especially obscure if the erroneous mono item is in a + // dependency. See for example issue #85155, where, before minimization, a PME happened two + // crates downstream from libcore's stdarch, without a way to know which dependency was the + // cause. + // + // If such an error occurs in the current crate, its span will be enough to locate the + // source. If the cause is in another crate, the goal here is to quickly locate which mono + // item in the current crate is ultimately responsible for causing the error. + // + // To give at least _some_ context to the user: while collecting mono items, we check the + // error count. If it has changed, a PME occurred, and we trigger some diagnostics about the + // current step of mono items collection. + // + let error_count = tcx.sess.diagnostic().err_count(); + match starting_point.node { MonoItem::Static(def_id) => { let instance = Instance::mono(tcx, def_id); @@ -411,6 +437,22 @@ fn collect_items_rec<'tcx>( } } + // Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the + // mono item graph where the PME diagnostics are currently the most problematic (e.g. ones + // involving a dependency, and the lack of context is confusing) in this MVP, we focus on + // diagnostics on edges crossing a crate boundary: the collected mono items which are not + // defined in the local crate. + if tcx.sess.diagnostic().err_count() > error_count && starting_point.node.krate() != LOCAL_CRATE + { + tcx.sess.span_note_without_error( + starting_point.span, + &format!( + "the above error was encountered while instantiating `{}`", + starting_point.node + ), + ); + } + record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map); for neighbour in neighbors {