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:
parent
59367b074f
commit
ac9aed56e4
8 changed files with 50 additions and 18 deletions
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
..
|
||||
}) => {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue