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