rustc: remove ty::Impl.

This commit is contained in:
Eduard Burtescu 2014-04-21 12:04:35 +03:00
parent 8f3cfe064b
commit 1e5a112922
9 changed files with 155 additions and 188 deletions

@ -114,10 +114,10 @@ pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
}
/// Returns information about the given implementation.
pub fn get_impl(tcx: &ty::ctxt, impl_def_id: ast::DefId)
-> ty::Impl {
let cdata = tcx.sess.cstore.get_crate_data(impl_def_id.krate);
decoder::get_impl(tcx.sess.cstore.intr.clone(), &*cdata, impl_def_id.node, tcx)
pub fn get_impl_methods(cstore: &cstore::CStore, impl_def_id: ast::DefId)
-> Vec<ast::DefId> {
let cdata = cstore.get_crate_data(impl_def_id.krate);
decoder::get_impl_methods(&*cdata, impl_def_id.node)
}
pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {

@ -733,32 +733,17 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
}
}
fn item_impl_methods(intr: Rc<IdentInterner>, cdata: Cmd, item: ebml::Doc,
tcx: &ty::ctxt) -> Vec<@ty::Method> {
let mut rslt = Vec::new();
reader::tagged_docs(item, tag_item_impl_method, |doc| {
/// Returns information about the given implementation.
pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
let mut methods = Vec::new();
reader::tagged_docs(lookup_item(impl_id, cdata.data()),
tag_item_impl_method, |doc| {
let m_did = reader::with_doc_data(doc, parse_def_id);
rslt.push(@get_method(intr.clone(), cdata, m_did.node, tcx));
methods.push(translate_def_id(cdata, m_did));
true
});
rslt
}
/// Returns information about the given implementation.
pub fn get_impl(intr: Rc<IdentInterner>, cdata: Cmd, impl_id: ast::NodeId,
tcx: &ty::ctxt)
-> ty::Impl {
let data = cdata.data();
let impl_item = lookup_item(impl_id, data);
ty::Impl {
did: ast::DefId {
krate: cdata.cnum,
node: impl_id,
},
ident: item_name(&*intr, impl_item),
methods: item_impl_methods(intr, cdata, impl_item, tcx),
}
methods
}
pub fn get_method_name_and_explicit_self(

@ -398,10 +398,12 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
ebml_w: &mut Encoder,
exp: &middle::resolve::Export2)
-> bool {
let impl_methods = ecx.tcx.impl_methods.borrow();
match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
Some(implementations) => {
for &base_impl in implementations.borrow().iter() {
for &m in base_impl.methods.iter() {
for base_impl_did in implementations.borrow().iter() {
for &method_did in impl_methods.get(base_impl_did).iter() {
let m = ty::method(ecx.tcx, method_did);
if m.explicit_self == ast::SelfStatic {
encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
}
@ -822,9 +824,9 @@ fn encode_inherent_implementations(ecx: &EncodeContext,
match ecx.tcx.inherent_impls.borrow().find(&def_id) {
None => {}
Some(implementations) => {
for implementation in implementations.borrow().iter() {
for &impl_def_id in implementations.borrow().iter() {
ebml_w.start_tag(tag_items_data_item_inherent_impl);
encode_def_id(ebml_w, implementation.did);
encode_def_id(ebml_w, impl_def_id);
ebml_w.end_tag();
}
}
@ -838,9 +840,9 @@ fn encode_extension_implementations(ecx: &EncodeContext,
match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
None => {}
Some(implementations) => {
for implementation in implementations.borrow().iter() {
for &impl_def_id in implementations.borrow().iter() {
ebml_w.start_tag(tag_items_data_item_extension_impl);
encode_def_id(ebml_w, implementation.did);
encode_def_id(ebml_w, impl_def_id);
ebml_w.end_tag();
}
}
@ -1028,8 +1030,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
// We need to encode information about the default methods we
// have inherited, so we drive this based on the impl structure.
let impls = tcx.impls.borrow();
let imp = impls.get(&def_id);
let impl_methods = tcx.impl_methods.borrow();
let methods = impl_methods.get(&def_id);
add_to_index(item, ebml_w, index);
ebml_w.start_tag(tag_items_data_item);
@ -1046,9 +1048,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
_ => {}
}
for method in imp.methods.iter() {
for &method_def_id in methods.iter() {
ebml_w.start_tag(tag_item_impl_method);
let s = def_to_str(method.def_id);
let s = def_to_str(method_def_id);
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
}
@ -1067,18 +1069,19 @@ fn encode_info_for_item(ecx: &EncodeContext,
// appear first in the impl structure, in the same order they do
// in the ast. This is a little sketchy.
let num_implemented_methods = ast_methods.len();
for (i, m) in imp.methods.iter().enumerate() {
for (i, &method_def_id) in methods.iter().enumerate() {
let ast_method = if i < num_implemented_methods {
Some(*ast_methods.get(i))
} else { None };
index.push(entry {
val: m.def_id.node as i64,
val: method_def_id.node as i64,
pos: ebml_w.writer.tell().unwrap(),
});
let m = ty::method(tcx, method_def_id);
encode_info_for_method(ecx,
ebml_w,
*m,
m,
path.clone(),
false,
item.id,

@ -336,13 +336,13 @@ impl<'a> DeadVisitor<'a> {
// This is done to handle the case where, for example, the static
// method of a private type is used, but the type itself is never
// called directly.
let def_id = local_def(id);
match self.tcx.inherent_impls.borrow().find(&def_id) {
let impl_methods = self.tcx.impl_methods.borrow();
match self.tcx.inherent_impls.borrow().find(&local_def(id)) {
None => (),
Some(impl_list) => {
for impl_ in impl_list.borrow().iter() {
for method in impl_.methods.iter() {
if self.live_symbols.contains(&method.def_id.node) {
for impl_did in impl_list.borrow().iter() {
for method_did in impl_methods.get(impl_did).iter() {
if self.live_symbols.contains(&method_did.node) {
return true;
}
}

@ -221,22 +221,22 @@ pub fn trans_static_method_callee(bcx: &Block,
}
}
pub fn method_with_name(ccx: &CrateContext,
impl_id: ast::DefId,
name: ast::Name) -> ast::DefId {
fn method_with_name(ccx: &CrateContext,
impl_id: ast::DefId,
name: ast::Name) -> ast::DefId {
match ccx.impl_method_cache.borrow().find_copy(&(impl_id, name)) {
Some(m) => return m,
None => {}
}
let imp = ccx.tcx.impls.borrow();
let imp = imp.find(&impl_id)
.expect("could not find impl while translating");
let meth = imp.methods.iter().find(|m| m.ident.name == name)
.expect("could not find method while translating");
let methods = ccx.tcx.impl_methods.borrow();
let methods = methods.find(&impl_id)
.expect("could not find impl while translating");
let meth_did = methods.iter().find(|&did| ty::method(&ccx.tcx, *did).ident.name == name)
.expect("could not find method while translating");
ccx.impl_method_cache.borrow_mut().insert((impl_id, name), meth.def_id);
meth.def_id
ccx.impl_method_cache.borrow_mut().insert((impl_id, name), *meth_did);
*meth_did
}
fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,

@ -116,12 +116,6 @@ impl Method {
}
}
pub struct Impl {
pub did: DefId,
pub ident: Ident,
pub methods: Vec<@Method>,
}
#[deriving(Clone, Eq, TotalEq, Hash)]
pub struct mt {
pub ty: t,
@ -320,18 +314,18 @@ pub struct ctxt {
pub destructors: RefCell<DefIdSet>,
// Maps a trait onto a list of impls of that trait.
pub trait_impls: RefCell<DefIdMap<@RefCell<Vec<@Impl>>>>,
pub trait_impls: RefCell<DefIdMap<@RefCell<Vec<ast::DefId>>>>,
// Maps a def_id of a type to a list of its inherent impls.
// Maps a DefId of a type to a list of its inherent impls.
// Contains implementations of methods that are inherent to a type.
// Methods in these implementations don't need to be exported.
pub inherent_impls: RefCell<DefIdMap<@RefCell<Vec<@Impl>>>>,
pub inherent_impls: RefCell<DefIdMap<@RefCell<Vec<ast::DefId>>>>,
// Maps a def_id of an impl to an Impl structure.
// Maps a DefId of an impl to a list of its methods.
// Note that this contains all of the impls that we know about,
// including ones in other crates. It's not clear that this is the best
// way to do it.
pub impls: RefCell<DefIdMap<@Impl>>,
pub impl_methods: RefCell<DefIdMap<Vec<ast::DefId>>>,
// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
// present in this set can be warned about.
@ -1126,7 +1120,7 @@ pub fn mk_ctxt(s: Session,
destructors: RefCell::new(DefIdSet::new()),
trait_impls: RefCell::new(DefIdMap::new()),
inherent_impls: RefCell::new(DefIdMap::new()),
impls: RefCell::new(DefIdMap::new()),
impl_methods: RefCell::new(DefIdMap::new()),
used_unsafe: RefCell::new(NodeSet::new()),
used_mut_nodes: RefCell::new(NodeSet::new()),
impl_vtables: RefCell::new(DefIdMap::new()),
@ -4384,15 +4378,15 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> @ItemVariances {
/// Records a trait-to-implementation mapping.
pub fn record_trait_implementation(tcx: &ctxt,
trait_def_id: DefId,
implementation: @Impl) {
impl_def_id: DefId) {
match tcx.trait_impls.borrow().find(&trait_def_id) {
Some(impls_for_trait) => {
impls_for_trait.borrow_mut().push(implementation);
impls_for_trait.borrow_mut().push(impl_def_id);
return;
}
None => {}
}
tcx.trait_impls.borrow_mut().insert(trait_def_id, @RefCell::new(vec!(implementation)));
tcx.trait_impls.borrow_mut().insert(trait_def_id, @RefCell::new(vec!(impl_def_id)));
}
/// Populates the type context with all the implementations for the given type
@ -4407,40 +4401,36 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
}
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
|implementation_def_id| {
let implementation = @csearch::get_impl(tcx, implementation_def_id);
|impl_def_id| {
let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
// Record the trait->implementation mappings, if applicable.
let associated_traits = csearch::get_impl_trait(tcx,
implementation.did);
let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
for trait_ref in associated_traits.iter() {
record_trait_implementation(tcx,
trait_ref.def_id,
implementation);
record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for method in implementation.methods.iter() {
for source in method.provided_source.iter() {
tcx.provided_method_sources.borrow_mut()
.insert(method.def_id, *source);
for &method_def_id in methods.iter() {
for &source in ty::method(tcx, method_def_id).provided_source.iter() {
tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
}
}
// Store the implementation info.
tcx.impls.borrow_mut().insert(implementation_def_id, implementation);
tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
// If this is an inherent implementation, record it.
if associated_traits.is_none() {
match tcx.inherent_impls.borrow().find(&type_id) {
Some(implementation_list) => {
implementation_list.borrow_mut().push(implementation);
implementation_list.borrow_mut().push(impl_def_id);
return;
}
None => {}
}
tcx.inherent_impls.borrow_mut().insert(type_id, @RefCell::new(vec!(implementation)));
tcx.inherent_impls.borrow_mut().insert(type_id, @RefCell::new(vec!(impl_def_id)));
}
});
@ -4461,22 +4451,21 @@ pub fn populate_implementations_for_trait_if_necessary(
csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
|implementation_def_id| {
let implementation = @csearch::get_impl(tcx, implementation_def_id);
let methods = csearch::get_impl_methods(&tcx.sess.cstore, implementation_def_id);
// Record the trait->implementation mapping.
record_trait_implementation(tcx, trait_id, implementation);
record_trait_implementation(tcx, trait_id, implementation_def_id);
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for method in implementation.methods.iter() {
for source in method.provided_source.iter() {
tcx.provided_method_sources.borrow_mut()
.insert(method.def_id, *source);
for &method_def_id in methods.iter() {
for &source in ty::method(tcx, method_def_id).provided_source.iter() {
tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
}
}
// Store the implementation info.
tcx.impls.borrow_mut().insert(implementation_def_id, implementation);
tcx.impl_methods.borrow_mut().insert(implementation_def_id, methods);
});
tcx.populated_external_traits.borrow_mut().insert(trait_id);

@ -468,9 +468,11 @@ impl<'a> LookupContext<'a> {
ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
// Look for explicit implementations.
let impl_methods = self.tcx().impl_methods.borrow();
for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
for impl_info in impl_infos.borrow().iter() {
self.push_candidates_from_impl(*impl_info, true);
for impl_did in impl_infos.borrow().iter() {
let methods = impl_methods.get(impl_did);
self.push_candidates_from_impl(*impl_did, methods.as_slice(), true);
}
}
}
@ -643,40 +645,35 @@ impl<'a> LookupContext<'a> {
// metadata if necessary.
ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
let impl_methods = self.tcx().impl_methods.borrow();
for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
for impl_info in impl_infos.borrow().iter() {
self.push_candidates_from_impl(*impl_info, false);
for impl_did in impl_infos.borrow().iter() {
let methods = impl_methods.get(impl_did);
self.push_candidates_from_impl(*impl_did, methods.as_slice(), false);
}
}
}
fn push_candidates_from_impl(&mut self,
impl_info: &ty::Impl,
impl_did: DefId,
impl_methods: &[DefId],
is_extension: bool) {
if !self.impl_dups.insert(impl_info.did) {
if !self.impl_dups.insert(impl_did) {
return; // already visited
}
debug!("push_candidates_from_impl: {} {} {}",
debug!("push_candidates_from_impl: {} {}",
token::get_name(self.m_name),
impl_info.ident.repr(self.tcx()),
impl_info.methods.iter()
.map(|m| m.ident)
.collect::<Vec<ast::Ident>>()
.repr(self.tcx()));
impl_methods.iter().map(|&did| ty::method(self.tcx(), did).ident)
.collect::<Vec<ast::Ident>>()
.repr(self.tcx()));
let idx = {
match impl_info.methods
.iter()
.position(|m| m.ident.name == self.m_name) {
Some(idx) => idx,
None => { return; } // No method with the right name.
}
let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did))
.find(|m| m.ident.name == self.m_name) {
Some(method) => method,
None => { return; } // No method with the right name.
};
let method = ty::method(self.tcx(),
impl_info.methods.get(idx).def_id);
// determine the `self` of the impl with fresh
// variables for each parameter:
let span = self.self_expr.map_or(self.span, |e| e.span);
@ -684,7 +681,7 @@ impl<'a> LookupContext<'a> {
let ty::ty_param_substs_and_ty {
substs: impl_substs,
ty: impl_ty
} = impl_self_ty(&vcx, span, impl_info.did);
} = impl_self_ty(&vcx, span, impl_did);
let candidates = if is_extension {
&mut self.extension_candidates

@ -325,21 +325,21 @@ fn search_for_vtable(vcx: &VtableContext,
}
};
// impls is the list of all impls in scope for trait_ref.
for im in impls.borrow().iter() {
for &impl_did in impls.borrow().iter() {
// im is one specific impl of trait_ref.
// First, ensure we haven't processed this impl yet.
if impls_seen.contains(&im.did) {
if impls_seen.contains(&impl_did) {
continue;
}
impls_seen.insert(im.did);
impls_seen.insert(impl_did);
// ty::impl_traits gives us the trait im implements.
//
// If foo implements a trait t, and if t is the same trait as
// trait_ref, we need to unify it with trait_ref in order to
// get all the ty vars sorted out.
let r = ty::impl_trait_ref(tcx, im.did);
let r = ty::impl_trait_ref(tcx, impl_did);
let of_trait_ref = r.expect("trait_ref missing on trait impl");
if of_trait_ref.def_id != trait_ref.def_id { continue; }
@ -362,7 +362,7 @@ fn search_for_vtable(vcx: &VtableContext,
let ty::ty_param_substs_and_ty {
substs: substs,
ty: for_ty
} = impl_self_ty(vcx, span, im.did);
} = impl_self_ty(vcx, span, impl_did);
match infer::mk_subty(vcx.infcx,
false,
infer::RelateSelfType(span),
@ -405,7 +405,7 @@ fn search_for_vtable(vcx: &VtableContext,
// type variables in substs. This might still be OK: the
// process of looking up bounds might constrain some of them.
let im_generics =
ty::lookup_item_type(tcx, im.did).generics;
ty::lookup_item_type(tcx, impl_did).generics;
let subres = lookup_vtables(vcx, span,
im_generics.type_param_defs(), &substs,
is_early);
@ -438,12 +438,12 @@ fn search_for_vtable(vcx: &VtableContext,
// I am a little confused about this, since it seems to be
// very similar to the relate_trait_refs we already do,
// but problems crop up if it is removed, so... -sully
connect_trait_tps(vcx, span, &substs_f, trait_ref, im.did);
connect_trait_tps(vcx, span, &substs_f, trait_ref, impl_did);
// Finally, we register that we found a matching impl, and
// record the def ID of the impl as well as the resolved list
// of type substitutions for the target trait.
found.push(vtable_static(im.did, substs_f.tps.clone(), subres));
found.push(vtable_static(impl_did, substs_f.tps.clone(), subres));
}
match found.len() {

@ -27,7 +27,6 @@ use middle::ty::{ty_uint, ty_uniq, ty_bare_fn, ty_closure};
use middle::ty::type_is_ty_var;
use middle::subst::Subst;
use middle::ty;
use middle::ty::{Impl, Method};
use middle::typeck::CrateCtxt;
use middle::typeck::infer::combine::Combine;
use middle::typeck::infer::InferCtxt;
@ -252,7 +251,8 @@ impl<'a> CoherenceChecker<'a> {
fn check_implementation(&self, item: &Item,
associated_traits: &[TraitRef]) {
let tcx = self.crate_context.tcx;
let self_type = ty::lookup_item_type(tcx, local_def(item.id));
let impl_did = local_def(item.id);
let self_type = ty::lookup_item_type(tcx, impl_did);
// If there are no traits, then this implementation must have a
// base type.
@ -276,7 +276,7 @@ impl<'a> CoherenceChecker<'a> {
}
}
let implementation = self.create_impl_from_item(item);
let impl_methods = self.create_impl_from_item(item);
for associated_trait in associated_traits.iter() {
let trait_ref = ty::node_id_to_trait_ref(
@ -285,7 +285,7 @@ impl<'a> CoherenceChecker<'a> {
trait_ref.repr(self.crate_context.tcx),
token::get_ident(item.ident));
self.add_trait_impl(trait_ref.def_id, implementation);
self.add_trait_impl(trait_ref.def_id, impl_did);
}
// Add the implementation to the mapping from implementation to base
@ -300,20 +300,20 @@ impl<'a> CoherenceChecker<'a> {
Some(base_type_def_id) => {
// FIXME: Gather up default methods?
if associated_traits.len() == 0 {
self.add_inherent_impl(base_type_def_id, implementation);
self.add_inherent_impl(base_type_def_id, impl_did);
}
}
}
tcx.impls.borrow_mut().insert(implementation.did, implementation);
tcx.impl_methods.borrow_mut().insert(impl_did, impl_methods);
}
// Creates default method IDs and performs type substitutions for an impl
// and trait pair. Then, for each provided method in the trait, inserts a
// `ProvidedMethodInfo` instance into the `provided_method_sources` map.
fn instantiate_default_methods(&self, impl_id: ast::DefId,
fn instantiate_default_methods(&self, impl_id: DefId,
trait_ref: &ty::TraitRef,
all_methods: &mut Vec<@Method> ) {
all_methods: &mut Vec<DefId>) {
let tcx = self.crate_context.tcx;
debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
impl_id, trait_ref.repr(tcx));
@ -339,7 +339,7 @@ impl<'a> CoherenceChecker<'a> {
Some(trait_method.def_id));
debug!("new_method_ty={}", new_method_ty.repr(tcx));
all_methods.push(new_method_ty);
all_methods.push(new_did);
// construct the polytype for the method based on the method_ty
let new_generics = ty::Generics {
@ -366,23 +366,23 @@ impl<'a> CoherenceChecker<'a> {
}
}
fn add_inherent_impl(&self, base_def_id: DefId, implementation: @Impl) {
fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
let tcx = self.crate_context.tcx;
match tcx.inherent_impls.borrow().find(&base_def_id) {
Some(implementation_list) => {
implementation_list.borrow_mut().push(implementation);
implementation_list.borrow_mut().push(impl_def_id);
return;
}
None => {}
}
tcx.inherent_impls.borrow_mut().insert(base_def_id, @RefCell::new(vec!(implementation)));
tcx.inherent_impls.borrow_mut().insert(base_def_id, @RefCell::new(vec!(impl_def_id)));
}
fn add_trait_impl(&self, base_def_id: DefId, implementation: @Impl) {
fn add_trait_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
ty::record_trait_implementation(self.crate_context.tcx,
base_def_id,
implementation);
impl_def_id);
}
fn check_implementation_coherence(&self) {
@ -393,34 +393,32 @@ impl<'a> CoherenceChecker<'a> {
fn check_implementation_coherence_of(&self, trait_def_id: DefId) {
// Unify pairs of polytypes.
self.iter_impls_of_trait_local(trait_def_id, |a| {
let implementation_a = a;
self.iter_impls_of_trait_local(trait_def_id, |impl_a| {
let polytype_a =
self.get_self_type_for_implementation(implementation_a);
self.get_self_type_for_implementation(impl_a);
// "We have an impl of trait <trait_def_id> for type <polytype_a>,
// and that impl is <implementation_a>"
self.iter_impls_of_trait(trait_def_id, |b| {
let implementation_b = b;
// and that impl is <impl_a>"
self.iter_impls_of_trait(trait_def_id, |impl_b| {
// An impl is coherent with itself
if a.did != b.did {
if impl_a != impl_b {
let polytype_b = self.get_self_type_for_implementation(
implementation_b);
impl_b);
if self.polytypes_unify(polytype_a.clone(), polytype_b) {
let session = &self.crate_context.tcx.sess;
session.span_err(
self.span_of_impl(implementation_a),
self.span_of_impl(impl_a),
format!("conflicting implementations for trait `{}`",
ty::item_path_str(self.crate_context.tcx,
trait_def_id)));
if implementation_b.did.krate == LOCAL_CRATE {
session.span_note(self.span_of_impl(implementation_b),
if impl_b.krate == LOCAL_CRATE {
session.span_note(self.span_of_impl(impl_b),
"note conflicting implementation here");
} else {
let crate_store = &self.crate_context.tcx.sess.cstore;
let cdata = crate_store.get_crate_data(implementation_b.did.krate);
let cdata = crate_store.get_crate_data(impl_b.krate);
session.note(
"conflicting implementation in crate `" + cdata.name + "`");
}
@ -430,7 +428,7 @@ impl<'a> CoherenceChecker<'a> {
})
}
fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |@Impl|) {
fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |DefId|) {
self.iter_impls_of_trait_local(trait_def_id, |x| f(x));
if trait_def_id.krate == LOCAL_CRATE {
@ -439,17 +437,17 @@ impl<'a> CoherenceChecker<'a> {
let crate_store = &self.crate_context.tcx.sess.cstore;
csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| {
let implementation = @csearch::get_impl(self.crate_context.tcx, impl_def_id);
let _ = lookup_item_type(self.crate_context.tcx, implementation.did);
f(implementation);
// Is this actually necessary?
let _ = lookup_item_type(self.crate_context.tcx, impl_def_id);
f(impl_def_id);
});
}
fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |@Impl|) {
fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |DefId|) {
match self.crate_context.tcx.trait_impls.borrow().find(&trait_def_id) {
Some(impls) => {
for &im in impls.borrow().iter() {
f(im);
for &impl_did in impls.borrow().iter() {
f(impl_did);
}
}
None => { /* no impls? */ }
@ -509,9 +507,9 @@ impl<'a> CoherenceChecker<'a> {
b.monotype).is_ok()
}
fn get_self_type_for_implementation(&self, implementation: @Impl)
fn get_self_type_for_implementation(&self, impl_did: DefId)
-> ty_param_bounds_and_ty {
self.crate_context.tcx.tcache.borrow().get_copy(&implementation.did)
self.crate_context.tcx.tcache.borrow().get_copy(&impl_did)
}
// Privileged scope checking
@ -563,15 +561,13 @@ impl<'a> CoherenceChecker<'a> {
}
}
// Converts an implementation in the AST to an Impl structure.
fn create_impl_from_item(&self, item: &Item) -> @Impl {
let tcx = self.crate_context.tcx;
// Converts an implementation in the AST to a vector of methods.
fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
match item.node {
ItemImpl(_, ref trait_refs, _, ref ast_methods) => {
let mut methods = Vec::new();
for ast_method in ast_methods.iter() {
methods.push(ty::method(tcx, local_def(ast_method.id)));
}
let mut methods: Vec<DefId> = ast_methods.iter().map(|ast_method| {
local_def(ast_method.id)
}).collect();
for trait_ref in trait_refs.iter() {
let ty_trait_ref = ty::node_id_to_trait_ref(
@ -583,11 +579,7 @@ impl<'a> CoherenceChecker<'a> {
&mut methods);
}
return @Impl {
did: local_def(item.id),
ident: item.ident,
methods: methods
};
methods
}
_ => {
self.crate_context.tcx.sess.span_bug(item.span,
@ -596,9 +588,9 @@ impl<'a> CoherenceChecker<'a> {
}
}
fn span_of_impl(&self, implementation: @Impl) -> Span {
assert_eq!(implementation.did.krate, LOCAL_CRATE);
self.crate_context.tcx.map.span(implementation.did.node)
fn span_of_impl(&self, impl_did: DefId) -> Span {
assert_eq!(impl_did.krate, LOCAL_CRATE);
self.crate_context.tcx.map.span(impl_did.node)
}
// External crate handling
@ -607,36 +599,35 @@ impl<'a> CoherenceChecker<'a> {
impls_seen: &mut HashSet<DefId>,
impl_def_id: DefId) {
let tcx = self.crate_context.tcx;
let implementation = @csearch::get_impl(tcx, impl_def_id);
let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
// Make sure we don't visit the same implementation multiple times.
if !impls_seen.insert(implementation.did) {
if !impls_seen.insert(impl_def_id) {
// Skip this one.
return
}
// Good. Continue.
let _ = lookup_item_type(tcx, implementation.did);
let associated_traits = get_impl_trait(tcx, implementation.did);
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 methods.
for trait_ref in associated_traits.iter() {
self.add_trait_impl(trait_ref.def_id, implementation);
self.add_trait_impl(trait_ref.def_id, impl_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for method in implementation.methods.iter() {
for source in method.provided_source.iter() {
tcx.provided_method_sources.borrow_mut()
.insert(method.def_id, *source);
for &method_def_id in methods.iter() {
for &source in ty::method(tcx, method_def_id).provided_source.iter() {
tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
}
}
tcx.impls.borrow_mut().insert(implementation.did, implementation);
tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
}
// Adds implementations and traits from external crates to the coherence
@ -663,19 +654,21 @@ impl<'a> CoherenceChecker<'a> {
Some(id) => id, None => { return }
};
let impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
let impl_methods = tcx.impl_methods.borrow();
let trait_impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
None => return, // No types with (new-style) dtors present.
Some(found_impls) => found_impls
};
for impl_info in impls.borrow().iter() {
if impl_info.methods.len() < 1 {
for &impl_did in trait_impls.borrow().iter() {
let methods = impl_methods.get(&impl_did);
if methods.len() < 1 {
// We'll error out later. For now, just don't ICE.
continue;
}
let method_def_id = impl_info.methods.get(0).def_id;
let method_def_id = *methods.get(0);
let self_type = self.get_self_type_for_implementation(*impl_info);
let self_type = self.get_self_type_for_implementation(impl_did);
match ty::get(self_type.ty).sty {
ty::ty_enum(type_def_id, _) |
ty::ty_struct(type_def_id, _) => {
@ -685,9 +678,9 @@ impl<'a> CoherenceChecker<'a> {
}
_ => {
// Destructors only work on nominal types.
if impl_info.did.krate == ast::LOCAL_CRATE {
if impl_did.krate == ast::LOCAL_CRATE {
{
match tcx.map.find(impl_info.did.node) {
match tcx.map.find(impl_did.node) {
Some(ast_map::NodeItem(item)) => {
tcx.sess.span_err((*item).span,
"the Drop trait may \