@@ -379,6 +379,47 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
379
379
) -> QueryResult < ' tcx > {
380
380
let tcx = ecx. tcx ( ) ;
381
381
ecx. probe_misc_candidate ( "builtin pointee" ) . enter ( |ecx| {
382
+ let check_tail = |ecx : & mut EvalCtxt < ' _ , ' tcx > ,
383
+ goal : Goal < ' tcx , Self > ,
384
+ tail_ty : Ty < ' tcx > |
385
+ -> QueryResult < ' tcx > {
386
+ // If `Self: Sized`, then `<Self as Pointee>::Metadata == ()`.
387
+ let sized_probe =
388
+ ecx. probe_misc_candidate ( "builtin pointee via sized" ) . enter ( |ecx| {
389
+ let sized_predicate = ty:: TraitRef :: from_lang_item (
390
+ tcx,
391
+ LangItem :: Sized ,
392
+ DUMMY_SP ,
393
+ [ ty:: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
394
+ ) ;
395
+ // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
396
+ ecx. add_goal ( GoalSource :: Misc , goal. with ( tcx, sized_predicate) ) ;
397
+ ecx. eq ( goal. param_env , goal. predicate . term , tcx. types . unit . into ( ) )
398
+ . expect ( "expected goal term to be fully unconstrained" ) ;
399
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
400
+ } ) ;
401
+
402
+ if let Ok ( response) = sized_probe {
403
+ return Ok ( response) ;
404
+ }
405
+
406
+ // If `Self: ?Sized` and `Self == Tail`, then we can't normalize further.
407
+ if goal. predicate . self_ty ( ) == tail_ty {
408
+ return Err ( NoSolution ) ;
409
+ }
410
+
411
+ // If `Self: ?Sized` and `Self != Tail`, then normalize from
412
+ // `<Self as Pointee>::Metadata` to `<Tail as Pointee>::Metadata`.
413
+ let metadata_def_id = tcx. require_lang_item ( LangItem :: Metadata , None ) ;
414
+ let projection_ty = ty:: AliasTy :: new ( tcx, metadata_def_id, [ tail_ty] ) ;
415
+ let predicate =
416
+ ty:: ProjectionPredicate { projection_ty, term : goal. predicate . term } ;
417
+
418
+ // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
419
+ ecx. add_goal ( GoalSource :: Misc , goal. with ( tcx, predicate) ) ;
420
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
421
+ } ;
422
+
382
423
let metadata_ty = match goal. predicate . self_ty ( ) . kind ( ) {
383
424
ty:: Bool
384
425
| ty:: Char
@@ -423,29 +464,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
423
464
ty:: Adt ( def, args) if def. is_struct ( ) => match def. non_enum_variant ( ) . tail_opt ( ) {
424
465
None => tcx. types . unit ,
425
466
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 ) ;
467
+ let tail_ty = field_def. ty ( tcx, args) ;
468
+ return check_tail ( ecx, goal, tail_ty) ;
434
469
}
435
470
} ,
436
471
ty:: Adt ( _, _) => tcx. types . unit ,
437
472
438
473
ty:: Tuple ( elements) => match elements. last ( ) {
439
474
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
- }
475
+ Some ( & tail_ty) => return check_tail ( ecx, goal, tail_ty) ,
449
476
} ,
450
477
451
478
ty:: Infer (
0 commit comments