diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2020-12-20 18:13:05 +0000 |
|---|---|---|
| committer | Matthew Jasper <mjjasper1@gmail.com> | 2020-12-20 21:47:51 +0000 |
| commit | 2e92b13a606ba2f073c789dfd6c33f889f04c8cf (patch) | |
| tree | 65d4dc0e2251bc3a5d08aa4d8360909074b5d3ca /compiler/rustc_infer | |
| parent | 77fce67733d2a1403f17b382dfbd3802003172a6 (diff) | |
| download | rust-2e92b13a606ba2f073c789dfd6c33f889f04c8cf.tar.gz rust-2e92b13a606ba2f073c789dfd6c33f889f04c8cf.zip | |
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`.
Diffstat (limited to 'compiler/rustc_infer')
| -rw-r--r-- | compiler/rustc_infer/src/traits/project.rs | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 65284bcee91..33bddf1dedc 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -90,6 +90,7 @@ impl ProjectionCacheKey<'tcx> { pub enum ProjectionCacheEntry<'tcx> { InProgress, Ambiguous, + Recur, Error, NormalizedTy(NormalizedTy<'tcx>), } @@ -143,7 +144,12 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}", key, value ); - let fresh_key = self.map().insert(key, ProjectionCacheEntry::NormalizedTy(value)); + let mut map = self.map(); + if let Some(ProjectionCacheEntry::Recur) = map.get(&key) { + debug!("Not overwriting Recur"); + return; + } + let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value)); assert!(!fresh_key, "never started projecting `{:?}`", key); } @@ -197,6 +203,14 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { assert!(!fresh, "never started projecting `{:?}`", key); } + /// Indicates that while trying to normalize `key`, `key` was required to + /// be normalized again. Selection or evaluation should eventually report + /// an error here. + pub fn recur(&mut self, key: ProjectionCacheKey<'tcx>) { + let fresh = self.map().insert(key, ProjectionCacheEntry::Recur); + assert!(!fresh, "never started projecting `{:?}`", key); + } + /// Indicates that trying to normalize `key` resulted in /// error. pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) { |
