From 88b65c9e2b42d663bca64c935350d6e96f0b9c4e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 17 Mar 2015 05:18:01 -0400 Subject: [PATCH] Refactor the emit_vtable_methods code to be a bit cleaner in its use of iterators. --- src/librustc_trans/trans/meth.rs | 99 +++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 34 deletions(-) diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index ba3798d7d8028..09a252a8e4684 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -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 { + -> Vec +{ 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; - - 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`, etc) into an object