@@ -235,6 +235,40 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
235
235
}
236
236
}
237
237
238
+ /// Assemble a list of predicates that would be present on a theoretical
239
+ /// user impl for an object type. These predicates must be checked any time
240
+ /// we assemble a built-in object candidate for an object type, since they
241
+ /// are not implied by the well-formedness of the type.
242
+ ///
243
+ /// For example, given the following traits:
244
+ ///
245
+ /// ```rust,ignore (theoretical code)
246
+ /// trait Foo: Baz {
247
+ /// type Bar: Copy;
248
+ /// }
249
+ ///
250
+ /// trait Baz {}
251
+ /// ```
252
+ ///
253
+ /// For the dyn type `dyn Foo<Item = Ty>`, we can imagine there being a
254
+ /// pair of theoretical impls:
255
+ ///
256
+ /// ```rust,ignore (theoretical code)
257
+ /// impl Foo for dyn Foo<Item = Ty>
258
+ /// where
259
+ /// Self: Baz,
260
+ /// <Self as Foo>::Bar: Copy,
261
+ /// {
262
+ /// type Bar = Ty;
263
+ /// }
264
+ ///
265
+ /// impl Baz for dyn Foo<Item = Ty> {}
266
+ /// ```
267
+ ///
268
+ /// However, in order to make such impls well-formed, we need to do an
269
+ /// additional step of eagerly folding the associated types in the where
270
+ /// clauses of the impl. In this example, that means replacing
271
+ /// `<Self as Foo>::Bar` with `Ty` in the first impl.
238
272
pub ( crate ) fn predicates_for_object_candidate < ' tcx > (
239
273
ecx : & EvalCtxt < ' _ , ' tcx > ,
240
274
param_env : ty:: ParamEnv < ' tcx > ,
@@ -247,6 +281,8 @@ pub(crate) fn predicates_for_object_candidate<'tcx>(
247
281
tcx. super_predicates_of ( trait_ref. def_id ) . instantiate ( tcx, trait_ref. substs ) . predicates ,
248
282
) ;
249
283
for item in tcx. associated_items ( trait_ref. def_id ) . in_definition_order ( ) {
284
+ // FIXME(associated_const_equality): Also add associated consts to
285
+ // the requirements here.
250
286
if item. kind == ty:: AssocKind :: Type {
251
287
requirements. extend ( tcx. item_bounds ( item. def_id ) . subst ( tcx, trait_ref. substs ) ) ;
252
288
}
@@ -290,13 +326,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
290
326
if let ty:: Alias ( ty:: Projection , alias_ty) = * ty. kind ( )
291
327
&& let Some ( replacement) = self . mapping . get ( & alias_ty. def_id )
292
328
{
329
+ // We may have a case where our object type's projection bound is higher-ranked,
330
+ // but the where clauses we instantiated are not. We can solve this by instantiating
331
+ // the binder at the usage site.
293
332
let proj = self . ecx . instantiate_binder_with_infer ( * replacement) ;
294
- // Technically this folder could be fallible?
333
+ // FIXME: Technically this folder could be fallible?
295
334
let nested = self
296
335
. ecx
297
336
. eq ( self . param_env , alias_ty, proj. projection_ty )
298
337
. expect ( "expected to be able to unify goal projection with dyn's projection" ) ;
299
- // Technically we could register these too..
338
+ // FIXME: Technically we could register these too..
300
339
assert ! ( nested. is_empty( ) , "did not expect unification to have any nested goals" ) ;
301
340
proj. term . ty ( ) . unwrap ( )
302
341
} else {
0 commit comments