From eee09ec4263ac13d94e79b92bdd7df780330077a Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 17 Dec 2021 10:27:26 -0500 Subject: [PATCH] Remove 'speculative evaluation' of predicates Performing 'speculative evaluation' introduces caching bugs that cannot be fixed without invasive changes to projection. Hopefully, we can win back most of the performance lost by re-adding 'cache completion' Fixes #90662 --- .../src/traits/project.rs | 19 +---------- .../traits/issue-90662-projection-caching.rs | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/traits/issue-90662-projection-caching.rs diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b32fb616e12be..35145fed8c427 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -10,7 +10,6 @@ use super::PredicateObligation; use super::Selection; use super::SelectionContext; use super::SelectionError; -use super::TraitQueryMode; use super::{ ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourcePointeeData, ImplSourceUserDefinedData, @@ -946,27 +945,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( }; let mut deduped: SsoHashSet<_> = Default::default(); - let mut canonical = - SelectionContext::with_query_mode(selcx.infcx(), TraitQueryMode::Canonical); - result.obligations.drain_filter(|projected_obligation| { if !deduped.insert(projected_obligation.clone()) { return true; } - // If any global obligations always apply, considering regions, then we don't - // need to include them. The `is_global` check rules out inference variables, - // so there's no need for the caller of `opt_normalize_projection_type` - // to evaluate them. - // Note that we do *not* discard obligations that evaluate to - // `EvaluatedtoOkModuloRegions`. Evaluating these obligations - // inside of a query (e.g. `evaluate_obligation`) can change - // the result to `EvaluatedToOkModuloRegions`, while an - // `EvaluatedToOk` obligation will never change the result. - // See #85360 for more details - projected_obligation.is_global(canonical.tcx()) - && canonical - .evaluate_root_obligation(projected_obligation) - .map_or(false, |res| res.must_apply_considering_regions()) + false }); if use_cache { diff --git a/src/test/ui/traits/issue-90662-projection-caching.rs b/src/test/ui/traits/issue-90662-projection-caching.rs new file mode 100644 index 0000000000000..879f30071bfdb --- /dev/null +++ b/src/test/ui/traits/issue-90662-projection-caching.rs @@ -0,0 +1,34 @@ +// check-pass + +// Regression test for issue #90662 +// Tests that projection caching does not cause a spurious error + +trait HasProvider {} +trait Provider { + type Interface: ?Sized; +} + +trait Repository {} +trait Service {} + +struct DbConnection; +impl Provider for DbConnection { + type Interface = DbConnection; +} + +struct RepositoryImpl; +impl> Provider for RepositoryImpl { + type Interface = dyn Repository; +} + +struct ServiceImpl; +impl> Provider for ServiceImpl { + type Interface = dyn Service; +} + +struct TestModule; +impl HasProvider<>::Interface> for TestModule {} +impl HasProvider<>::Interface> for TestModule {} +impl HasProvider<>::Interface> for TestModule {} + +fn main() {}