Auto merge of #130194 - lcnr:generalize-cache, r=compiler-errors

generalize: track relevant info in cache key

This was previously theoretically incomplete as we could incorrectly generalize as if the type was in an invariant context even though we're in a covariant one. Similar with the `in_alias` flag.

r? `@compiler-errors`
This commit is contained in:
bors 2024-09-11 07:17:12 +00:00
commit 5a2dd7d4f3
3 changed files with 16 additions and 16 deletions

View File

@ -259,11 +259,11 @@ impl<'tcx> InferCtxt<'tcx> {
structurally_relate_aliases, structurally_relate_aliases,
root_vid, root_vid,
for_universe, for_universe,
ambient_variance,
root_term: source_term.into(), root_term: source_term.into(),
ambient_variance,
in_alias: false, in_alias: false,
has_unconstrained_ty_var: false,
cache: Default::default(), cache: Default::default(),
has_unconstrained_ty_var: false,
}; };
let value_may_be_infer = generalizer.relate(source_term, source_term)?; let value_may_be_infer = generalizer.relate(source_term, source_term)?;
@ -304,14 +304,12 @@ struct Generalizer<'me, 'tcx> {
/// we reject the relation. /// we reject the relation.
for_universe: ty::UniverseIndex, for_universe: ty::UniverseIndex,
/// After we generalize this type, we are going to relate it to
/// some other type. What will be the variance at this point?
ambient_variance: ty::Variance,
/// The root term (const or type) we're generalizing. Used for cycle errors. /// The root term (const or type) we're generalizing. Used for cycle errors.
root_term: Term<'tcx>, root_term: Term<'tcx>,
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>, /// After we generalize this type, we are going to relate it to
/// some other type. What will be the variance at this point?
ambient_variance: ty::Variance,
/// This is set once we're generalizing the arguments of an alias. /// This is set once we're generalizing the arguments of an alias.
/// ///
@ -320,6 +318,8 @@ struct Generalizer<'me, 'tcx> {
/// hold by either normalizing the outer or the inner associated type. /// hold by either normalizing the outer or the inner associated type.
in_alias: bool, in_alias: bool,
cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
/// See the field `has_unconstrained_ty_var` in `Generalization`. /// See the field `has_unconstrained_ty_var` in `Generalization`.
has_unconstrained_ty_var: bool, has_unconstrained_ty_var: bool,
} }
@ -451,7 +451,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be == assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
if let Some(&result) = self.cache.get(&t) { if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
return Ok(result); return Ok(result);
} }
@ -557,7 +557,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
_ => relate::structurally_relate_tys(self, t, t), _ => relate::structurally_relate_tys(self, t, t),
}?; }?;
self.cache.insert(t, g); self.cache.insert((t, self.ambient_variance, self.in_alias), g);
Ok(g) Ok(g)
} }

View File

@ -11,9 +11,11 @@ fn bind<T>() -> (T, [u8; 6 + 1]) {
fn main() { fn main() {
let (mut t, foo) = bind(); let (mut t, foo) = bind();
//~^ ERROR mismatched types
//~| NOTE cyclic type
// `t` is `ty::Infer(TyVar(?1t))` // `t` is `ty::Infer(TyVar(?1t))`
// `foo` contains `ty::Infer(TyVar(?1t))` in its substs // `foo` contains `ty::Infer(TyVar(?1t))` in its substs
t = foo; t = foo;
//~^ ERROR mismatched types
//~| NOTE cyclic type
} }

View File

@ -1,10 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/unused-substs-3.rs:16:9 --> $DIR/unused-substs-3.rs:13:24
| |
LL | t = foo; LL | let (mut t, foo) = bind();
| ^^^- help: try using a conversion method: `.to_vec()` | ^^^^^^ cyclic type of infinite size
| |
| cyclic type of infinite size
error: aborting due to 1 previous error error: aborting due to 1 previous error