rustc: Make coherence aware of multiple-traits-per-impl

This commit is contained in:
Patrick Walton 2012-07-18 17:07:56 -07:00
parent 5506bf1480
commit 635a959363

View file

@ -111,6 +111,7 @@ fn get_base_type_def_id(inference_context: infer_ctxt,
class CoherenceInfo { class CoherenceInfo {
// 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.
let inherent_methods: hashmap<def_id,@dvec<@Impl>>; let inherent_methods: hashmap<def_id,@dvec<@Impl>>;
// Contains implementations of methods associated with a trait. For these, // Contains implementations of methods associated with a trait. For these,
@ -129,14 +130,17 @@ class CoherenceChecker {
// A mapping from implementations to the corresponding base type // A mapping from implementations to the corresponding base type
// definition ID. // definition ID.
let base_type_def_ids: hashmap<def_id,def_id>; let base_type_def_ids: hashmap<def_id,def_id>;
// A set of implementations in privileged scopes; i.e. those // A set of implementations in privileged scopes; i.e. those
// implementations that are defined in the same scope as their base types. // implementations that are defined in the same scope as their base types.
let privileged_implementations: hashmap<node_id,()>; let privileged_implementations: hashmap<node_id,()>;
// The set of types that we are currently in the privileged scope of. This // The set of types that we are currently in the privileged scope of. This
// is used while we traverse the AST while checking privileged scopes. // is used while we traverse the AST while checking privileged scopes.
let privileged_types: hashmap<def_id,()>; let privileged_types: hashmap<def_id,()>;
new(crate_context: @crate_ctxt) { new(crate_context: @crate_ctxt) {
@ -158,17 +162,7 @@ class CoherenceChecker {
alt item.node { alt item.node {
item_impl(_, associated_traits, self_type, _) { item_impl(_, associated_traits, self_type, _) {
// XXX: Accept an array of traits. self.check_implementation(item, associated_traits);
let optional_associated_trait;
if associated_traits.len() == 0 {
optional_associated_trait = none;
} else {
optional_associated_trait =
some(associated_traits[0]);
}
self.check_implementation(item,
optional_associated_trait);
} }
_ { _ {
// Nothing to do. // Nothing to do.
@ -195,14 +189,15 @@ class CoherenceChecker {
self.add_external_crates(); self.add_external_crates();
} }
fn check_implementation(item: @item, fn check_implementation(item: @item, associated_traits: ~[@trait_ref]) {
optional_associated_trait: option<@trait_ref>) {
let self_type = self.crate_context.tcx.tcache.get(local_def(item.id)); let self_type = self.crate_context.tcx.tcache.get(local_def(item.id));
alt optional_associated_trait {
none { // If there are no traits, then this implementation must have a
#debug("(checking implementation) no associated trait for \ // base type.
item '%s'",
if associated_traits.len() == 0 {
#debug("(checking implementation) no associated traits for item \
'%s'",
*item.ident); *item.ident);
alt get_base_type_def_id(self.inference_context, alt get_base_type_def_id(self.inference_context,
@ -220,7 +215,8 @@ class CoherenceChecker {
} }
} }
} }
some(associated_trait) {
for associated_traits.each |associated_trait| {
let def = self.crate_context.tcx.def_map.get let def = self.crate_context.tcx.def_map.get
(associated_trait.ref_id); (associated_trait.ref_id);
#debug("(checking implementation) adding impl for trait \ #debug("(checking implementation) adding impl for trait \
@ -232,10 +228,10 @@ class CoherenceChecker {
let implementation = self.create_impl_from_item(item); let implementation = self.create_impl_from_item(item);
self.add_trait_method(def_id_of_def(def), implementation); self.add_trait_method(def_id_of_def(def), implementation);
} }
}
// Add the implementation to the mapping from implementation to base // Add the implementation to the mapping from implementation to base
// type def ID, if there is a base type for this implementation. // type def ID, if there is a base type for this implementation.
alt get_base_type_def_id(self.inference_context, alt get_base_type_def_id(self.inference_context,
item.span, item.span,
self_type.ty) { self_type.ty) {
@ -326,6 +322,7 @@ class CoherenceChecker {
// Converts a polytype to a monotype by replacing all parameters with // Converts a polytype to a monotype by replacing all parameters with
// type variables. // type variables.
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t { fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
let self_region = let self_region =
if !polytype.rp {none} if !polytype.rp {none}
@ -385,14 +382,6 @@ class CoherenceChecker {
} }
} }
item_impl(_, associated_traits, _, _) { item_impl(_, associated_traits, _, _) {
// XXX: Accept an array of traits.
let optional_trait_ref;
if associated_traits.len() == 0 {
optional_trait_ref = none;
} else {
optional_trait_ref = some(associated_traits[0]);
}
alt self.base_type_def_ids.find(local_def(item.id)) { alt self.base_type_def_ids.find(local_def(item.id)) {
none { none {
// Nothing to do. // Nothing to do.
@ -411,53 +400,48 @@ class CoherenceChecker {
} else { } else {
// This implementation is not in scope of // This implementation is not in scope of
// its base type. This still might be OK // its base type. This still might be OK
// if the trait is defined in the same // if the traits are defined in the same
// crate. // crate.
alt optional_trait_ref { if associated_traits.len() == 0 {
none { // There is no trait to implement, so
// There is no trait to implement, // this is an error.
// so this is an error.
let session = let session =
self.crate_context.tcx.sess; self.crate_context.tcx.sess;
session.span_err(item.span, session.span_err(item.span,
~"cannot \ ~"cannot implement \
implement \ inherent methods \
inherent \ for a type outside \
methods for a \ the scope the type \
type outside \ was defined in; \
the scope the \
type was \
defined in; \
define and \ define and \
implement a \ implement a trait \
trait instead"); instead");
} }
some(trait_ref) {
for associated_traits.each |trait_ref| {
// This is OK if and only if the // This is OK if and only if the
// trait was defined in this // trait was defined in this
// crate. // crate.
let def_map = self.crate_context let def_map = self.crate_context.tcx
.tcx.def_map; .def_map;
let trait_def = let trait_def = def_map.get
def_map.get(trait_ref.ref_id); (trait_ref.ref_id);
let trait_id = let trait_id =
def_id_of_def(trait_def); def_id_of_def(trait_def);
if trait_id.crate != local_crate { if trait_id.crate != local_crate {
let session = self let session = self.crate_context
.crate_context.tcx.sess; .tcx.sess;
session.span_err(item.span, session.span_err(item.span,
~"cannot \ ~"cannot \
provide \ provide an \
an \
extension \ extension \
implementa\ implementa\
tion \ tion \
for a \ for a trait \
trait not \ not defined \
defined \
in this \ in this \
crate"); crate");
} }
@ -465,7 +449,6 @@ class CoherenceChecker {
} }
} }
} }
}
visit_item(item, (), visitor); visit_item(item, (), visitor);
} }