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 \
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