1
Fork 0

Prevent caching projections in the case of cycles

When normalizing a projection which results in a cycle, we would
cache the result of `project_type` without the nested obligations
(because they're not needed for inference). This would result in
the nested obligations only being handled once in fulfill, which
would avoid the cycle error.

Fixes #79714, a regresion from #79305 caused by the removal of
`get_paranoid_cache_value_obligation`.
This commit is contained in:
Matthew Jasper 2020-12-20 18:13:05 +00:00
parent 77fce67733
commit 2e92b13a60
11 changed files with 150 additions and 21 deletions

View file

@ -496,12 +496,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
return Ok(None);
}
Err(ProjectionCacheEntry::InProgress) => {
// If while normalized A::B, we are asked to normalize
// A::B, just return A::B itself. This is a conservative
// answer, in the sense that A::B *is* clearly equivalent
// to A::B, though there may be a better value we can
// find.
// Under lazy normalization, this can arise when
// bootstrapping. That is, imagine an environment with a
// where-clause like `A::B == u32`. Now, if we are asked
@ -512,6 +506,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
debug!("found cache entry: in-progress");
// Cache that normalizing this projection resulted in a cycle. This
// should ensure that, unless this happens within a snapshot that's
// rolled back, fulfillment or evaluation will notice the cycle.
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
return Err(InProgress);
}
Err(ProjectionCacheEntry::Recur) => {
return Err(InProgress);
}
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {

View file

@ -291,6 +291,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.tcx
}
pub(super) fn query_mode(&self) -> TraitQueryMode {
self.query_mode
}
///////////////////////////////////////////////////////////////////////////
// Selection
//