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.
This commit is contained in:
Tomas Tauber 2019-09-27 21:32:04 +08:00
parent 59367b074f
commit ac9aed56e4
8 changed files with 50 additions and 18 deletions

View file

@ -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)]

View file

@ -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();
}

View file

@ -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,
..
}) => {

View file

@ -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(),
);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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