@@ -7,6 +7,7 @@ use super::{Certainty, EvalCtxt, Goal, QueryResult};
77use  rustc_errors:: ErrorGuaranteed ; 
88use  rustc_hir:: def:: DefKind ; 
99use  rustc_hir:: def_id:: DefId ; 
10+ use  rustc_hir:: LangItem ; 
1011use  rustc_infer:: infer:: InferCtxt ; 
1112use  rustc_infer:: traits:: query:: NoSolution ; 
1213use  rustc_infer:: traits:: specialization_graph:: LeafDef ; 
@@ -391,6 +392,96 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
391392    )  -> QueryResult < ' tcx >  { 
392393        bug ! ( "`Tuple` does not have an associated type: {:?}" ,  goal) ; 
393394    } 
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+     } 
394485} 
395486
396487/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. 
0 commit comments