@@ -7,6 +7,7 @@ use super::{Certainty, EvalCtxt, Goal, QueryResult};
7
7
use rustc_errors:: ErrorGuaranteed ;
8
8
use rustc_hir:: def:: DefKind ;
9
9
use rustc_hir:: def_id:: DefId ;
10
+ use rustc_hir:: LangItem ;
10
11
use rustc_infer:: infer:: InferCtxt ;
11
12
use rustc_infer:: traits:: query:: NoSolution ;
12
13
use rustc_infer:: traits:: specialization_graph:: LeafDef ;
@@ -391,6 +392,96 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
391
392
) -> QueryResult < ' tcx > {
392
393
bug ! ( "`Tuple` does not have an associated type: {:?}" , goal) ;
393
394
}
395
+
396
+ fn consider_builtin_pointee_candidate (
397
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
398
+ goal : Goal < ' tcx , Self > ,
399
+ ) -> QueryResult < ' tcx > {
400
+ let tcx = ecx. tcx ( ) ;
401
+ ecx. infcx . probe ( |_| {
402
+ let metadata_ty = match goal. predicate . self_ty ( ) . kind ( ) {
403
+ ty:: Bool
404
+ | ty:: Char
405
+ | ty:: Int ( ..)
406
+ | ty:: Uint ( ..)
407
+ | ty:: Float ( ..)
408
+ | ty:: Array ( ..)
409
+ | ty:: RawPtr ( ..)
410
+ | ty:: Ref ( ..)
411
+ | ty:: FnDef ( ..)
412
+ | ty:: FnPtr ( ..)
413
+ | ty:: Closure ( ..)
414
+ | ty:: Infer ( ty:: IntVar ( ..) | ty:: FloatVar ( ..) )
415
+ | ty:: Generator ( ..)
416
+ | ty:: GeneratorWitness ( ..)
417
+ | ty:: Never
418
+ | ty:: Foreign ( ..) => tcx. types . unit ,
419
+
420
+ ty:: Error ( e) => tcx. ty_error_with_guaranteed ( * e) ,
421
+
422
+ ty:: Str | ty:: Slice ( _) => tcx. types . usize ,
423
+
424
+ ty:: Dynamic ( _, _, _) => {
425
+ let dyn_metadata = tcx. require_lang_item ( LangItem :: DynMetadata , None ) ;
426
+ tcx. bound_type_of ( dyn_metadata)
427
+ . subst ( tcx, & [ ty:: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] )
428
+ }
429
+
430
+ ty:: Infer ( ty:: TyVar ( ..) ) | ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
431
+ // FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints.
432
+ let sized_predicate = ty:: Binder :: dummy ( tcx. at ( DUMMY_SP ) . mk_trait_ref (
433
+ LangItem :: Sized ,
434
+ [ ty:: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
435
+ ) ) ;
436
+
437
+ let mut nested_goals = ecx. infcx . eq (
438
+ goal. param_env ,
439
+ goal. predicate . term . ty ( ) . unwrap ( ) ,
440
+ tcx. types . unit ,
441
+ ) ?;
442
+ nested_goals. push ( goal. with ( tcx, sized_predicate) ) ;
443
+
444
+ return ecx. evaluate_all_and_make_canonical_response ( nested_goals) ;
445
+ }
446
+
447
+ ty:: Adt ( def, substs) if def. is_struct ( ) => {
448
+ match def. non_enum_variant ( ) . fields . last ( ) {
449
+ None => tcx. types . unit ,
450
+ Some ( field_def) => {
451
+ let self_ty = field_def. ty ( tcx, substs) ;
452
+ let new_goal = goal. with (
453
+ tcx,
454
+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( tcx, self_ty) ) ,
455
+ ) ;
456
+ return ecx. evaluate_all_and_make_canonical_response ( vec ! [ new_goal] ) ;
457
+ }
458
+ }
459
+ }
460
+ ty:: Adt ( _, _) => tcx. types . unit ,
461
+
462
+ ty:: Tuple ( elements) => match elements. last ( ) {
463
+ None => tcx. types . unit ,
464
+ Some ( & self_ty) => {
465
+ let new_goal = goal. with (
466
+ tcx,
467
+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( tcx, self_ty) ) ,
468
+ ) ;
469
+ return ecx. evaluate_all_and_make_canonical_response ( vec ! [ new_goal] ) ;
470
+ }
471
+ } ,
472
+
473
+ ty:: Infer ( ty:: FreshTy ( ..) | ty:: FreshIntTy ( ..) | ty:: FreshFloatTy ( ..) )
474
+ | ty:: Bound ( ..) => bug ! (
475
+ "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`" ,
476
+ goal. predicate. self_ty( )
477
+ ) ,
478
+ } ;
479
+
480
+ let nested_goals =
481
+ ecx. infcx . eq ( goal. param_env , goal. predicate . term . ty ( ) . unwrap ( ) , metadata_ty) ?;
482
+ ecx. evaluate_all_and_make_canonical_response ( nested_goals)
483
+ } )
484
+ }
394
485
}
395
486
396
487
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
0 commit comments