From a5164605bc3b572cf2281ce81ad5339fd6249aea Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 8 Feb 2023 13:50:27 +0100 Subject: [PATCH 1/2] correctly update goals in the cache --- .../src/solve/search_graph/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index 7514c7ee55170..a2ca4bc189c87 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -7,7 +7,7 @@ use cache::ProvisionalCache; use overflow::OverflowData; use rustc_index::vec::IndexVec; use rustc_middle::ty::TyCtxt; -use std::collections::hash_map::Entry; +use std::{collections::hash_map::Entry, mem}; rustc_index::newtype_index! { pub struct StackDepth {} @@ -134,12 +134,15 @@ impl<'tcx> SearchGraph<'tcx> { let provisional_entry_index = *cache.lookup_table.get(&goal).unwrap(); let provisional_entry = &mut cache.entries[provisional_entry_index]; let depth = provisional_entry.depth; + // We eagerly update the response in the cache here. If we have to reevaluate + // this goal we use the new response when hitting a cycle, and we definitely + // want to access the final response whenever we look at the cache. + let prev_response = mem::replace(&mut provisional_entry.response, response); + // Was the current goal the root of a cycle and was the provisional response // different from the final one. - if has_been_used && provisional_entry.response != response { - // If so, update the provisional reponse for this goal... - provisional_entry.response = response; - // ...remove all entries whose result depends on this goal + if has_been_used && prev_response != response { + // If so, remove all entries whose result depends on this goal // from the provisional cache... // // That's not completely correct, as a nested goal can also From 4c7c5e597f2c7d6d9453a8288d54a211ae0414bb Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 8 Feb 2023 14:16:22 +0100 Subject: [PATCH 2/2] add (currently ICEing) test --- .../new-solver/provisional-result-done.rs | 37 +++++++++++++++++++ .../new-solver/provisional-result-done.stderr | 6 +++ 2 files changed, 43 insertions(+) create mode 100644 tests/ui/traits/new-solver/provisional-result-done.rs create mode 100644 tests/ui/traits/new-solver/provisional-result-done.stderr diff --git a/tests/ui/traits/new-solver/provisional-result-done.rs b/tests/ui/traits/new-solver/provisional-result-done.rs new file mode 100644 index 0000000000000..a3d97927bad22 --- /dev/null +++ b/tests/ui/traits/new-solver/provisional-result-done.rs @@ -0,0 +1,37 @@ +// known-bug: unknown +// compile-flags: -Ztrait-solver=next +// failure-status: 101 +// normalize-stderr-test "note: .*\n\n" -> "" +// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +// rustc-env:RUST_BACKTRACE=0 + +// This tests checks that we update results in the provisional cache when +// we pop a goal from the stack. +#![feature(auto_traits)] +auto trait Coinductive {} +struct Foo(T); +struct Bar(T); + +impl Coinductive for Foo +where + Bar: Coinductive +{} + +impl Coinductive for Bar +where + Foo: Coinductive, + Bar: ConstrainInfer, +{} + +trait ConstrainInfer {} +impl ConstrainInfer for Bar {} +impl ConstrainInfer for Foo {} + +fn impls() -> T { todo!() } + +fn constrain(_: T) {} + +fn main() { + // This should constrain `_` to `u8`. + impls::>(); +} diff --git a/tests/ui/traits/new-solver/provisional-result-done.stderr b/tests/ui/traits/new-solver/provisional-result-done.stderr new file mode 100644 index 0000000000000..ffc92b81f089e --- /dev/null +++ b/tests/ui/traits/new-solver/provisional-result-done.stderr @@ -0,0 +1,6 @@ +error: the compiler unexpectedly panicked. this is a bug. + +query stack during panic: +#0 [check_well_formed] checking that `` is well-formed +#1 [check_mod_type_wf] checking that types are well-formed in top-level module +end of query stack