diff options
| author | lcnr <rust@lcnr.de> | 2023-02-14 10:53:25 +0100 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2023-02-14 12:18:33 +0100 |
| commit | 51671cd435a9b24bcbe9a3b3e3c7e98b1832dfea (patch) | |
| tree | 41fd4d6d2553c694c439ac4caf39148b60dc736b /compiler/rustc_trait_selection/src | |
| parent | 646e6672000f17154f38f03b0a6948727510d663 (diff) | |
add test for coinduction in new solver
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/mod.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/search_graph/mod.rs | 18 |
2 files changed, 26 insertions, 2 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index e56588c58bd..38a86d55a2c 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -265,12 +265,18 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // call `exists<U> <T as Trait>::Assoc == U` to enable better caching. This goal // could constrain `U` to `u32` which would cause this check to result in a // solver cycle. - if cfg!(debug_assertions) && has_changed && !self.in_projection_eq_hack { + if cfg!(debug_assertions) + && has_changed + && !self.in_projection_eq_hack + && !self.search_graph.in_cycle() + { let mut orig_values = OriginalQueryValues::default(); let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values); let canonical_response = EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?; - assert!(canonical_response.value.var_values.is_identity()); + if !canonical_response.value.var_values.is_identity() { + bug!("unstable result: {goal:?} {canonical_goal:?} {canonical_response:?}"); + } assert_eq!(certainty, canonical_response.value.certainty); } 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 a2ca4bc189c..e989c9145d1 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -42,6 +42,24 @@ impl<'tcx> SearchGraph<'tcx> { && !self.overflow_data.did_overflow() } + /// Whether we're currently in a cycle. This should only be used + /// for debug assertions. + pub(super) fn in_cycle(&self) -> bool { + if let Some(stack_depth) = self.stack.last() { + // Either the current goal on the stack is the root of a cycle... + if self.stack[stack_depth].has_been_used { + return true; + } + + // ...or it depends on a goal with a lower depth. + let current_goal = self.stack[stack_depth].goal; + let entry_index = self.provisional_cache.lookup_table[¤t_goal]; + self.provisional_cache.entries[entry_index].depth != stack_depth + } else { + false + } + } + /// Tries putting the new goal on the stack, returning an error if it is already cached. /// /// This correctly updates the provisional cache if there is a cycle. |
