Skip to content

diagnostics: make paths to external items more visible #32439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 31, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ use mir::repr::Mir;
use mir::mir_map::MirMap;
use session::Session;
use session::search_paths::PathKind;
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
use util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
use std::any::Any;
use std::cell::RefCell;
use std::rc::Rc;
@@ -169,6 +169,7 @@ pub trait CrateStore<'tcx> : Any {
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::TypeScheme<'tcx>;
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>;
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
fn item_name(&self, def: DefId) -> ast::Name;
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
@@ -347,6 +348,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::TypeScheme<'tcx> { unimplemented!() }
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
unimplemented!()
}
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
fn item_name(&self, def: DefId) -> ast::Name { unimplemented!() }
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
44 changes: 43 additions & 1 deletion src/librustc/ty/item_path.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@

use front::map::DefPathData;
use middle::cstore::LOCAL_CRATE;
use middle::def_id::DefId;
use middle::def_id::{DefId, CRATE_DEF_INDEX};
use ty::{self, Ty, TyCtxt};
use syntax::ast;

@@ -75,9 +75,51 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

/// If possible, this pushes a global path resolving to `external_def_id` that is visible
/// from at least one local module and returns true. If the crate defining `external_def_id` is
/// declared with an `extern crate`, the path is guarenteed to use the `extern crate`.
pub fn try_push_visible_item_path<T>(&self, buffer: &mut T, external_def_id: DefId) -> bool
where T: ItemPathBuffer
{
let visible_parent_map = self.sess.cstore.visible_parent_map();

let (mut cur_def, mut cur_path) = (external_def_id, Vec::<ast::Name>::new());
loop {
// If `cur_def` is a direct or injected extern crate, push the path to the crate
// followed by the path to the item within the crate and return.
if cur_def.index == CRATE_DEF_INDEX {
match self.sess.cstore.extern_crate(cur_def.krate) {
Some(extern_crate) if extern_crate.direct => {
self.push_item_path(buffer, extern_crate.def_id);
cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count();
return true;
}
None => {
buffer.push(&self.crate_name(cur_def.krate));
cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count();
return true;
}
_ => {},
}
}

cur_path.push(self.sess.cstore.item_name(cur_def));
match visible_parent_map.get(&cur_def) {
Some(&def) => cur_def = def,
None => return false,
};
}
}

pub fn push_item_path<T>(&self, buffer: &mut T, def_id: DefId)
where T: ItemPathBuffer
{
match *buffer.root_mode() {
RootMode::Local if !def_id.is_local() =>
if self.try_push_visible_item_path(buffer, def_id) { return },
_ => {}
}

let key = self.def_key(def_id);
match key.disambiguated_data.data {
DefPathData::CrateRoot => {
62 changes: 59 additions & 3 deletions src/librustc_metadata/csearch.rs
Original file line number Diff line number Diff line change
@@ -13,17 +13,17 @@ use decoder;
use encoder;
use loader;

use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst};
use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst, DefLike};
use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
use middle::def;
use middle::lang_items;
use rustc::ty::{self, Ty, TyCtxt, VariantKind};
use middle::def_id::{DefId, DefIndex};
use middle::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};

use rustc::front::map as hir_map;
use rustc::mir::repr::Mir;
use rustc::mir::mir_map::MirMap;
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};

use std::cell::RefCell;
use std::rc::Rc;
@@ -544,4 +544,60 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
{
encoder::metadata_encoding_version
}

/// Returns a map from a sufficiently visible external item (i.e. an external item that is
/// visible from at least one local module) to a sufficiently visible parent (considering
/// modules that re-export the external item to be parents).
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
let mut visible_parent_map = self.visible_parent_map.borrow_mut();
if !visible_parent_map.is_empty() { return visible_parent_map; }

use rustc_front::hir;
use rustc::middle::cstore::{CrateStore, ChildItem};
use std::collections::vec_deque::VecDeque;
use std::collections::hash_map::Entry;
for cnum in 1 .. self.next_crate_num() {
let cdata = self.get_crate_data(cnum);

match cdata.extern_crate.get() {
// Ignore crates without a corresponding local `extern crate` item.
Some(extern_crate) if !extern_crate.direct => continue,
_ => {},
}

let mut bfs_queue = &mut VecDeque::new();
let mut add_child = |bfs_queue: &mut VecDeque<_>, child: ChildItem, parent: DefId| {
let child = match child.def {
DefLike::DlDef(def) if child.vis == hir::Public => def.def_id(),
_ => return,
};

match visible_parent_map.entry(child) {
Entry::Occupied(mut entry) => {
// If `child` is defined in crate `cnum`, ensure
// that it is mapped to a parent in `cnum`.
if child.krate == cnum && entry.get().krate != cnum {
entry.insert(parent);
}
}
Entry::Vacant(entry) => {
entry.insert(parent);
bfs_queue.push_back(child);
}
}
};

let croot = DefId { krate: cnum, index: CRATE_DEF_INDEX };
for child in self.crate_top_level_items(cnum) {
add_child(bfs_queue, child, croot);
}
while let Some(def) = bfs_queue.pop_front() {
for child in self.item_children(def) {
add_child(bfs_queue, child, def);
}
}
}

visible_parent_map
}
}
5 changes: 4 additions & 1 deletion src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,8 @@ use loader;

use rustc::back::svh::Svh;
use rustc::middle::cstore::{ExternCrate};
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
use rustc::middle::def_id::DefId;

use std::cell::{RefCell, Ref, Cell};
use std::rc::Rc;
@@ -92,6 +93,7 @@ pub struct CStore {
used_link_args: RefCell<Vec<String>>,
statically_included_foreign_items: RefCell<NodeSet>,
pub intr: Rc<IdentInterner>,
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
}

impl CStore {
@@ -104,6 +106,7 @@ impl CStore {
used_link_args: RefCell::new(Vec::new()),
intr: intr,
statically_included_foreign_items: RefCell::new(NodeSet()),
visible_parent_map: RefCell::new(FnvHashMap()),
}
}

2 changes: 1 addition & 1 deletion src/test/compile-fail/associated-types-unsized.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ trait Get {
}

fn foo<T:Get>(t: T) {
let x = t.get(); //~ ERROR the trait `core::marker::Sized` is not implemented
let x = t.get(); //~ ERROR the trait `std::marker::Sized` is not implemented
}

fn main() {
4 changes: 2 additions & 2 deletions src/test/compile-fail/bad-const-type.rs
Original file line number Diff line number Diff line change
@@ -10,8 +10,8 @@

static i: String = 10;
//~^ ERROR mismatched types
//~| expected `collections::string::String`
//~| expected `std::string::String`
//~| found `_`
//~| expected struct `collections::string::String`
//~| expected struct `std::string::String`
//~| found integral variable
fn main() { println!("{}", i); }
2 changes: 1 addition & 1 deletion src/test/compile-fail/bad-method-typaram-kind.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
// except according to those terms.

fn foo<T:'static>() {
1.bar::<T>(); //~ ERROR `core::marker::Send` is not implemented
1.bar::<T>(); //~ ERROR `std::marker::Send` is not implemented
}

trait bar {
6 changes: 3 additions & 3 deletions src/test/compile-fail/bad-sized.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ trait Trait {}

pub fn main() {
let x: Vec<Trait + Sized> = Vec::new();
//~^ ERROR the trait `core::marker::Sized` is not implemented
//~| ERROR the trait `core::marker::Sized` is not implemented
//~| ERROR the trait `core::marker::Sized` is not implemented
//~^ ERROR the trait `std::marker::Sized` is not implemented
//~| ERROR the trait `std::marker::Sized` is not implemented
//~| ERROR the trait `std::marker::Sized` is not implemented
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/binop-bitxor-str.rs
Original file line number Diff line number Diff line change
@@ -8,6 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern:`^` cannot be applied to type `collections::string::String`
// error-pattern:`^` cannot be applied to type `std::string::String`

fn main() { let x = "a".to_string() ^ "b".to_string(); }
4 changes: 2 additions & 2 deletions src/test/compile-fail/builtin-superkinds-double-superkind.rs
Original file line number Diff line number Diff line change
@@ -13,9 +13,9 @@

trait Foo : Send+Sync { }

impl <T: Sync+'static> Foo for (T,) { } //~ ERROR the trait `core::marker::Send` is not implemented
impl <T: Sync+'static> Foo for (T,) { } //~ ERROR the trait `std::marker::Send` is not implemented

impl <T: Send> Foo for (T,T) { } //~ ERROR the trait `core::marker::Sync` is not implemented
impl <T: Send> Foo for (T,T) { } //~ ERROR the trait `std::marker::Sync` is not implemented

impl <T: Send+Sync> Foo for (T,T,T) { } // (ok)

2 changes: 1 addition & 1 deletion src/test/compile-fail/builtin-superkinds-in-metadata.rs
Original file line number Diff line number Diff line change
@@ -22,6 +22,6 @@ struct X<T>(T);
impl <T:Sync> RequiresShare for X<T> { }

impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { }
//~^ ERROR the trait `core::marker::Send` is not implemented
//~^ ERROR the trait `std::marker::Send` is not implemented

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/builtin-superkinds-simple.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,6 @@
trait Foo : Send { }

impl Foo for std::rc::Rc<i8> { }
//~^ ERROR the trait `core::marker::Send` is not implemented
//~^ ERROR the trait `std::marker::Send` is not implemented

fn main() { }
Original file line number Diff line number Diff line change
@@ -12,6 +12,6 @@

trait Foo : Send { }

impl <T: Sync+'static> Foo for T { } //~ ERROR the trait `core::marker::Send` is not implemented
impl <T: Sync+'static> Foo for T { } //~ ERROR the trait `std::marker::Send` is not implemented

fn main() { }
4 changes: 2 additions & 2 deletions src/test/compile-fail/cast-rfc0401.rs
Original file line number Diff line number Diff line change
@@ -91,7 +91,7 @@ fn main()
let _ = 42usize as *const [u8]; //~ ERROR casting
let _ = v as *const [u8]; //~ ERROR cannot cast
let _ = fat_v as *const Foo;
//~^ ERROR `core::marker::Sized` is not implemented for the type `[u8]`
//~^ ERROR `std::marker::Sized` is not implemented for the type `[u8]`
//~^^ HELP run `rustc --explain E0277` to see a detailed explanation
//~^^^ NOTE `[u8]` does not have a constant size known at compile-time
//~^^^^ NOTE required for the cast to the object type `Foo`
@@ -106,7 +106,7 @@ fn main()

let a : *const str = "hello";
let _ = a as *const Foo;
//~^ ERROR `core::marker::Sized` is not implemented for the type `str`
//~^ ERROR `std::marker::Sized` is not implemented for the type `str`
//~^^ HELP run `rustc --explain E0277` to see a detailed explanation
//~^^^ NOTE `str` does not have a constant size known at compile-time
//~^^^^ NOTE required for the cast to the object type `Foo`
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ struct X<F> where F: FnOnce() + 'static + Send {
}

fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
//~^ ERROR the trait `core::marker::Send` is not implemented for the type
//~^ ERROR the trait `std::marker::Send` is not implemented for the type
return X { field: blk };
}

2 changes: 1 addition & 1 deletion src/test/compile-fail/closure-bounds-subtype.rs
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ fn give_any<F>(f: F) where F: FnOnce() {

fn give_owned<F>(f: F) where F: FnOnce() + Send {
take_any(f);
take_const_owned(f); //~ ERROR the trait `core::marker::Sync` is not implemented for the type
take_const_owned(f); //~ ERROR the trait `std::marker::Sync` is not implemented for the type
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -17,10 +17,10 @@ struct TestType<T>(::std::marker::PhantomData<T>);
unsafe impl<T: MyTrait+'static> Send for TestType<T> {}

impl<T: MyTrait> !Send for TestType<T> {}
//~^ ERROR conflicting implementations of trait `core::marker::Send`
//~^ ERROR conflicting implementations of trait `std::marker::Send`

unsafe impl<T:'static> Send for TestType<T> {}
//~^ ERROR error: conflicting implementations of trait `core::marker::Send`
//~^ ERROR error: conflicting implementations of trait `std::marker::Send`

impl !Send for TestType<i32> {}

Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ struct E {
#[derive(Clone)]
struct C {
x: NoCloneOrEq
//~^ ERROR the trait `core::clone::Clone` is not implemented for the type `NoCloneOrEq`
//~^ ERROR the trait `std::clone::Clone` is not implemented for the type `NoCloneOrEq`
}


2 changes: 1 addition & 1 deletion src/test/compile-fail/deriving-span-Default-struct.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ struct Error;

#[derive(Default)]
struct Struct {
x: Error //~ ERROR `core::default::Default` is not implemented
x: Error //~ ERROR `std::default::Default` is not implemented
}

fn main() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/destructure-trait-ref.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ fn main() {
// n == m
let &x = &1isize as &T; //~ ERROR type `&T` cannot be dereferenced
let &&x = &(&1isize as &T); //~ ERROR type `&T` cannot be dereferenced
let box x = box 1isize as Box<T>; //~ ERROR the trait `core::marker::Sized` is not implemented
let box x = box 1isize as Box<T>; //~ ERROR the trait `std::marker::Sized` is not implemented

// n > m
let &&x = &1isize as &T;
4 changes: 2 additions & 2 deletions src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs
Original file line number Diff line number Diff line change
@@ -39,8 +39,8 @@ enum Wrapper<T:'static> {
}

fn main() {
let w = //~ ERROR overflow while adding drop-check rules for core::option
let w = //~ ERROR overflow while adding drop-check rules for std::option
Some(Wrapper::Simple::<u32>);
//~^ ERROR overflow while adding drop-check rules for core::option::Option
//~^ ERROR overflow while adding drop-check rules for std::option::Option
//~| ERROR overflow while adding drop-check rules for Wrapper
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/dst-bad-assign-2.rs
Original file line number Diff line number Diff line change
@@ -44,5 +44,5 @@ pub fn main() {
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = *z;
//~^ ERROR the trait `core::marker::Sized` is not implemented
//~^ ERROR the trait `std::marker::Sized` is not implemented
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/dst-bad-assign.rs
Original file line number Diff line number Diff line change
@@ -49,5 +49,5 @@ pub fn main() {
//~| found `Bar1`
//~| expected trait ToBar
//~| found struct `Bar1`
//~| ERROR the trait `core::marker::Sized` is not implemented for the type `ToBar`
//~| ERROR the trait `std::marker::Sized` is not implemented for the type `ToBar`
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/dst-bad-deep.rs
Original file line number Diff line number Diff line change
@@ -21,5 +21,5 @@ pub fn main() {
let f: Fat<[isize; 3]> = Fat { ptr: [5, 6, 7] };
let g: &Fat<[isize]> = &f;
let h: &Fat<Fat<[isize]>> = &Fat { ptr: *g };
//~^ ERROR the trait `core::marker::Sized` is not implemented
//~^ ERROR the trait `std::marker::Sized` is not implemented
}
Loading