cache types during normalization

This commit is contained in:
Bastian Kauschke 2020-09-19 17:27:13 +02:00
parent 4e8a8b49ae
commit 1146c39da7
7 changed files with 83 additions and 68 deletions

View file

@ -7,6 +7,7 @@ use crate::infer::canonical::OriginalQueryValues;
use crate::infer::{InferCtxt, InferOk};
use crate::traits::error_reporting::InferCtxtExt;
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use rustc_data_structures::mini_map::MiniMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::traits::Normalized;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
@ -57,6 +58,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
param_env: self.param_env,
obligations: vec![],
error: false,
cache: MiniMap::new(),
anon_depth: 0,
};
@ -85,6 +87,7 @@ struct QueryNormalizer<'cx, 'tcx> {
cause: &'cx ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
obligations: Vec<PredicateObligation<'tcx>>,
cache: MiniMap<Ty<'tcx>, Ty<'tcx>>,
error: bool,
anon_depth: usize,
}
@ -99,8 +102,12 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
return ty;
}
if let Some(ty) = self.cache.get(&ty) {
return ty;
}
let ty = ty.super_fold_with(self);
match *ty.kind() {
let res = (|| match *ty.kind() {
ty::Opaque(def_id, substs) => {
// Only normalize `impl Trait` after type-checking, usually in codegen.
match self.param_env.reveal() {
@ -197,7 +204,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
}
_ => ty,
}
})();
self.cache.insert(ty, res);
res
}
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {