Refactor the emit_vtable_methods code to be a bit cleaner in its use of

iterators.
This commit is contained in:
Niko Matsakis 2015-03-17 05:18:01 -04:00
parent 883551b1d7
commit 88b65c9e2b

View file

@ -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 \
@ -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;
trait_item_def_ids
.iter()
Some(fn_ref).into_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