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:
parent
2f3296192b
commit
17d2e3b5d2
12 changed files with 91 additions and 43 deletions
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue