Better handling for exponential-sized types in misc places

Mostly to fix ui/issues/issue-37311-type-length-limit/issue-37311.rs.

Most parts of the compiler can handle deeply nested types with a lot
of duplicates just fine, but some parts still attempt to naively
traverse type tree.

Before such problems were caught by type length limit check,
but now these places will have to be changed to handle
duplicated types gracefully.
This commit is contained in:
Valerii Lashmanov 2020-09-15 18:22:24 -05:00
parent 2f3296192b
commit 17d2e3b5d2
12 changed files with 91 additions and 43 deletions

View file

@ -31,6 +31,7 @@ use super::unify_key::replace_if_possible;
use super::unify_key::{ConstVarValue, ConstVariableValue};
use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use super::{InferCtxt, MiscVariable, TypeTrace};
use rustc_data_structures::fx::FxHashMap;
use crate::traits::{Obligation, PredicateObligations};
@ -379,6 +380,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
needs_wf: false,
root_ty: ty,
param_env: self.param_env,
cache: FxHashMap::default(),
};
let ty = match generalize.relate(ty, ty) {
@ -438,6 +440,8 @@ struct Generalizer<'cx, 'tcx> {
root_ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cache: FxHashMap<(Ty<'tcx>, Ty<'tcx>), RelateResult<'tcx, Ty<'tcx>>>,
}
/// Result from a generalization operation. This includes
@ -535,13 +539,17 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
let cache_key = (t, t2);
if let Some(result) = self.cache.get(&cache_key) {
return result.clone();
}
debug!("generalize: t={:?}", t);
// Check to see whether the type we are generalizing references
// any other type variable related to `vid` via
// subtyping. This is basically our "occurs check", preventing
// us from creating infinitely sized types.
match *t.kind() {
let result = match *t.kind() {
ty::Infer(ty::TyVar(vid)) => {
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
@ -598,7 +606,10 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
Ok(t)
}
_ => relate::super_relate_tys(self, t, t),
}
};
self.cache.insert(cache_key, result.clone());
return result;
}
fn regions(