diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 66b227fe5c54d..ab2a39864336f 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use common::*; use rustc::hir::def_id::DefId; use rustc::infer::TransNormalize; +use rustc::ty::fold::{TypeFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; -use common::*; use rustc::util::ppaux; - +use rustc::util::common::MemoizationMap; use std::fmt; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -51,10 +52,8 @@ pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>, let tcx = scx.tcx(); debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value); let substituted = value.subst(tcx, param_substs); - debug!("apply_param_substs: substituted={:?}{}", - substituted, - if substituted.has_projection_types() { " [needs projection]" } else { "" }); - tcx.normalize_associated_type(&substituted) + let substituted = scx.tcx().erase_regions(&substituted); + AssociatedTypeNormalizer::new(scx).fold(&substituted) } @@ -67,3 +66,39 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.normalize_associated_type(&f.ty(tcx, param_substs)) } +struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b> { + shared: &'a SharedCrateContext<'b, 'gcx>, +} + +impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> { + fn new(shared: &'a SharedCrateContext<'b, 'gcx>) -> Self { + AssociatedTypeNormalizer { + shared: shared, + } + } + + fn fold>(&mut self, value: &T) -> T { + if !value.has_projection_types() { + value.clone() + } else { + value.fold_with(self) + } + } +} + +impl<'a, 'b, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'b, 'gcx> { + fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> { + self.shared.tcx() + } + + fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> { + if !ty.has_projection_types() { + ty + } else { + self.shared.project_cache().memoize(ty, || { + debug!("AssociatedTypeNormalizer: ty={:?}", ty); + self.shared.tcx().normalize_associated_type(&ty) + }) + } + } +}