rustc: Change ty::get_impl_traits to return an option instead of a vec

Impls can implement either zero or one traits; this has been true
more or less since we removed classes. So I got rid of the comments
saying "we should support multiple traits" and changed the code to
make it clear that we don't. This is just cleanup, and doesn't break
any existing tests.
This commit is contained in:
Tim Chevalier 2013-05-16 15:54:51 -07:00
parent 6a9c3bd86e
commit 65b7903ba3
6 changed files with 37 additions and 40 deletions

View file

@ -234,14 +234,13 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
}
}
// Given a def_id for an impl or class, return the traits it implements,
// or the empty vector if it's not for an impl or for a class that implements
// traits
pub fn get_impl_traits(tcx: ty::ctxt,
def: ast::def_id) -> ~[@ty::TraitRef] {
// Given a def_id for an impl, return the trait it implements,
// if there is one.
pub fn get_impl_trait(tcx: ty::ctxt,
def: ast::def_id) -> Option<@ty::TraitRef> {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_impl_traits(cdata, def.node, tcx)
decoder::get_impl_trait(cdata, def.node, tcx)
}
pub fn get_impl_method(cstore: @mut cstore::CStore,

View file

@ -415,19 +415,20 @@ pub fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data))
}
pub fn get_impl_traits(cdata: cmd,
pub fn get_impl_trait(cdata: cmd,
id: ast::node_id,
tcx: ty::ctxt) -> ~[@ty::TraitRef]
tcx: ty::ctxt) -> Option<@ty::TraitRef>
{
let item_doc = lookup_item(id, cdata.data);
let mut results = ~[];
let mut result = None;
for reader::tagged_docs(item_doc, tag_item_trait_ref) |tp| {
let trait_ref =
@parse_trait_ref_data(tp.data, cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did));
results.push(trait_ref);
result = Some(trait_ref);
break;
};
results
result
}
pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,

View file

@ -795,8 +795,11 @@ pub fn make_impl_vtable(ccx: @CrateContext,
let _icx = ccx.insn_ctxt("impl::make_impl_vtable");
let tcx = ccx.tcx;
// XXX: This should support multiple traits.
let trt_id = ty::impl_trait_refs(tcx, impl_id)[0].def_id;
let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
Some(t_id) => t_id.def_id,
None => ccx.sess.bug("make_impl_vtable: don't know how to \
make a vtable for a type impl!")
};
let has_tps =
!ty::lookup_item_type(ccx.tcx, impl_id).generics.type_param_defs.is_empty();

View file

@ -3878,23 +3878,23 @@ pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
|| @csearch::get_trait_method_def_ids(cx.cstore, id))
}
pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] {
pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
if id.crate == ast::local_crate {
debug!("(impl_traits) searching for trait impl %?", id);
debug!("(impl_trait_ref) searching for trait impl %?", id);
match cx.items.find(&id.node) {
Some(&ast_map::node_item(@ast::item {
node: ast::item_impl(_, opt_trait, _, _),
_},
_)) => {
match opt_trait {
Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)],
None => ~[]
Some(t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
None => None
}
}
_ => ~[]
_ => None
}
} else {
csearch::get_impl_traits(cx, id)
csearch::get_impl_trait(cx, id)
}
}

View file

@ -261,24 +261,14 @@ fn lookup_vtable(vcx: &VtableContext,
}
impls_seen.insert(im.did);
// ty::impl_traits gives us the list of all
// traits that im implements. Again, usually
// there's just one.
// ty::impl_traits gives us the trait im implements,
// if there is one (there's either zero or one).
//
// For example, if im represented the struct
// in:
//
// struct foo : baz<int>, bar, quux { ... }
//
// then ty::impl_traits would return
//
// ~[baz<int>, bar, quux]
//
// For each of the traits foo implements, if
// it's the same trait as trait_ref, we need to
// 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.
for ty::impl_trait_refs(tcx, im.did).each |&of_trait_ref|
for ty::impl_trait_ref(tcx, im.did).each |&of_trait_ref|
{
if of_trait_ref.def_id != trait_ref.def_id { loop; }
@ -456,8 +446,12 @@ fn connect_trait_tps(vcx: &VtableContext,
{
let tcx = vcx.tcx();
// XXX: This should work for multiple traits.
let impl_trait_ref = ty::impl_trait_refs(tcx, impl_did)[0];
let impl_trait_ref = match ty::impl_trait_ref(tcx, impl_did) {
Some(t) => t,
None => vcx.tcx().sess.span_bug(location_info.span,
"connect_trait_tps invoked on a type impl")
};
let impl_trait_ref = (*impl_trait_ref).subst(tcx, impl_substs);
relate_trait_refs(vcx, location_info, &impl_trait_ref, trait_ref);
}

View file

@ -16,7 +16,7 @@
use driver;
use metadata::csearch::{each_path, get_impl_traits};
use metadata::csearch::{each_path, get_impl_trait};
use metadata::csearch::{get_impls_for_mod};
use metadata::csearch;
use metadata::cstore::{CStore, iter_crate_data};
@ -898,13 +898,13 @@ pub impl CoherenceChecker {
let self_type = lookup_item_type(self.crate_context.tcx,
implementation.did);
let associated_traits = get_impl_traits(self.crate_context.tcx,
let associated_traits = get_impl_trait(self.crate_context.tcx,
implementation.did);
// Do a sanity check to make sure that inherent methods have base
// types.
if associated_traits.len() == 0 {
if associated_traits.is_none() {
match get_base_type_def_id(self.inference_context,
dummy_sp(),
self_type.ty) {
@ -940,7 +940,7 @@ pub impl CoherenceChecker {
Some(base_type_def_id) => {
// inherent methods apply to `impl Type` but not
// `impl Trait for Type`:
if associated_traits.len() == 0 {
if associated_traits.is_none() {
self.add_inherent_method(base_type_def_id,
*implementation);
}