rustc: remove ty::Impl.
This commit is contained in:
parent
8f3cfe064b
commit
1e5a112922
src/librustc
metadata
middle
@ -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 \
|
||||
|
Loading…
x
Reference in New Issue
Block a user