Rollup merge of #64678 - tomtau:fix/no-std-error, r=matthewjasper
added more context for duplicate lang item errors (fixes #60561) Some more information about #60561 -- these errors are pretty common when one works in restrictive environments with `no_std` or customized `std`, but they don't provide much context for debugging, as any transitive dependency could have brought in `std` crate. With that, currently, one needs to use something like `cargo tree` and investigate transitive dependencies one by one. It'll be more helpful to know at least the crate that uses `std` (which `cargo tree` doesn't show) to pin down this investigation when debugging. I'm not sure what the best way to get this context is inside rustc internals (I'm new to them). I found that `all_crate_nums` query returns the crates in some dependency order, so printing out the name of the preceding crate seems to do the trick. But I welcome suggestions if this can be done in a better way.
This commit is contained in:
commit
05881d046e
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
Reference in a new issue