Skip to content

Commit

Permalink
Refactor the emit_vtable_methods code to be a bit cleaner in its use of
Browse files Browse the repository at this point in the history
iterators.
  • Loading branch information
nikomatsakis committed Mar 17, 2015
1 parent 883551b commit 88b65c9
Showing 1 changed file with 65 additions and 34 deletions.
99 changes: 65 additions & 34 deletions src/librustc_trans/trans/meth.rs
Expand Up @@ -771,9 +771,15 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
impl_id: ast::DefId,
substs: subst::Substs<'tcx>,
param_substs: &'tcx subst::Substs<'tcx>)
-> Vec<ValueRef> {
-> Vec<ValueRef>
{
let tcx = ccx.tcx();

debug!("emit_vtable_methods(impl_id={}, substs={}, param_substs={})",
impl_id.repr(tcx),
substs.repr(tcx),
param_substs.repr(tcx));

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 \
Expand All @@ -783,41 +789,66 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ty::populate_implementations_for_trait_if_necessary(tcx, trt_id);

let trait_item_def_ids = ty::trait_item_def_ids(tcx, trt_id);
trait_item_def_ids.iter().flat_map(|method_def_id| {
let method_def_id = method_def_id.def_id();
let name = ty::impl_or_trait_item(tcx, method_def_id).name();
// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
let m_id = method_with_name(ccx, impl_id, name);
let ti = ty::impl_or_trait_item(tcx, m_id);
match ti {
ty::MethodTraitItem(m) => {
debug!("(making impl vtable) emitting method {} at subst {}",
m.repr(tcx),
substs.repr(tcx));
if m.generics.has_type_params(subst::FnSpace) ||
ty::type_has_self(ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(m.fty.clone())))
{
debug!("(making impl vtable) method has self or type \
params: {}",
token::get_name(name));
Some(C_null(Type::nil(ccx).ptr_to())).into_iter()
} else {
let fn_ref = trans_fn_ref_with_substs(
ccx,
m_id,
ExprId(0),
param_substs,
substs.clone()).val;

Some(fn_ref).into_iter()
}
trait_item_def_ids
.iter()

// Filter out the associated types.
.filter_map(|item_def_id| {
match *item_def_id {
ty::MethodTraitItemId(def_id) => Some(def_id),
ty::TypeTraitItemId(_) => None,
}
ty::TypeTraitItem(_) => {
None.into_iter()
})

// Now produce pointers for each remaining method. If the
// method could never be called from this object, just supply
// null.
.map(|trait_method_def_id| {
debug!("emit_vtable_methods: trait_method_def_id={}",
trait_method_def_id.repr(tcx));

let trait_method_type = match ty::impl_or_trait_item(tcx, trait_method_def_id) {
ty::MethodTraitItem(m) => m,
ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type")
};
let name = trait_method_type.name;

debug!("emit_vtable_methods: trait_method_type={}",
trait_method_type.repr(tcx));

// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
let impl_method_def_id = method_with_name(ccx, impl_id, name);
let impl_method_type = match ty::impl_or_trait_item(tcx, impl_method_def_id) {
ty::MethodTraitItem(m) => m,
ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type")
};

debug!("emit_vtable_methods: m={}",
impl_method_type.repr(tcx));

let nullptr = C_null(Type::nil(ccx).ptr_to());

if impl_method_type.generics.has_type_params(subst::FnSpace) {
debug!("emit_vtable_methods: generic");
return nullptr;
}
}
}).collect()

let bare_fn_ty =
ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_method_type.fty.clone()));
if ty::type_has_self(bare_fn_ty) {
debug!("emit_vtable_methods: type_has_self {}",
bare_fn_ty.repr(tcx));
return nullptr;
}

trans_fn_ref_with_substs(ccx,
impl_method_def_id,
ExprId(0),
param_substs,
substs.clone()).val
})
.collect()
}

/// Generates the code to convert from a pointer (`Box<T>`, `&T`, etc) into an object
Expand Down

0 comments on commit 88b65c9

Please sign in to comment.