diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8da0f8f13ff..53a974a4bbb 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -653,50 +653,52 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn vtable_methods<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) - -> Vec)>> + -> Rc)>>> { debug!("vtable_methods({:?})", trait_ref); - supertraits(tcx, trait_ref).flat_map(move |trait_ref| { - let trait_methods = tcx.associated_items(trait_ref.def_id()) - .filter(|item| item.kind == ty::AssociatedKind::Method); + Rc::new( + supertraits(tcx, trait_ref).flat_map(move |trait_ref| { + let trait_methods = tcx.associated_items(trait_ref.def_id()) + .filter(|item| item.kind == ty::AssociatedKind::Method); - // Now list each method's DefId and Substs (for within its trait). - // If the method can never be called from this object, produce None. - trait_methods.map(move |trait_method| { - debug!("vtable_methods: trait_method={:?}", trait_method); - let def_id = trait_method.def_id; + // Now list each method's DefId and Substs (for within its trait). + // If the method can never be called from this object, produce None. + trait_methods.map(move |trait_method| { + debug!("vtable_methods: trait_method={:?}", trait_method); + let def_id = trait_method.def_id; - // Some methods cannot be called on an object; skip those. - if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { - debug!("vtable_methods: not vtable safe"); - return None; - } + // Some methods cannot be called on an object; skip those. + if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { + debug!("vtable_methods: not vtable safe"); + return None; + } - // the method may have some early-bound lifetimes, add - // regions for those - let substs = Substs::for_item(tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| trait_ref.substs().type_for_def(def)); + // the method may have some early-bound lifetimes, add + // regions for those + let substs = Substs::for_item(tcx, def_id, + |_, _| tcx.types.re_erased, + |def, _| trait_ref.substs().type_for_def(def)); - // the trait type may have higher-ranked lifetimes in it; - // so erase them if they appear, so that we get the type - // at some particular call site - let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs)); + // the trait type may have higher-ranked lifetimes in it; + // so erase them if they appear, so that we get the type + // at some particular call site + let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs)); - // It's possible that the method relies on where clauses that - // do not hold for this particular set of type parameters. - // Note that this method could then never be called, so we - // do not want to try and trans it, in that case (see #23435). - let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); - if !normalize_and_test_predicates(tcx, predicates.predicates) { - debug!("vtable_methods: predicates do not hold"); - return None; - } + // It's possible that the method relies on where clauses that + // do not hold for this particular set of type parameters. + // Note that this method could then never be called, so we + // do not want to try and trans it, in that case (see #23435). + let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); + if !normalize_and_test_predicates(tcx, predicates.predicates) { + debug!("vtable_methods: predicates do not hold"); + return None; + } - Some((def_id, substs)) - }) - }).collect() + Some((def_id, substs)) + }) + }).collect() + ) } impl<'tcx,O> Obligation<'tcx,O> { diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 872069d381b..4b68f5addd2 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -229,7 +229,7 @@ define_maps! { <'tcx> [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] fn is_mir_available: IsMirAvailable(DefId) -> bool, [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>) - -> Vec)>>, + -> Rc)>>>, [] fn trans_fulfill_obligation: fulfill_obligation_dep_node( (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 08478700001..33a2e96ee66 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -850,7 +850,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Walk all methods of the trait, including those of its supertraits let methods = tcx.vtable_methods(poly_trait_ref); - let methods = methods.into_iter().filter_map(|method| method) + let methods = methods.iter().cloned().filter_map(|method| method) .map(|(def_id, substs)| ty::Instance::resolve( tcx, ty::ParamEnv::empty(traits::Reveal::All), diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 66d633cf9a1..3253a0339a8 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -86,7 +86,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if let Some(trait_ref) = trait_ref { let trait_ref = trait_ref.with_self_ty(tcx, ty); - let methods = tcx.vtable_methods(trait_ref).into_iter().map(|opt_mth| { + let methods = tcx.vtable_methods(trait_ref); + let methods = methods.iter().cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { callee::resolve_and_get_fn(ccx, def_id, substs) })