1
Fork 0

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

View file

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

View file

@ -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, /// Returns information about the given implementation.
tcx: &ty::ctxt) -> Vec<@ty::Method> { pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
let mut rslt = Vec::new(); let mut methods = Vec::new();
reader::tagged_docs(item, tag_item_impl_method, |doc| { 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); 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 true
}); });
rslt methods
}
/// 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),
}
} }
pub fn get_method_name_and_explicit_self( pub fn get_method_name_and_explicit_self(

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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