diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 33bddf1dedc1b..9c3c138a939a8 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -92,7 +92,7 @@ pub enum ProjectionCacheEntry<'tcx> { Ambiguous, Recur, Error, - NormalizedTy(NormalizedTy<'tcx>), + NormalizedTy(Ty<'tcx>), } impl<'tcx> ProjectionCacheStorage<'tcx> { @@ -149,7 +149,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { debug!("Not overwriting Recur"); return; } - let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value)); + let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value.value)); assert!(!fresh_key, "never started projecting `{:?}`", key); } @@ -160,9 +160,9 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>) { let mut map = self.map(); let ty = match map.get(&key) { - Some(&ProjectionCacheEntry::NormalizedTy(ref ty)) => { + Some(&ProjectionCacheEntry::NormalizedTy(ty)) => { debug!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty); - ty.value + ty } ref value => { // Type inference could "strand behind" old cache entries. Leave @@ -172,26 +172,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { } }; - map.insert( - key, - ProjectionCacheEntry::NormalizedTy(Normalized { value: ty, obligations: vec![] }), - ); - } - - /// A specialized version of `complete` for when the key's value is known - /// to be a NormalizedTy. - pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &NormalizedTy<'tcx>) { - // We want to insert `ty` with no obligations. If the existing value - // already has no obligations (as is common) we don't insert anything. - if !ty.obligations.is_empty() { - self.map().insert( - key, - ProjectionCacheEntry::NormalizedTy(Normalized { - value: ty.value, - obligations: vec![], - }), - ); - } + map.insert(key, ProjectionCacheEntry::NormalizedTy(ty)); } /// Indicates that trying to normalize `key` resulted in diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 388413ae06b55..e08295e983e1d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -519,18 +519,12 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( Err(ProjectionCacheEntry::NormalizedTy(ty)) => { // This is the hottest path in this function. // - // If we find the value in the cache, then return it along - // with the obligations that went along with it. Note - // that, when using a fulfillment context, these - // obligations could in principle be ignored: they have - // already been registered when the cache entry was - // created (and hence the new ones will quickly be - // discarded as duplicated). But when doing trait - // evaluation this is not the case, and dropping the trait - // evaluations can causes ICEs (e.g., #43132). + // If we find the value in the cache, then the obligations + // have already been returned from the previous entry (and + // should therefore have been honored). debug!(?ty, "found normalized ty"); - obligations.extend(ty.obligations); - return Ok(Some(ty.value)); + + return Ok(Some(ty)); } Err(ProjectionCacheEntry::Error) => { debug!("opt_normalize_projection_type: found error"); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a292de148a67a..75ef379c00cd4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2083,28 +2083,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); } - // We are performing deduplication here to avoid exponential blowups - // (#38528) from happening, but the real cause of the duplication is - // unknown. What we know is that the deduplication avoids exponential - // amount of predicates being propagated when processing deeply nested - // types. - // - // This code is hot enough that it's worth avoiding the allocation - // required for the FxHashSet when possible. Special-casing lengths 0, - // 1 and 2 covers roughly 75-80% of the cases. - if obligations.len() <= 1 { - // No possibility of duplicates. - } else if obligations.len() == 2 { - // Only two elements. Drop the second if they are equal. - if obligations[0] == obligations[1] { - obligations.truncate(1); - } - } else { - // Three or more elements. Use a general deduplication process. - let mut seen = FxHashSet::default(); - obligations.retain(|i| seen.insert(i.clone())); - } - obligations } }