1
1
use rustc_data_structures:: fx:: FxHashMap ;
2
- use rustc_hir:: { Movability , Mutability } ;
2
+ use rustc_hir:: { def_id :: DefId , Movability , Mutability } ;
3
3
use rustc_infer:: traits:: query:: NoSolution ;
4
4
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable } ;
5
5
@@ -236,10 +236,12 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
236
236
}
237
237
238
238
pub ( crate ) fn predicates_for_object_candidate < ' tcx > (
239
- tcx : TyCtxt < ' tcx > ,
239
+ ecx : & EvalCtxt < ' _ , ' tcx > ,
240
+ param_env : ty:: ParamEnv < ' tcx > ,
240
241
trait_ref : ty:: TraitRef < ' tcx > ,
241
242
object_bound : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
242
243
) -> Vec < ty:: Predicate < ' tcx > > {
244
+ let tcx = ecx. tcx ( ) ;
243
245
let mut requirements = vec ! [ ] ;
244
246
requirements. extend (
245
247
tcx. super_predicates_of ( trait_ref. def_id ) . instantiate ( tcx, trait_ref. substs ) . predicates ,
@@ -252,13 +254,9 @@ pub(crate) fn predicates_for_object_candidate<'tcx>(
252
254
253
255
let mut replace_projection_with = FxHashMap :: default ( ) ;
254
256
for bound in object_bound {
255
- let bound = bound. no_bound_vars ( ) . expect ( "higher-ranked projections not supported, yet" ) ;
256
- if let ty:: ExistentialPredicate :: Projection ( proj) = bound {
257
+ if let ty:: ExistentialPredicate :: Projection ( proj) = bound. skip_binder ( ) {
257
258
let proj = proj. with_self_ty ( tcx, trait_ref. self_ty ( ) ) ;
258
- let old_ty = replace_projection_with. insert (
259
- proj. projection_ty ,
260
- proj. term . ty ( ) . expect ( "expected only types in dyn right now" ) ,
261
- ) ;
259
+ let old_ty = replace_projection_with. insert ( proj. def_id ( ) , bound. rebind ( proj) ) ;
262
260
assert_eq ! (
263
261
old_ty,
264
262
None ,
@@ -270,24 +268,37 @@ pub(crate) fn predicates_for_object_candidate<'tcx>(
270
268
}
271
269
}
272
270
273
- requirements. fold_with ( & mut ReplaceProjectionWith { tcx, mapping : replace_projection_with } )
271
+ requirements. fold_with ( & mut ReplaceProjectionWith {
272
+ ecx,
273
+ param_env,
274
+ mapping : replace_projection_with,
275
+ } )
274
276
}
275
277
276
- struct ReplaceProjectionWith < ' tcx > {
277
- tcx : TyCtxt < ' tcx > ,
278
- mapping : FxHashMap < ty:: AliasTy < ' tcx > , Ty < ' tcx > > ,
278
+ struct ReplaceProjectionWith < ' a , ' tcx > {
279
+ ecx : & ' a EvalCtxt < ' a , ' tcx > ,
280
+ param_env : ty:: ParamEnv < ' tcx > ,
281
+ mapping : FxHashMap < DefId , ty:: PolyProjectionPredicate < ' tcx > > ,
279
282
}
280
283
281
- impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for ReplaceProjectionWith < ' tcx > {
284
+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for ReplaceProjectionWith < ' _ , ' tcx > {
282
285
fn interner ( & self ) -> TyCtxt < ' tcx > {
283
- self . tcx
286
+ self . ecx . tcx ( )
284
287
}
285
288
286
289
fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
287
290
if let ty:: Alias ( ty:: Projection , alias_ty) = * ty. kind ( )
288
- && let Some ( replacement) = self . mapping . get ( & alias_ty)
291
+ && let Some ( replacement) = self . mapping . get ( & alias_ty. def_id )
289
292
{
290
- * replacement
293
+ let proj = self . ecx . instantiate_binder_with_infer ( * replacement) ;
294
+ // Technically this folder could be fallible?
295
+ let nested = self
296
+ . ecx
297
+ . eq ( self . param_env , alias_ty, proj. projection_ty )
298
+ . expect ( "expected to be able to unify goal projection with dyn's projection" ) ;
299
+ // Technically we could register these too..
300
+ assert ! ( nested. is_empty( ) , "did not expect unification to have any nested goals" ) ;
301
+ proj. term . ty ( ) . unwrap ( )
291
302
} else {
292
303
ty. super_fold_with ( self )
293
304
}
0 commit comments