Auto merge of #25323 - eddyb:coherent-coherence, r=pnkfelix

The loop to load all the known impls from external crates seems to have been used because `ty::populate_implementations_for_trait_if_necessary` wasn't doing its job, and solely relying on it resulted in loading only impls in the same crate as the trait.

Coherence for `librustc` was reduced from 18.310s to 0.610s, from stage1 to stage2.
Interestingly, type checking also went from 46.232s to 42.003s, though that could be noise or unrelated improvements.

On a smaller scale, `fn main() {}` now spends 0.003s in coherence instead of 0.368s, which fixes #22068.
It also peaks at only 1.2MB, instead of 16MB of heap usage.
This commit is contained in:
bors 2015-05-12 10:46:14 +00:00
commit 67dfc177f3
9 changed files with 148 additions and 244 deletions

View File

@ -189,6 +189,7 @@ pub const tag_item_impl_vtables: usize = 0x7e;
pub const tag_impls: usize = 0x109; // top-level only
pub const tag_impls_impl: usize = 0x7f;
pub const tag_impls_impl_trait_def_id: usize = 0x8d;
pub const tag_items_data_item_inherent_impl: usize = 0x80;
pub const tag_items_data_item_extension_impl: usize = 0x81;

View File

@ -304,31 +304,23 @@ pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
decoder::get_native_libraries(&*cdata)
}
pub fn each_impl<F>(cstore: &cstore::CStore,
crate_num: ast::CrateNum,
callback: F) where
F: FnMut(ast::DefId),
{
let cdata = cstore.get_crate_data(crate_num);
decoder::each_impl(&*cdata, callback)
}
pub fn each_implementation_for_type<F>(cstore: &cstore::CStore,
def_id: ast::DefId,
callback: F) where
pub fn each_inherent_implementation_for_type<F>(cstore: &cstore::CStore,
def_id: ast::DefId,
callback: F) where
F: FnMut(ast::DefId),
{
let cdata = cstore.get_crate_data(def_id.krate);
decoder::each_implementation_for_type(&*cdata, def_id.node, callback)
decoder::each_inherent_implementation_for_type(&*cdata, def_id.node, callback)
}
pub fn each_implementation_for_trait<F>(cstore: &cstore::CStore,
def_id: ast::DefId,
callback: F) where
mut callback: F) where
F: FnMut(ast::DefId),
{
let cdata = cstore.get_crate_data(def_id.krate);
decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
cstore.iter_crate_data(|_, cdata| {
decoder::each_implementation_for_trait(cdata, def_id, &mut callback)
})
}
/// If the given def ID describes an item belonging to a trait (either a

View File

@ -21,7 +21,8 @@ use metadata::common::*;
use metadata::csearch::MethodInfo;
use metadata::csearch;
use metadata::cstore;
use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id,
use metadata::encoder::def_to_u64;
use metadata::tydecode::{parse_ty_data, parse_region_data,
parse_type_param_def_data, parse_bare_fn_ty_data,
parse_trait_ref_data, parse_predicate_data};
use middle::def;
@ -190,29 +191,32 @@ fn item_symbol(item: rbml::Doc) -> String {
reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string()
}
fn item_parent_item(d: rbml::Doc) -> Option<ast::DefId> {
fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> ast::DefId {
let id = reader::doc_as_u64(d);
let def_id = ast::DefId { krate: (id >> 32) as u32, node: id as u32 };
translate_def_id(cdata, def_id)
}
fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option<ast::DefId> {
let mut ret = None;
reader::tagged_docs(d, tag_items_data_parent_item, |did| {
ret = Some(reader::with_doc_data(did, parse_def_id));
ret = Some(translated_def_id(cdata, did));
false
});
ret
}
fn item_reqd_and_translated_parent_item(cnum: ast::CrateNum,
d: rbml::Doc) -> ast::DefId {
let trait_did = item_parent_item(d).expect("item without parent");
ast::DefId { krate: cnum, node: trait_did.node }
fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> ast::DefId {
translated_def_id(cdata, reader::get_doc(d, tag_items_data_parent_item))
}
fn item_def_id(d: rbml::Doc, cdata: Cmd) -> ast::DefId {
let tagdoc = reader::get_doc(d, tag_def_id);
return translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
translated_def_id(cdata, reader::get_doc(d, tag_def_id))
}
fn get_provided_source(d: rbml::Doc, cdata: Cmd) -> Option<ast::DefId> {
reader::maybe_get_doc(d, tag_item_method_provided_source).map(|doc| {
translate_def_id(cdata, reader::with_doc_data(doc, parse_def_id))
translated_def_id(cdata, doc)
})
}
@ -261,14 +265,12 @@ fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
}
fn enum_variant_ids(item: rbml::Doc, cdata: Cmd) -> Vec<ast::DefId> {
let mut ids: Vec<ast::DefId> = Vec::new();
let v = tag_items_data_item_variant;
reader::tagged_docs(item, v, |p| {
let ext = reader::with_doc_data(p, parse_def_id);
ids.push(ast::DefId { krate: cdata.cnum, node: ext.node });
let mut ids = vec![];
reader::tagged_docs(item, tag_items_data_item_variant, |p| {
ids.push(translated_def_id(cdata, p));
true
});
return ids;
ids
}
fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
@ -303,8 +305,7 @@ fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
}
}
fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
-> DefLike {
fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: ast::DefId) -> DefLike {
let fam = item_family(item);
match fam {
Constant => {
@ -314,11 +315,9 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
// See the comment for methods below.
let provenance = if reader::maybe_get_doc(
item, tag_item_trait_parent_sort).is_some() {
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
item))
def::FromTrait(item_require_parent_item(cdata, item))
} else {
def::FromImpl(item_reqd_and_translated_parent_item(cnum,
item))
def::FromImpl(item_require_parent_item(cdata, item))
};
DlDef(def::DefAssociatedConst(did, provenance))
} else {
@ -339,17 +338,15 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
// a trait_parent_sort.
let provenance = if reader::maybe_get_doc(
item, tag_item_trait_parent_sort).is_some() {
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
item))
def::FromTrait(item_require_parent_item(cdata, item))
} else {
def::FromImpl(item_reqd_and_translated_parent_item(cnum,
item))
def::FromImpl(item_require_parent_item(cdata, item))
};
DlDef(def::DefMethod(did, provenance))
}
Type => {
if item_sort(item) == Some('t') {
let trait_did = item_reqd_and_translated_parent_item(cnum, item);
let trait_did = item_require_parent_item(cdata, item);
DlDef(def::DefAssociatedTy(trait_did, did))
} else {
DlDef(def::DefTy(did, false))
@ -358,11 +355,11 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
Mod => DlDef(def::DefMod(did)),
ForeignMod => DlDef(def::DefForeignMod(did)),
StructVariant => {
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
let enum_did = item_require_parent_item(cdata, item);
DlDef(def::DefVariant(enum_did, did, true))
}
TupleVariant => {
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
let enum_did = item_require_parent_item(cdata, item);
DlDef(def::DefVariant(enum_did, did, false))
}
Trait => DlDef(def::DefTrait(did)),
@ -560,9 +557,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
{
// Iterate over all children.
let _ = reader::tagged_docs(item_doc, tag_mod_child, |child_info_doc| {
let child_def_id = reader::with_doc_data(child_info_doc,
parse_def_id);
let child_def_id = translate_def_id(cdata, child_def_id);
let child_def_id = translated_def_id(cdata, child_info_doc);
// This item may be in yet another crate if it was the child of a
// reexport.
@ -584,9 +579,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
Some(child_item_doc) => {
// Hand off the item to the callback.
let child_name = item_name(&*intr, child_item_doc);
let def_like = item_to_def_like(child_item_doc,
child_def_id,
cdata.cnum);
let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
let visibility = item_visibility(child_item_doc);
callback(def_like, child_name, visibility);
@ -615,9 +608,8 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
if let StaticMethod = item_family(impl_method_doc) {
// Hand off the static method to the callback.
let static_method_name = item_name(&*intr, impl_method_doc);
let static_method_def_like = item_to_def_like(impl_method_doc,
impl_item_def_id,
cdata.cnum);
let static_method_def_like = item_to_def_like(cdata, impl_method_doc,
impl_item_def_id);
callback(static_method_def_like,
static_method_name,
item_visibility(impl_method_doc));
@ -633,9 +625,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
let _ = each_reexport(item_doc, |reexport_doc| {
let def_id_doc = reader::get_doc(reexport_doc,
tag_items_data_item_reexport_def_id);
let child_def_id = reader::with_doc_data(def_id_doc,
parse_def_id);
let child_def_id = translate_def_id(cdata, child_def_id);
let child_def_id = translated_def_id(cdata, def_id_doc);
let name_doc = reader::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
@ -657,9 +647,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
// Get the item.
if let Some(child_item_doc) = maybe_find_item(child_def_id.node, other_crates_items) {
// Hand off the item to the callback.
let def_like = item_to_def_like(child_item_doc,
child_def_id,
child_def_id.krate);
let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
// These items have a public visibility because they're part of
// a public re-export.
callback(def_like, token::intern(name), ast::Public);
@ -733,9 +721,8 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
match decode_inlined_item(cdata, tcx, path, item_doc) {
Ok(ii) => csearch::FoundAst::Found(ii),
Err(path) => {
match item_parent_item(item_doc) {
match item_parent_item(cdata, item_doc) {
Some(did) => {
let did = translate_def_id(cdata, did);
let parent_item = lookup_item(did.node, cdata.data());
match decode_inlined_item(cdata, tcx, path, parent_item) {
Ok(ii) => csearch::FoundAst::FoundParent(did, ii),
@ -759,7 +746,7 @@ pub fn get_enum_variant_defs(intr: &IdentInterner,
let item = find_item(did.node, items);
let name = item_name(intr, item);
let visibility = item_visibility(item);
match item_to_def_like(item, *did, cdata.cnum) {
match item_to_def_like(cdata, item, *did) {
DlDef(def @ def::DefVariant(..)) => (def, name, visibility),
_ => unreachable!()
}
@ -889,8 +876,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
let def_id = item_def_id(method_doc, cdata);
let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
method_doc);
let container_id = item_require_parent_item(cdata, method_doc);
let container_doc = lookup_item(container_id.node, cdata.data());
let container = match item_family(container_doc) {
Trait => TraitContainer(container_id),
@ -1094,7 +1080,7 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
let item = lookup_item(node_id, cdata.data());
let mut ret = None;
reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor, |_| {
ret = Some(item_reqd_and_translated_parent_item(cdata.cnum, item));
ret = Some(item_require_parent_item(cdata, item));
false
});
ret
@ -1144,7 +1130,7 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
let name = item_name(&*intr, an_item);
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
let origin_id = translated_def_id(cdata, tagdoc);
result.push(ty::field_ty {
name: name,
id: did,
@ -1158,7 +1144,7 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let f = item_family(an_item);
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
let origin_id = translated_def_id(cdata, tagdoc);
result.push(ty::field_ty {
name: special_idents::unnamed_field.name,
id: did,
@ -1342,55 +1328,77 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId {
}
}
pub fn each_impl<F>(cdata: Cmd, mut callback: F) where
F: FnMut(ast::DefId),
{
let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| {
callback(item_def_id(impl_doc, cdata));
true
});
// Translate a DefId from the current compilation environment to a DefId
// for an external crate.
fn reverse_translate_def_id(cdata: Cmd, did: ast::DefId) -> Option<ast::DefId> {
if did.krate == cdata.cnum {
return Some(ast::DefId { krate: ast::LOCAL_CRATE, node: did.node });
}
for (&local, &global) in &cdata.cnum_map {
if global == did.krate {
return Some(ast::DefId { krate: local, node: did.node });
}
}
None
}
pub fn each_implementation_for_type<F>(cdata: Cmd,
id: ast::NodeId,
mut callback: F)
pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
id: ast::NodeId,
mut callback: F)
where F: FnMut(ast::DefId),
{
let item_doc = lookup_item(id, cdata.data());
reader::tagged_docs(item_doc,
tag_items_data_item_inherent_impl,
|impl_doc| {
let implementation_def_id = item_def_id(impl_doc, cdata);
callback(implementation_def_id);
if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() {
callback(item_def_id(impl_doc, cdata));
}
true
});
}
pub fn each_implementation_for_trait<F>(cdata: Cmd,
id: ast::NodeId,
def_id: ast::DefId,
mut callback: F) where
F: FnMut(ast::DefId),
{
let item_doc = lookup_item(id, cdata.data());
if cdata.cnum == def_id.krate {
let item_doc = lookup_item(def_id.node, cdata.data());
let _ = reader::tagged_docs(item_doc,
tag_items_data_item_extension_impl,
|impl_doc| {
callback(item_def_id(impl_doc, cdata));
true
});
return;
}
let _ = reader::tagged_docs(item_doc,
tag_items_data_item_extension_impl,
|impl_doc| {
let implementation_def_id = item_def_id(impl_doc, cdata);
callback(implementation_def_id);
true
});
// Do a reverse lookup beforehand to avoid touching the crate_num
// hash map in the loop below.
if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) {
let def_id_u64 = def_to_u64(crate_local_did);
let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| {
let impl_trait = reader::get_doc(impl_doc, tag_impls_impl_trait_def_id);
if reader::doc_as_u64(impl_trait) == def_id_u64 {
callback(item_def_id(impl_doc, cdata));
}
true
});
}
}
pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
-> Option<ast::DefId> {
let item_doc = lookup_item(id, cdata.data());
let parent_item_id = match item_parent_item(item_doc) {
let parent_item_id = match item_parent_item(cdata, item_doc) {
None => return None,
Some(item_id) => item_id,
};
let parent_item_id = translate_def_id(cdata, parent_item_id);
let parent_item_doc = lookup_item(parent_item_id.node, cdata.data());
match item_family(parent_item_doc) {
Trait => Some(item_def_id(parent_item_doc, cdata)),
@ -1538,8 +1546,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
let name = item_name(&*token::get_ident_interner(), ident_str_doc);
let def_id_doc = reader::get_doc(rp_doc,
tag_region_param_def_def_id);
let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
let def_id = translate_def_id(cdata, def_id);
let def_id = translated_def_id(cdata, def_id_doc);
let doc = reader::get_doc(rp_doc, tag_region_param_def_space);
let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as usize);

View File

@ -91,8 +91,8 @@ fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Name) {
rbml_w.wr_tagged_str(tag_item_impl_type_basename, &token::get_name(name));
}
pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id));
fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
}
#[derive(Clone)]
@ -122,6 +122,10 @@ fn encode_family(rbml_w: &mut Encoder, c: char) {
rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
}
pub fn def_to_u64(did: DefId) -> u64 {
(did.krate as u64) << 32 | (did.node as u64)
}
pub fn def_to_string(did: DefId) -> String {
format!("{}:{}", did.krate, did.node)
}
@ -153,9 +157,9 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
}
fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
let s = def_to_string(vid);
rbml_w.wr_tagged_str(tag_items_data_item_variant, &s[..]);
rbml_w.wr_tagged_str(tag_mod_child, &s[..]);
let id = def_to_u64(vid);
rbml_w.wr_tagged_u64(tag_items_data_item_variant, id);
rbml_w.wr_tagged_u64(tag_mod_child, id);
}
pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
@ -260,7 +264,7 @@ fn encode_disr_val(_: &EncodeContext,
}
fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
rbml_w.wr_tagged_str(tag_items_data_parent_item, &def_to_string(id));
rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
}
fn encode_struct_fields(rbml_w: &mut Encoder,
@ -275,7 +279,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder,
}
encode_struct_field_family(rbml_w, f.vis);
encode_def_id(rbml_w, f.id);
rbml_w.wr_tagged_str(tag_item_field_origin, &def_to_string(origin));
rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin));
rbml_w.end_tag();
}
}
@ -358,8 +362,8 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder,
debug!("(encode reexported static method) {}::{}",
exp.name, token::get_name(method_name));
rbml_w.start_tag(tag_items_data_item_reexport);
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
&def_to_string(method_def_id));
rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
def_to_u64(method_def_id));
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
&format!("{}::{}", exp.name,
token::get_name(method_name)));
@ -495,8 +499,8 @@ fn encode_reexports(ecx: &EncodeContext,
exp.def_id.node,
id);
rbml_w.start_tag(tag_items_data_item_reexport);
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
&def_to_string(exp.def_id));
rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
def_to_u64(exp.def_id));
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
exp.name.as_str());
rbml_w.end_tag();
@ -526,12 +530,12 @@ fn encode_info_for_mod(ecx: &EncodeContext,
// Encode info about all the module children.
for item in &md.items {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(item.id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(item.id)));
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(auxiliary_node_id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(auxiliary_node_id)));
true
});
@ -541,8 +545,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
token::get_ident(ident),
did, ecx.tcx.map.node_to_string(did));
rbml_w.wr_tagged_str(tag_mod_impl,
&def_to_string(local_def(did)));
rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(local_def(did)));
}
}
@ -619,8 +622,7 @@ fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
fn encode_provided_source(rbml_w: &mut Encoder,
source_opt: Option<DefId>) {
if let Some(source) = source_opt {
rbml_w.wr_tagged_str(tag_item_method_provided_source,
&def_to_string(source));
rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source));
}
}
@ -725,8 +727,8 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
encode_name(rbml_w, param.name);
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_region_param_def_def_id,
&def_to_string(param.def_id));
rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
def_to_u64(param.def_id));
rbml_w.wr_tagged_u64(tag_region_param_def_space,
param.space.to_uint() as u64);
@ -1089,8 +1091,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
// Encode all the items in this module.
for foreign_item in &fm.items {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(foreign_item.id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(foreign_item.id)));
}
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
@ -1335,8 +1337,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(method_def_id.def_id()));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(method_def_id.def_id()));
}
encode_path(rbml_w, path.clone());
@ -1893,6 +1895,7 @@ impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
def_id.krate != ast::LOCAL_CRATE {
self.rbml_w.start_tag(tag_impls_impl);
encode_def_id(self.rbml_w, local_def(item.id));
self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id));
self.rbml_w.end_tag();
}
}
@ -1932,12 +1935,12 @@ fn encode_misc_info(ecx: &EncodeContext,
rbml_w.start_tag(tag_misc_info);
rbml_w.start_tag(tag_misc_info_crate_items);
for item in &krate.module.items {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(item.id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(item.id)));
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(auxiliary_node_id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(auxiliary_node_id)));
true
});
}

View File

@ -2564,9 +2564,11 @@ impl<'tcx> TraitDef<'tcx> {
tcx: &ctxt<'tcx>,
impl_def_id: DefId,
impl_trait_ref: TraitRef<'tcx>) {
debug!("TraitDef::record_impl for {}, from {}",
self.repr(tcx), impl_trait_ref.repr(tcx));
// We don't want to borrow_mut after we already populated all impls,
// so check if an impl is present with an immutable borrow first.
if let Some(sty) = fast_reject::simplify_type(tcx,
impl_trait_ref.self_ty(), false) {
if let Some(is) = self.nonblanket_impls.borrow().get(&sty) {
@ -6336,10 +6338,10 @@ pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt,
tcx.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
}
/// Populates the type context with all the implementations for the given type
/// if necessary.
pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
type_id: ast::DefId) {
/// Populates the type context with all the inherent implementations for
/// the given type if necessary.
pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt,
type_id: ast::DefId) {
if type_id.krate == LOCAL_CRATE {
return
}
@ -6348,37 +6350,15 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
return
}
debug!("populate_implementations_for_type_if_necessary: searching for {:?}", type_id);
debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", type_id);
let mut inherent_impls = Vec::new();
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
// Record the implementation, if needed
if let Some(trait_ref) = csearch::get_impl_trait(tcx, impl_def_id) {
let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
trait_def.record_impl(tcx, impl_def_id, trait_ref);
} else {
inherent_impls.push(impl_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for impl_item_def_id in &impl_items {
let method_def_id = impl_item_def_id.def_id();
match impl_or_trait_item(tcx, method_def_id) {
MethodTraitItem(method) => {
if let Some(source) = method.provided_source {
tcx.provided_method_sources
.borrow_mut()
.insert(method_def_id, source);
}
}
_ => {}
}
}
csearch::each_inherent_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
// Record the implementation.
inherent_impls.push(impl_def_id);
// Store the implementation info.
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
});
@ -6388,18 +6368,18 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
/// Populates the type context with all the implementations for the given
/// trait if necessary.
pub fn populate_implementations_for_trait_if_necessary(
tcx: &ctxt,
trait_id: ast::DefId) {
pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) {
if trait_id.krate == LOCAL_CRATE {
return
}
let def = lookup_trait_def(tcx, trait_id);
if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
return
return;
}
debug!("populate_implementations_for_trait_if_necessary: searching for {}", def.repr(tcx));
if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) {
record_trait_has_default_impl(tcx, trait_id);
}

View File

@ -371,7 +371,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) {
// Read the inherent implementation candidates for this type from the
// metadata if necessary.
ty::populate_implementations_for_type_if_necessary(self.tcx(), def_id);
ty::populate_inherent_implementations_for_type_if_necessary(self.tcx(), def_id);
if let Some(impl_infos) = self.tcx().inherent_impls.borrow().get(&def_id) {
for &impl_def_id in &***impl_infos {

View File

@ -16,13 +16,10 @@
// mappings. That mapping code resides here.
use metadata::csearch::{each_impl, get_impl_trait};
use metadata::csearch;
use middle::subst::{self, Subst};
use middle::ty::RegionEscape;
use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
use middle::ty::{MethodTraitItemId, TypeTraitItemId};
use middle::ty::{ParameterEnvironment, lookup_item_type};
use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
use middle::ty::{ty_param, TypeScheme, ty_ptr};
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
@ -33,7 +30,6 @@ use middle::ty;
use CrateCtxt;
use middle::infer::InferCtxt;
use middle::infer::new_infer_ctxt;
use std::collections::HashSet;
use std::cell::RefCell;
use std::rc::Rc;
use syntax::ast::{Crate, DefId};
@ -130,11 +126,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
Rc::new((*v.borrow()).clone()));
}
// Bring in external crates. It's fine for this to happen after the
// coherence checks, because we ensure by construction that no errors
// can happen at link time.
self.add_external_crates();
// Populate the table of destructors. It might seem a bit strange to
// do this here, but it's actually the most convenient place, since
// the coherence tables contain the trait -> type mappings.
@ -267,11 +258,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
trait_def.record_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref);
}
fn get_self_type_for_implementation(&self, impl_did: DefId)
-> TypeScheme<'tcx> {
self.crate_context.tcx.tcache.borrow().get(&impl_did).unwrap().clone()
}
// Converts an implementation in the AST to a vector of items.
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
match item.node {
@ -313,66 +299,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
}
}
// External crate handling
fn add_external_impl(&self,
impls_seen: &mut HashSet<DefId>,
impl_def_id: DefId) {
let tcx = self.crate_context.tcx;
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
impl_def_id);
// Make sure we don't visit the same implementation multiple times.
if !impls_seen.insert(impl_def_id) {
// Skip this one.
return
}
// Good. Continue.
let _ = lookup_item_type(tcx, impl_def_id);
let associated_traits = get_impl_trait(tcx, impl_def_id);
// Do a sanity check.
assert!(associated_traits.is_some());
// Record all the trait items.
if let Some(trait_ref) = associated_traits {
self.add_trait_impl(trait_ref, impl_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for item_def_id in &impl_items {
let impl_item = ty::impl_or_trait_item(tcx, item_def_id.def_id());
match impl_item {
ty::MethodTraitItem(ref method) => {
if let Some(source) = method.provided_source {
tcx.provided_method_sources
.borrow_mut()
.insert(item_def_id.def_id(), source);
}
}
_ => {}
}
}
tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
}
// Adds implementations and traits from external crates to the coherence
// info.
fn add_external_crates(&self) {
let mut impls_seen = HashSet::new();
let crate_store = &self.crate_context.tcx.sess.cstore;
crate_store.iter_crate_data(|crate_number, _crate_metadata| {
each_impl(crate_store, crate_number, |def_id| {
assert_eq!(crate_number, def_id.krate);
self.add_external_impl(&mut impls_seen, def_id)
})
})
}
//
// Destructors
//
@ -395,7 +321,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
}
let method_def_id = items[0];
let self_type = self.get_self_type_for_implementation(impl_did);
let self_type = ty::lookup_item_type(tcx, impl_did);
match self_type.ty.sty {
ty::ty_enum(type_def_id, _) |
ty::ty_struct(type_def_id, _) |
@ -451,7 +377,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
return
}
let self_type = self.get_self_type_for_implementation(impl_did);
let self_type = ty::lookup_item_type(tcx, impl_did);
debug!("check_implementations_of_copy: self_type={} (bound)",
self_type.repr(tcx));

View File

@ -48,14 +48,9 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
// check_for_overlapping_impls_of_trait() check, since that
// check can populate this table further with impls from other
// crates.
let trait_defs : Vec<&ty::TraitDef> = {
let d = self.tcx.trait_defs.borrow();
d.values().map(|&v|v).collect()
};
let trait_defs: Vec<_> = self.tcx.trait_defs.borrow().values().cloned().collect();
for trait_def in trait_defs {
// FIXME -- it seems like this method actually pushes
// duplicate impls onto the list
ty::populate_implementations_for_trait_if_necessary(
self.tcx,
trait_def.trait_ref.def_id);

View File

@ -221,7 +221,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
did: ast::DefId) -> Vec<clean::Item> {
ty::populate_implementations_for_type_if_necessary(tcx, did);
ty::populate_inherent_implementations_for_type_if_necessary(tcx, did);
let mut impls = Vec::new();
match tcx.inherent_impls.borrow().get(&did) {