diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index de84fcd7160df..ddf6262b7382e 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 c5d9a722ae18e..cab929389d6a4 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 2bc87d6b8ba5e..fe0d0fad3a565 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 af41b6a4c857f..91b9f38ebce1f 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 11121ee875dda..0cca4dfa4c5ef 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 1892ad38a594b..02be11d1fd0e5 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 26e6e2e1bce7e..d4b59a1148e60 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 3224031111650..e6d24348ca825 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