From 033047a72cd3129831d4c0ae59024d77f17106ec Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 23 Jan 2023 15:34:11 +0100 Subject: [PATCH] `new_outside_solver` -> `evaluate_root_goal` --- .../src/solve/fulfill.rs | 7 +--- .../rustc_trait_selection/src/solve/mod.rs | 42 +++++++++++++------ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 40b9bedc84fd..d59fa71406c3 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,5 +1,6 @@ use std::mem; +use super::{Certainty, InferCtxtEvalExt}; use rustc_infer::{ infer::InferCtxt, traits::{ @@ -8,8 +9,6 @@ use rustc_infer::{ }, }; -use super::{search_graph, Certainty, EvalCtxt}; - /// A trait engine using the new trait solver. /// /// This is mostly identical to how `evaluate_all` works inside of the @@ -66,9 +65,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut has_changed = false; for obligation in mem::take(&mut self.obligations) { let goal = obligation.clone().into(); - let search_graph = &mut search_graph::SearchGraph::new(infcx.tcx); - let mut ecx = EvalCtxt::new_outside_solver(infcx, search_graph); - let (changed, certainty) = match ecx.evaluate_goal(goal) { + let (changed, certainty) = match infcx.evaluate_root_goal(goal) { Ok(result) => result, Err(NoSolution) => { errors.push(FulfillmentError { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index da2a1a19957e..70f094014453 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -152,6 +152,36 @@ impl<'tcx> TyCtxtExt<'tcx> for TyCtxt<'tcx> { } } +pub trait InferCtxtEvalExt<'tcx> { + /// Evaluates a goal from **outside** of the trait solver. + /// + /// Using this while inside of the solver is wrong as it uses a new + /// search graph which would break cycle detection. + fn evaluate_root_goal( + &self, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + ) -> Result<(bool, Certainty), NoSolution>; +} + +impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { + fn evaluate_root_goal( + &self, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + ) -> Result<(bool, Certainty), NoSolution> { + let mut search_graph = search_graph::SearchGraph::new(self.tcx); + + let result = EvalCtxt { + search_graph: &mut search_graph, + infcx: self, + var_values: CanonicalVarValues::dummy(), + } + .evaluate_goal(goal); + + assert!(search_graph.is_empty()); + result + } +} + struct EvalCtxt<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, var_values: CanonicalVarValues<'tcx>, @@ -164,18 +194,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { self.infcx.tcx } - /// Creates a new evaluation context outside of the trait solver. - /// - /// With this solver making a canonical response doesn't make much sense. - /// The `search_graph` for this solver has to be completely empty. - fn new_outside_solver( - infcx: &'a InferCtxt<'tcx>, - search_graph: &'a mut search_graph::SearchGraph<'tcx>, - ) -> EvalCtxt<'a, 'tcx> { - assert!(search_graph.is_empty()); - EvalCtxt { infcx, var_values: CanonicalVarValues::dummy(), search_graph } - } - #[instrument(level = "debug", skip(tcx, search_graph), ret)] fn evaluate_canonical_goal( tcx: TyCtxt<'tcx>,