@@ -28,9 +28,11 @@ use super::inspect::ProofTreeBuilder;
2828use super :: search_graph:: { self , OverflowHandler } ;
2929use super :: SolverMode ;
3030use super :: { search_graph:: SearchGraph , Goal } ;
31+ pub use select:: InferCtxtSelectExt ;
3132
3233mod canonical;
3334mod probe;
35+ mod select;
3436
3537pub struct EvalCtxt < ' a , ' tcx > {
3638 /// The inference context that backs (mostly) inference and placeholder terms
@@ -140,28 +142,47 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
140142 Result < ( bool , Certainty , Vec < Goal < ' tcx , ty:: Predicate < ' tcx > > > ) , NoSolution > ,
141143 Option < inspect:: GoalEvaluation < ' tcx > > ,
142144 ) {
143- let mode = if self . intercrate { SolverMode :: Coherence } else { SolverMode :: Normal } ;
144- let mut search_graph = search_graph:: SearchGraph :: new ( self . tcx , mode) ;
145+ EvalCtxt :: enter_root ( self , generate_proof_tree, |ecx| {
146+ ecx. evaluate_goal ( IsNormalizesToHack :: No , goal)
147+ } )
148+ }
149+ }
150+
151+ impl < ' a , ' tcx > EvalCtxt < ' a , ' tcx > {
152+ pub ( super ) fn solver_mode ( & self ) -> SolverMode {
153+ self . search_graph . solver_mode ( )
154+ }
155+
156+ /// Creates a root evaluation context and search graph. This should only be
157+ /// used from outside of any evaluation, and other methods should be preferred
158+ /// over using this manually (such as [`InferCtxtEvalExt::evaluate_root_goal`]).
159+ fn enter_root < R > (
160+ infcx : & InferCtxt < ' tcx > ,
161+ generate_proof_tree : GenerateProofTree ,
162+ f : impl FnOnce ( & mut EvalCtxt < ' _ , ' tcx > ) -> R ,
163+ ) -> ( R , Option < inspect:: GoalEvaluation < ' tcx > > ) {
164+ let mode = if infcx. intercrate { SolverMode :: Coherence } else { SolverMode :: Normal } ;
165+ let mut search_graph = search_graph:: SearchGraph :: new ( infcx. tcx , mode) ;
145166
146167 let mut ecx = EvalCtxt {
147168 search_graph : & mut search_graph,
148- infcx : self ,
169+ infcx : infcx ,
149170 // Only relevant when canonicalizing the response,
150171 // which we don't do within this evaluation context.
151- predefined_opaques_in_body : self
172+ predefined_opaques_in_body : infcx
152173 . tcx
153174 . mk_predefined_opaques_in_body ( PredefinedOpaquesData :: default ( ) ) ,
154175 // Only relevant when canonicalizing the response.
155176 max_input_universe : ty:: UniverseIndex :: ROOT ,
156177 var_values : CanonicalVarValues :: dummy ( ) ,
157178 nested_goals : NestedGoals :: new ( ) ,
158179 tainted : Ok ( ( ) ) ,
159- inspect : ( self . tcx . sess . opts . unstable_opts . dump_solver_proof_tree
180+ inspect : ( infcx . tcx . sess . opts . unstable_opts . dump_solver_proof_tree
160181 || matches ! ( generate_proof_tree, GenerateProofTree :: Yes ) )
161182 . then ( ProofTreeBuilder :: new_root)
162183 . unwrap_or_else ( ProofTreeBuilder :: new_noop) ,
163184 } ;
164- let result = ecx . evaluate_goal ( IsNormalizesToHack :: No , goal ) ;
185+ let result = f ( & mut ecx ) ;
165186
166187 let tree = ecx. inspect . finalize ( ) ;
167188 if let Some ( tree) = & tree {
@@ -177,11 +198,66 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
177198 assert ! ( search_graph. is_empty( ) ) ;
178199 ( result, tree)
179200 }
180- }
181201
182- impl < ' a , ' tcx > EvalCtxt < ' a , ' tcx > {
183- pub ( super ) fn solver_mode ( & self ) -> SolverMode {
184- self . search_graph . solver_mode ( )
202+ /// Creates a nested evaluation context that shares the same search graph as the
203+ /// one passed in. This is suitable for evaluation, granted that the search graph
204+ /// has had the nested goal recorded on its stack ([`SearchGraph::with_new_goal`]),
205+ /// but it's preferable to use other methods that call this one rather than this
206+ /// method directly.
207+ ///
208+ /// This function takes care of setting up the inference context, setting the anchor,
209+ /// and registering opaques from the canonicalized input.
210+ fn enter_canonical < R > (
211+ tcx : TyCtxt < ' tcx > ,
212+ search_graph : & ' a mut search_graph:: SearchGraph < ' tcx > ,
213+ canonical_input : CanonicalInput < ' tcx > ,
214+ goal_evaluation : & mut ProofTreeBuilder < ' tcx > ,
215+ f : impl FnOnce ( & mut EvalCtxt < ' _ , ' tcx > , Goal < ' tcx , ty:: Predicate < ' tcx > > ) -> R ,
216+ ) -> R {
217+ let intercrate = match search_graph. solver_mode ( ) {
218+ SolverMode :: Normal => false ,
219+ SolverMode :: Coherence => true ,
220+ } ;
221+ let ( ref infcx, input, var_values) = tcx
222+ . infer_ctxt ( )
223+ . intercrate ( intercrate)
224+ . with_next_trait_solver ( true )
225+ . with_opaque_type_inference ( canonical_input. value . anchor )
226+ . build_with_canonical ( DUMMY_SP , & canonical_input) ;
227+
228+ let mut ecx = EvalCtxt {
229+ infcx,
230+ var_values,
231+ predefined_opaques_in_body : input. predefined_opaques_in_body ,
232+ max_input_universe : canonical_input. max_universe ,
233+ search_graph,
234+ nested_goals : NestedGoals :: new ( ) ,
235+ tainted : Ok ( ( ) ) ,
236+ inspect : goal_evaluation. new_goal_evaluation_step ( input) ,
237+ } ;
238+
239+ for & ( key, ty) in & input. predefined_opaques_in_body . opaque_types {
240+ ecx. insert_hidden_type ( key, input. goal . param_env , ty)
241+ . expect ( "failed to prepopulate opaque types" ) ;
242+ }
243+
244+ if !ecx. nested_goals . is_empty ( ) {
245+ panic ! ( "prepopulating opaque types shouldn't add goals: {:?}" , ecx. nested_goals) ;
246+ }
247+
248+ let result = f ( & mut ecx, input. goal ) ;
249+
250+ goal_evaluation. goal_evaluation_step ( ecx. inspect ) ;
251+
252+ // When creating a query response we clone the opaque type constraints
253+ // instead of taking them. This would cause an ICE here, since we have
254+ // assertions against dropping an `InferCtxt` without taking opaques.
255+ // FIXME: Once we remove support for the old impl we can remove this.
256+ if input. anchor != DefiningAnchor :: Error {
257+ let _ = infcx. take_opaque_types ( ) ;
258+ }
259+
260+ result
185261 }
186262
187263 /// The entry point of the solver.
@@ -210,53 +286,17 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
210286 canonical_input,
211287 goal_evaluation,
212288 |search_graph, goal_evaluation| {
213- let intercrate = match search_graph. solver_mode ( ) {
214- SolverMode :: Normal => false ,
215- SolverMode :: Coherence => true ,
216- } ;
217- let ( ref infcx, input, var_values) = tcx
218- . infer_ctxt ( )
219- . intercrate ( intercrate)
220- . with_next_trait_solver ( true )
221- . with_opaque_type_inference ( canonical_input. value . anchor )
222- . build_with_canonical ( DUMMY_SP , & canonical_input) ;
223-
224- let mut ecx = EvalCtxt {
225- infcx,
226- var_values,
227- predefined_opaques_in_body : input. predefined_opaques_in_body ,
228- max_input_universe : canonical_input. max_universe ,
289+ EvalCtxt :: enter_canonical (
290+ tcx,
229291 search_graph,
230- nested_goals : NestedGoals :: new ( ) ,
231- tainted : Ok ( ( ) ) ,
232- inspect : goal_evaluation. new_goal_evaluation_step ( input) ,
233- } ;
234-
235- for & ( key, ty) in & input. predefined_opaques_in_body . opaque_types {
236- ecx. insert_hidden_type ( key, input. goal . param_env , ty)
237- . expect ( "failed to prepopulate opaque types" ) ;
238- }
239-
240- if !ecx. nested_goals . is_empty ( ) {
241- panic ! (
242- "prepopulating opaque types shouldn't add goals: {:?}" ,
243- ecx. nested_goals
244- ) ;
245- }
246-
247- let result = ecx. compute_goal ( input. goal ) ;
248- ecx. inspect . query_result ( result) ;
249- goal_evaluation. goal_evaluation_step ( ecx. inspect ) ;
250-
251- // When creating a query response we clone the opaque type constraints
252- // instead of taking them. This would cause an ICE here, since we have
253- // assertions against dropping an `InferCtxt` without taking opaques.
254- // FIXME: Once we remove support for the old impl we can remove this.
255- if input. anchor != DefiningAnchor :: Error {
256- let _ = infcx. take_opaque_types ( ) ;
257- }
258-
259- result
292+ canonical_input,
293+ goal_evaluation,
294+ |ecx, goal| {
295+ let result = ecx. compute_goal ( goal) ;
296+ ecx. inspect . query_result ( result) ;
297+ result
298+ } ,
299+ )
260300 } ,
261301 )
262302 }
0 commit comments