diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a43449a8f99fd..53c3c0d8f85cf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1439,6 +1439,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.next_trait_solver() && let ty::Alias(..) = ty.kind() { + if let Some(&normalized_ty) = self.normalization_cache.borrow().get(&ty) { + return normalized_ty; + } // We need to use a separate variable here as otherwise the temporary for // `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting // in a reentrant borrow, causing an ICE. @@ -1446,7 +1449,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .at(&self.misc(sp), self.param_env) .structurally_normalize_ty(ty, &mut **self.fulfillment_cx.borrow_mut()); match result { - Ok(normalized_ty) => normalized_ty, + Ok(normalized_ty) => { + self.normalization_cache.borrow_mut().insert(ty, normalized_ty); + self.resolve_vars_with_obligations(normalized_ty) + } Err(errors) => { let guar = self.err_ctxt().report_fulfillment_errors(errors); return Ty::new_error(self.tcx, guar); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 393556928af89..cc3ad5d2d2f2f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -9,6 +9,7 @@ use std::cell::{Cell, RefCell}; use std::ops::Deref; use hir::def_id::CRATE_DEF_ID; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, HirId, ItemLocalMap}; @@ -122,6 +123,8 @@ pub(crate) struct FnCtxt<'a, 'tcx> { /// These are stored here so we may collect them when canonicalizing user /// type ascriptions later. pub(super) trait_ascriptions: RefCell>>>, + + pub(super) normalization_cache: RefCell, Ty<'tcx>>>, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -150,6 +153,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diverging_fallback_behavior, diverging_block_behavior, trait_ascriptions: Default::default(), + normalization_cache: Default::default(), } }