From ac9aed56e4dc62c4959ae0c14cec585994302c93 Mon Sep 17 00:00:00 2001 From: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Date: Fri, 27 Sep 2019 21:32:04 +0800 Subject: [PATCH] getting more context for duplicate lang items (fixes #60561) Where possible, the error message includes the name of the crate that brought in the crate with duplicate lang items (which helps with debugging). This information is passed on from cstore using the `extern_crate` query. --- src/librustc/middle/cstore.rs | 9 ++++- src/librustc/middle/lang_items.rs | 34 ++++++++++++++++--- src/librustc/ty/print/pretty.rs | 2 +- src/librustc_metadata/creader.rs | 15 ++++---- src/librustc_metadata/cstore_impl.rs | 2 +- src/test/ui/duplicate_entry_error.stderr | 2 +- src/test/ui/error-codes/E0152.stderr | 2 +- .../ui/panic-handler/panic-handler-std.stderr | 2 +- 8 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index de84fcd7160d..ddf6262b7382 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -126,10 +126,17 @@ pub struct ExternCrate { /// used to select the extern with the shortest path pub path_len: usize, + /// Crate that depends on this crate + pub dependency_of: CrateNum, +} + +impl ExternCrate { /// If true, then this crate is the crate named by the extern /// crate referenced above. If false, then this crate is a dep /// of the crate. - pub direct: bool, + pub fn is_direct(&self) -> bool { + self.dependency_of == LOCAL_CRATE + } } #[derive(Copy, Clone, Debug, HashStable)] diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index c5d9a722ae18..cab929389d6a 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -13,6 +13,7 @@ use crate::hir::def_id::DefId; use crate::hir::check_attr::Target; use crate::ty::{self, TyCtxt}; use crate::middle::weak_lang_items; +use crate::middle::cstore::ExternCrate; use crate::util::nodemap::FxHashMap; use syntax::ast; @@ -182,16 +183,39 @@ impl LanguageItemCollector<'tcx> { E0152, "duplicate lang item found: `{}`.", name), - None => self.tcx.sess.struct_err(&format!( - "duplicate lang item in crate `{}`: `{}`.", - self.tcx.crate_name(item_def_id.krate), - name)), + None => { + match self.tcx.extern_crate(item_def_id) { + Some(ExternCrate {dependency_of, ..}) => { + self.tcx.sess.struct_err(&format!( + "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.", + self.tcx.crate_name(item_def_id.krate), + self.tcx.crate_name(*dependency_of), + name)) + }, + _ => { + self.tcx.sess.struct_err(&format!( + "duplicate lang item in crate `{}`: `{}`.", + self.tcx.crate_name(item_def_id.krate), + name)) + } + } + }, }; if let Some(span) = self.tcx.hir().span_if_local(original_def_id) { span_note!(&mut err, span, "first defined here."); } else { - err.note(&format!("first defined in crate `{}`.", + match self.tcx.extern_crate(original_def_id) { + Some(ExternCrate {dependency_of, ..}) => { + err.note(&format!( + "first defined in crate `{}` (which `{}` depends on).", + self.tcx.crate_name(original_def_id.krate), + self.tcx.crate_name(*dependency_of))); + }, + _ => { + err.note(&format!("first defined in crate `{}`.", self.tcx.crate_name(original_def_id.krate))); + } + } } err.emit(); } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 2bc87d6b8ba5..fe0d0fad3a56 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -278,7 +278,7 @@ pub trait PrettyPrinter<'tcx>: match self.tcx().extern_crate(def_id) { Some(&ExternCrate { src: ExternCrateSource::Extern(def_id), - direct: true, + dependency_of: LOCAL_CRATE, span, .. }) => { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index af41b6a4c857..91b9f38ebce1 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -17,6 +17,7 @@ use rustc::middle::cstore::{ExternCrate, ExternCrateSource}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; +use rustc::hir::def_id::LOCAL_CRATE; use std::ops::Deref; use std::path::PathBuf; @@ -430,7 +431,7 @@ impl<'a> CrateLoader<'a> { mut extern_crate: ExternCrate, visited: &mut FxHashSet<(CrateNum, bool)>) { - if !visited.insert((cnum, extern_crate.direct)) { return } + if !visited.insert((cnum, extern_crate.is_direct())) { return } let cmeta = self.cstore.get_crate_data(cnum); let mut old_extern_crate = cmeta.extern_crate.borrow_mut(); @@ -441,14 +442,14 @@ impl<'a> CrateLoader<'a> { // - shorter paths to longer (tuple.2). let new_rank = ( true, - extern_crate.direct, + extern_crate.is_direct(), cmp::Reverse(extern_crate.path_len), ); let old_rank = match *old_extern_crate { None => (false, false, cmp::Reverse(usize::max_value())), Some(ref c) => ( true, - c.direct, + c.is_direct(), cmp::Reverse(c.path_len), ), }; @@ -460,7 +461,7 @@ impl<'a> CrateLoader<'a> { drop(old_extern_crate); // Propagate the extern crate info to dependencies. - extern_crate.direct = false; + extern_crate.dependency_of = cnum; for &dep_cnum in cmeta.dependencies.borrow().iter() { self.update_extern_crate(dep_cnum, extern_crate, visited); } @@ -1030,7 +1031,7 @@ impl<'a> CrateLoader<'a> { src: ExternCrateSource::Extern(def_id), span: item.span, path_len, - direct: true, + dependency_of: LOCAL_CRATE, }, &mut FxHashSet::default(), ); @@ -1057,7 +1058,7 @@ impl<'a> CrateLoader<'a> { span, // to have the least priority in `update_extern_crate` path_len: usize::max_value(), - direct: true, + dependency_of: LOCAL_CRATE, }, &mut FxHashSet::default(), ); @@ -1081,7 +1082,7 @@ impl<'a> CrateLoader<'a> { span, // to have the least priority in `update_extern_crate` path_len: usize::max_value(), - direct: true, + dependency_of: LOCAL_CRATE, }, &mut FxHashSet::default(), ); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 11121ee875dd..0cca4dfa4c5e 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -233,7 +233,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, missing_extern_crate_item => { let r = match *cdata.extern_crate.borrow() { - Some(extern_crate) if !extern_crate.direct => true, + Some(extern_crate) if !extern_crate.is_direct() => true, _ => false, }; r diff --git a/src/test/ui/duplicate_entry_error.stderr b/src/test/ui/duplicate_entry_error.stderr index 1892ad38a594..02be11d1fd0e 100644 --- a/src/test/ui/duplicate_entry_error.stderr +++ b/src/test/ui/duplicate_entry_error.stderr @@ -7,7 +7,7 @@ LL | | loop {} LL | | } | |_^ | - = note: first defined in crate `std`. + = note: first defined in crate `std` (which `duplicate_entry_error` depends on). error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr index 26e6e2e1bce7..d4b59a1148e6 100644 --- a/src/test/ui/error-codes/E0152.stderr +++ b/src/test/ui/error-codes/E0152.stderr @@ -4,7 +4,7 @@ error[E0152]: duplicate lang item found: `arc`. LL | struct Foo; | ^^^^^^^^^^^ | - = note: first defined in crate `alloc`. + = note: first defined in crate `alloc` (which `std` depends on). error: aborting due to previous error diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr index 322403111165..e6d24348ca82 100644 --- a/src/test/ui/panic-handler/panic-handler-std.stderr +++ b/src/test/ui/panic-handler/panic-handler-std.stderr @@ -6,7 +6,7 @@ LL | | loop {} LL | | } | |_^ | - = note: first defined in crate `std`. + = note: first defined in crate `std` (which `panic_handler_std` depends on). error: argument should be `&PanicInfo` --> $DIR/panic-handler-std.rs:7:16