17
17
//!
18
18
//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html
19
19
20
- use either:: Either ;
21
20
use infer:: canonical:: substitute:: substitute_value;
22
21
use infer:: canonical:: {
23
22
Canonical , CanonicalVarKind , CanonicalVarValues , CanonicalizedQueryResult , Certainty ,
@@ -29,7 +28,6 @@ use rustc_data_structures::indexed_vec::Idx;
29
28
use rustc_data_structures:: indexed_vec:: IndexVec ;
30
29
use rustc_data_structures:: sync:: Lrc ;
31
30
use std:: fmt:: Debug ;
32
- use std:: iter:: once;
33
31
use syntax:: ast;
34
32
use traits:: query:: NoSolution ;
35
33
use traits:: { FulfillmentContext , TraitEngine } ;
@@ -191,9 +189,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
191
189
pub fn instantiate_nll_query_result_and_region_obligations < R > (
192
190
& self ,
193
191
cause : & ObligationCause < ' tcx > ,
192
+ param_env : ty:: ParamEnv < ' tcx > ,
194
193
original_values : & CanonicalVarValues < ' tcx > ,
195
194
query_result : & Canonical < ' tcx , QueryResult < ' tcx , R > > ,
196
- ) -> Vec < QueryRegionConstraint < ' tcx > >
195
+ output_query_region_constraints : & mut Vec < QueryRegionConstraint < ' tcx > > ,
196
+ ) -> InferResult < ' tcx , R >
197
197
where
198
198
R : Debug + TypeFoldable < ' tcx > ,
199
199
{
@@ -210,52 +210,59 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
210
210
// Compute `QueryRegionConstraint` values that unify each of
211
211
// the original values `v_o` that was canonicalized into a
212
212
// variable...
213
- let qrc_from_unify = original_values. var_values . iter_enumerated ( ) . flat_map (
214
- |( index, original_value) | {
215
- // ...with the value `v_r` of that variable from the query.
216
- let result_value =
217
- query_result
218
- . substitute_projected ( self . tcx , & result_subst, |v| & v. var_values [ index] ) ;
219
- match ( original_value. unpack ( ) , result_value. unpack ( ) ) {
220
- (
221
- UnpackedKind :: Lifetime ( ty:: ReErased ) ,
222
- UnpackedKind :: Lifetime ( ty:: ReErased ) ,
223
- ) => {
224
- // no action needed
225
- Either :: Left ( None . into_iter ( ) )
226
- }
213
+ let mut obligations = vec ! [ ] ;
214
+
215
+ for ( index, original_value) in original_values. var_values . iter_enumerated ( ) {
216
+ // ...with the value `v_r` of that variable from the query.
217
+ let result_value = query_result
218
+ . substitute_projected ( self . tcx , & result_subst, |v| & v. var_values [ index] ) ;
219
+ match ( original_value. unpack ( ) , result_value. unpack ( ) ) {
220
+ ( UnpackedKind :: Lifetime ( ty:: ReErased ) , UnpackedKind :: Lifetime ( ty:: ReErased ) ) => {
221
+ // no action needed
222
+ }
227
223
228
- ( UnpackedKind :: Lifetime ( v_o) , UnpackedKind :: Lifetime ( v_r) ) => {
229
- // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
230
- Either :: Right (
231
- once ( ty :: OutlivesPredicate ( v_o . into ( ) , v_r ) )
232
- . chain ( once ( ty:: OutlivesPredicate ( v_r . into ( ) , v_o ) ) )
233
- . map ( ty :: Binder :: dummy ) ,
234
- )
224
+ ( UnpackedKind :: Lifetime ( v_o) , UnpackedKind :: Lifetime ( v_r) ) => {
225
+ // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
226
+ if v_o != v_r {
227
+ output_query_region_constraints
228
+ . push ( ty :: Binder :: dummy ( ty:: OutlivesPredicate ( v_o . into ( ) , v_r ) ) ) ;
229
+ output_query_region_constraints
230
+ . push ( ty :: Binder :: dummy ( ty :: OutlivesPredicate ( v_r . into ( ) , v_o ) ) ) ;
235
231
}
232
+ }
236
233
237
- ( UnpackedKind :: Type ( _) , _) | ( _, UnpackedKind :: Type ( _) ) => {
238
- // in NLL queries, we do not expect `type` results.
239
- bug ! (
240
- "unexpected type in NLL query: cannot unify {:?} and {:?}" ,
241
- original_value,
242
- result_value,
243
- ) ;
244
- }
234
+ ( UnpackedKind :: Type ( v1) , UnpackedKind :: Type ( v2) ) => {
235
+ let ok = self . at ( cause, param_env) . eq ( v1, v2) ?;
236
+ obligations. extend ( ok. into_obligations ( ) ) ;
245
237
}
246
- } ,
247
- ) ;
238
+
239
+ _ => {
240
+ bug ! (
241
+ "kind mismatch, cannot unify {:?} and {:?}" ,
242
+ original_value,
243
+ result_value
244
+ ) ;
245
+ }
246
+ }
247
+ }
248
248
249
249
// ...also include the other query region constraints from the query.
250
- let qrc_from_result = query_result. value . region_constraints . iter ( ) . map ( |r_c| {
251
- r_c. map_bound ( |ty:: OutlivesPredicate ( k1, r2) | {
250
+ output_query_region_constraints. reserve ( query_result. value . region_constraints . len ( ) ) ;
251
+ for r_c in query_result. value . region_constraints . iter ( ) {
252
+ output_query_region_constraints. push ( r_c. map_bound ( |ty:: OutlivesPredicate ( k1, r2) | {
252
253
let k1 = substitute_value ( self . tcx , & result_subst, & k1) ;
253
254
let r2 = substitute_value ( self . tcx , & result_subst, & r2) ;
254
255
ty:: OutlivesPredicate ( k1, r2)
255
- } )
256
- } ) ;
256
+ } ) ) ;
257
+ }
257
258
258
- qrc_from_unify. chain ( qrc_from_result) . collect ( )
259
+ let user_result: R =
260
+ query_result. substitute_projected ( self . tcx , & result_subst, |q_r| & q_r. value ) ;
261
+
262
+ Ok ( InferOk {
263
+ value : user_result,
264
+ obligations,
265
+ } )
259
266
}
260
267
261
268
/// Given the original values and the (canonicalized) result from
0 commit comments