@@ -9,7 +9,10 @@ use rustc_infer::infer::{
9
9
use rustc_infer:: traits:: query:: NoSolution ;
10
10
use rustc_infer:: traits:: ObligationCause ;
11
11
use 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 ;
13
16
use rustc_middle:: ty:: {
14
17
self , Ty , TyCtxt , TypeFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitableExt ,
15
18
TypeVisitor ,
@@ -44,6 +47,9 @@ pub struct EvalCtxt<'a, 'tcx> {
44
47
infcx : & ' a InferCtxt < ' tcx > ,
45
48
46
49
pub ( super ) var_values : CanonicalVarValues < ' tcx > ,
50
+
51
+ predefined_opaques_in_body : PredefinedOpaques < ' tcx > ,
52
+
47
53
/// The highest universe index nameable by the caller.
48
54
///
49
55
/// 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> {
126
132
let mut ecx = EvalCtxt {
127
133
search_graph : & mut search_graph,
128
134
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 ( ) ) ,
129
140
// Only relevant when canonicalizing the response.
130
141
max_input_universe : ty:: UniverseIndex :: ROOT ,
131
142
var_values : CanonicalVarValues :: dummy ( ) ,
@@ -162,29 +173,59 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
162
173
fn evaluate_canonical_goal (
163
174
tcx : TyCtxt < ' tcx > ,
164
175
search_graph : & ' a mut search_graph:: SearchGraph < ' tcx > ,
165
- canonical_goal : CanonicalGoal < ' tcx > ,
176
+ canonical_input : CanonicalInput < ' tcx > ,
166
177
) -> QueryResult < ' tcx > {
167
178
// Deal with overflow, caching, and coinduction.
168
179
//
169
180
// 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| {
171
182
let intercrate = match search_graph. solver_mode ( ) {
172
183
SolverMode :: Normal => false ,
173
184
SolverMode :: Coherence => true ,
174
185
} ;
175
- let ( ref infcx, goal , var_values) = tcx
186
+ let ( ref infcx, input , var_values) = tcx
176
187
. infer_ctxt ( )
177
188
. 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
+ }
179
208
let mut ecx = EvalCtxt {
180
209
infcx,
181
210
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 ,
183
213
search_graph,
184
214
nested_goals : NestedGoals :: new ( ) ,
185
215
tainted : Ok ( ( ) ) ,
186
216
} ;
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
188
229
} )
189
230
}
190
231
@@ -199,7 +240,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
199
240
let canonical_response =
200
241
EvalCtxt :: evaluate_canonical_goal ( self . tcx ( ) , self . search_graph , canonical_goal) ?;
201
242
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 ( ) ;
203
245
let ( certainty, nested_goals) = self . instantiate_and_apply_query_response (
204
246
goal. param_env ,
205
247
orig_values,
@@ -418,6 +460,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
418
460
let mut ecx = EvalCtxt {
419
461
infcx : self . infcx ,
420
462
var_values : self . var_values ,
463
+ predefined_opaques_in_body : self . predefined_opaques_in_body ,
421
464
max_input_universe : self . max_input_universe ,
422
465
search_graph : self . search_graph ,
423
466
nested_goals : self . nested_goals . clone ( ) ,
@@ -682,4 +725,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
682
725
| rustc_transmute:: Answer :: IfAny ( _) => Err ( NoSolution ) ,
683
726
}
684
727
}
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
+ }
685
740
}
0 commit comments