about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-12-20 07:30:16 +0000
committerbors <bors@rust-lang.org>2021-12-20 07:30:16 +0000
commit60f3bd78eeac87ad474916d36d29ed7e5084b25b (patch)
treea78a4c898374cc0405f31664766be0fc80b04891
parent940a97a91023d1817b33d0ababc985793c9ed780 (diff)
parenteee09ec4263ac13d94e79b92bdd7df780330077a (diff)
downloadrust-60f3bd78eeac87ad474916d36d29ed7e5084b25b.tar.gz
rust-60f3bd78eeac87ad474916d36d29ed7e5084b25b.zip
Auto merge of #92041 - Aaron1011:remove-speculative-evaluation, r=jackh726
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
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs19
-rw-r--r--src/test/ui/traits/issue-90662-projection-caching.rs34
2 files changed, 35 insertions, 18 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 490e35d34f2..23f615a9618 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 00000000000..879f30071bf
--- /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<T: ?Sized> {}
+trait Provider<M> {
+    type Interface: ?Sized;
+}
+
+trait Repository {}
+trait Service {}
+
+struct DbConnection;
+impl<M> Provider<M> for DbConnection {
+    type Interface = DbConnection;
+}
+
+struct RepositoryImpl;
+impl<M: HasProvider<DbConnection>> Provider<M> for RepositoryImpl {
+    type Interface = dyn Repository;
+}
+
+struct ServiceImpl;
+impl<M: HasProvider<dyn Repository>> Provider<M> for ServiceImpl {
+    type Interface = dyn Service;
+}
+
+struct TestModule;
+impl HasProvider<<DbConnection as Provider<Self>>::Interface> for TestModule {}
+impl HasProvider<<RepositoryImpl as Provider<Self>>::Interface> for TestModule {}
+impl HasProvider<<ServiceImpl as Provider<Self>>::Interface> for TestModule {}
+
+fn main() {}