@@ -379,6 +379,45 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
379379 ) -> QueryResult < ' tcx > {
380380 let tcx = ecx. tcx ( ) ;
381381 ecx. probe_misc_candidate ( "builtin pointee" ) . enter ( |ecx| {
382+ fn handle_product_ty < ' tcx > (
383+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
384+ goal : Goal < ' tcx , NormalizesTo < ' tcx > > ,
385+ tail_ty : Ty < ' tcx > ,
386+ ) -> QueryResult < ' tcx > {
387+ let tcx = ecx. tcx ( ) ;
388+
389+ // If `Self: Sized`, then `<Self as Pointee>::Metadata == ()`.
390+ let sized_probe =
391+ ecx. probe_misc_candidate ( "builtin pointee via sized" ) . enter ( |ecx| {
392+ let sized_predicate = ty:: TraitRef :: from_lang_item (
393+ tcx,
394+ LangItem :: Sized ,
395+ DUMMY_SP ,
396+ [ ty:: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
397+ ) ;
398+ // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
399+ ecx. add_goal ( GoalSource :: Misc , goal. with ( tcx, sized_predicate) ) ;
400+ ecx. eq ( goal. param_env , goal. predicate . term , tcx. types . unit . into ( ) )
401+ . expect ( "expected goal term to be fully unconstrained" ) ;
402+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
403+ } ) ;
404+
405+ if let Ok ( response) = sized_probe {
406+ return Ok ( response) ;
407+ }
408+
409+ // Otherwise, if `Self: ?Sized`, then normalize from
410+ // `<Self as Pointee>::Metadata` to `<Tail as Pointee>::Metadata`.
411+ let metadata_def_id = tcx. require_lang_item ( LangItem :: Metadata , None ) ;
412+ let projection_ty = ty:: AliasTy :: new ( tcx, metadata_def_id, [ tail_ty] ) ;
413+ let predicate =
414+ ty:: ProjectionPredicate { projection_ty, term : goal. predicate . term } ;
415+
416+ // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
417+ ecx. add_goal ( GoalSource :: Misc , goal. with ( tcx, predicate) ) ;
418+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
419+ }
420+
382421 let metadata_ty = match goal. predicate . self_ty ( ) . kind ( ) {
383422 ty:: Bool
384423 | ty:: Char
@@ -423,29 +462,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
423462 ty:: Adt ( def, args) if def. is_struct ( ) => match def. non_enum_variant ( ) . tail_opt ( ) {
424463 None => tcx. types . unit ,
425464 Some ( field_def) => {
426- let self_ty = field_def. ty ( tcx, args) ;
427- // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
428- ecx. add_goal (
429- GoalSource :: Misc ,
430- goal. with ( tcx, goal. predicate . with_self_ty ( tcx, self_ty) ) ,
431- ) ;
432- return ecx
433- . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) ;
465+ let tail_ty = field_def. ty ( tcx, args) ;
466+ return handle_product_ty ( ecx, goal, tail_ty) ;
434467 }
435468 } ,
436469 ty:: Adt ( _, _) => tcx. types . unit ,
437470
438471 ty:: Tuple ( elements) => match elements. last ( ) {
439472 None => tcx. types . unit ,
440- Some ( & self_ty) => {
441- // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
442- ecx. add_goal (
443- GoalSource :: Misc ,
444- goal. with ( tcx, goal. predicate . with_self_ty ( tcx, self_ty) ) ,
445- ) ;
446- return ecx
447- . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) ;
448- }
473+ Some ( & tail_ty) => return handle_product_ty ( ecx, goal, tail_ty) ,
449474 } ,
450475
451476 ty:: Infer (
0 commit comments