@@ -9,7 +9,10 @@ use rustc_infer::infer::{
99use rustc_infer:: traits:: query:: NoSolution ;
1010use rustc_infer:: traits:: ObligationCause ;
1111use rustc_middle:: infer:: unify_key:: { ConstVariableOrigin , ConstVariableOriginKind } ;
12- use rustc_middle:: traits:: solve:: { CanonicalGoal , Certainty , MaybeCause , QueryResult } ;
12+ use rustc_middle:: traits:: solve:: {
13+ CanonicalInput , Certainty , MaybeCause , PredefinedOpaques , PredefinedOpaquesData , QueryResult ,
14+ } ;
15+ use rustc_middle:: traits:: DefiningAnchor ;
1316use rustc_middle:: ty:: {
1417 self , Ty , TyCtxt , TypeFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitableExt ,
1518 TypeVisitor ,
@@ -44,6 +47,9 @@ pub struct EvalCtxt<'a, 'tcx> {
4447 infcx : & ' a InferCtxt < ' tcx > ,
4548
4649 pub ( super ) var_values : CanonicalVarValues < ' tcx > ,
50+
51+ predefined_opaques_in_body : PredefinedOpaques < ' tcx > ,
52+
4753 /// The highest universe index nameable by the caller.
4854 ///
4955 /// When we enter a new binder inside of the query we create new universes
@@ -126,6 +132,11 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
126132 let mut ecx = EvalCtxt {
127133 search_graph : & mut search_graph,
128134 infcx : self ,
135+ // Only relevant when canonicalizing the response,
136+ // which we don't do within this evaluation context.
137+ predefined_opaques_in_body : self
138+ . tcx
139+ . mk_predefined_opaques_in_body ( PredefinedOpaquesData :: default ( ) ) ,
129140 // Only relevant when canonicalizing the response.
130141 max_input_universe : ty:: UniverseIndex :: ROOT ,
131142 var_values : CanonicalVarValues :: dummy ( ) ,
@@ -162,29 +173,59 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
162173 fn evaluate_canonical_goal (
163174 tcx : TyCtxt < ' tcx > ,
164175 search_graph : & ' a mut search_graph:: SearchGraph < ' tcx > ,
165- canonical_goal : CanonicalGoal < ' tcx > ,
176+ canonical_input : CanonicalInput < ' tcx > ,
166177 ) -> QueryResult < ' tcx > {
167178 // Deal with overflow, caching, and coinduction.
168179 //
169180 // The actual solver logic happens in `ecx.compute_goal`.
170- search_graph. with_new_goal ( tcx, canonical_goal , |search_graph| {
181+ search_graph. with_new_goal ( tcx, canonical_input , |search_graph| {
171182 let intercrate = match search_graph. solver_mode ( ) {
172183 SolverMode :: Normal => false ,
173184 SolverMode :: Coherence => true ,
174185 } ;
175- let ( ref infcx, goal , var_values) = tcx
186+ let ( ref infcx, input , var_values) = tcx
176187 . infer_ctxt ( )
177188 . intercrate ( intercrate)
178- . build_with_canonical ( DUMMY_SP , & canonical_goal) ;
189+ . with_opaque_type_inference ( canonical_input. value . anchor )
190+ . build_with_canonical ( DUMMY_SP , & canonical_input) ;
191+
192+ for & ( a, b) in & input. predefined_opaques_in_body . opaque_types {
193+ let InferOk { value : ( ) , obligations } = infcx
194+ . handle_opaque_type (
195+ tcx. mk_opaque ( a. def_id . to_def_id ( ) , a. substs ) ,
196+ b,
197+ true ,
198+ & ObligationCause :: dummy ( ) ,
199+ input. goal . param_env ,
200+ )
201+ . expect ( "expected opaque type instantiation to succeed" ) ;
202+ // We're only registering opaques already defined by the caller,
203+ // so we're not responsible for proving that they satisfy their
204+ // item bounds, unless we use them in a normalizes-to goal,
205+ // which is handled in `EvalCtxt::unify_existing_opaque_tys`.
206+ let _ = obligations;
207+ }
179208 let mut ecx = EvalCtxt {
180209 infcx,
181210 var_values,
182- max_input_universe : canonical_goal. max_universe ,
211+ predefined_opaques_in_body : input. predefined_opaques_in_body ,
212+ max_input_universe : canonical_input. max_universe ,
183213 search_graph,
184214 nested_goals : NestedGoals :: new ( ) ,
185215 tainted : Ok ( ( ) ) ,
186216 } ;
187- ecx. compute_goal ( goal)
217+
218+ let result = ecx. compute_goal ( input. goal ) ;
219+
220+ // When creating a query response we clone the opaque type constraints
221+ // instead of taking them. This would cause an ICE here, since we have
222+ // assertions against dropping an `InferCtxt` without taking opaques.
223+ // FIXME: Once we remove support for the old impl we can remove this.
224+ if input. anchor != DefiningAnchor :: Error {
225+ let _ = infcx. take_opaque_types ( ) ;
226+ }
227+
228+ result
188229 } )
189230 }
190231
@@ -199,7 +240,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
199240 let canonical_response =
200241 EvalCtxt :: evaluate_canonical_goal ( self . tcx ( ) , self . search_graph , canonical_goal) ?;
201242
202- let has_changed = !canonical_response. value . var_values . is_identity ( ) ;
243+ let has_changed = !canonical_response. value . var_values . is_identity ( )
244+ || !canonical_response. value . external_constraints . opaque_types . is_empty ( ) ;
203245 let ( certainty, nested_goals) = self . instantiate_and_apply_query_response (
204246 goal. param_env ,
205247 orig_values,
@@ -418,6 +460,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
418460 let mut ecx = EvalCtxt {
419461 infcx : self . infcx ,
420462 var_values : self . var_values ,
463+ predefined_opaques_in_body : self . predefined_opaques_in_body ,
421464 max_input_universe : self . max_input_universe ,
422465 search_graph : self . search_graph ,
423466 nested_goals : self . nested_goals . clone ( ) ,
@@ -682,4 +725,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
682725 | rustc_transmute:: Answer :: IfAny ( _) => Err ( NoSolution ) ,
683726 }
684727 }
728+
729+ pub ( super ) fn handle_opaque_ty (
730+ & mut self ,
731+ a : Ty < ' tcx > ,
732+ b : Ty < ' tcx > ,
733+ param_env : ty:: ParamEnv < ' tcx > ,
734+ ) -> Result < ( ) , NoSolution > {
735+ let InferOk { value : ( ) , obligations } =
736+ self . infcx . handle_opaque_type ( a, b, true , & ObligationCause :: dummy ( ) , param_env) ?;
737+ self . add_goals ( obligations. into_iter ( ) . map ( |obligation| obligation. into ( ) ) ) ;
738+ Ok ( ( ) )
739+ }
685740}
0 commit comments