@@ -235,6 +235,40 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
235235 }
236236}
237237
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.
238272pub ( crate ) fn predicates_for_object_candidate < ' tcx > (
239273 ecx : & EvalCtxt < ' _ , ' tcx > ,
240274 param_env : ty:: ParamEnv < ' tcx > ,
@@ -247,6 +281,8 @@ pub(crate) fn predicates_for_object_candidate<'tcx>(
247281 tcx. super_predicates_of ( trait_ref. def_id ) . instantiate ( tcx, trait_ref. substs ) . predicates ,
248282 ) ;
249283 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.
250286 if item. kind == ty:: AssocKind :: Type {
251287 requirements. extend ( tcx. item_bounds ( item. def_id ) . subst ( tcx, trait_ref. substs ) ) ;
252288 }
@@ -290,13 +326,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
290326 if let ty:: Alias ( ty:: Projection , alias_ty) = * ty. kind ( )
291327 && let Some ( replacement) = self . mapping . get ( & alias_ty. def_id )
292328 {
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.
293332 let proj = self . ecx . instantiate_binder_with_infer ( * replacement) ;
294- // Technically this folder could be fallible?
333+ // FIXME: Technically this folder could be fallible?
295334 let nested = self
296335 . ecx
297336 . eq ( self . param_env , alias_ty, proj. projection_ty )
298337 . 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..
300339 assert ! ( nested. is_empty( ) , "did not expect unification to have any nested goals" ) ;
301340 proj. term . ty ( ) . unwrap ( )
302341 } else {
0 commit comments