@@ -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,97 @@ 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(erica_solver, 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+ . without_const ( ) ;
437+
438+ let mut nested_goals = ecx. infcx . eq (
439+ goal. param_env ,
440+ goal. predicate . term . ty ( ) . unwrap ( ) ,
441+ tcx. types . unit ,
442+ ) ?;
443+ nested_goals. push ( goal. with ( tcx, sized_predicate) ) ;
444+
445+ return ecx. evaluate_all_and_make_canonical_response ( nested_goals) ;
446+ }
447+
448+ ty:: Adt ( def, substs) if def. is_struct ( ) => {
449+ match def. non_enum_variant ( ) . fields . last ( ) {
450+ None => tcx. types . unit ,
451+ Some ( field_def) => {
452+ let self_ty = field_def. ty ( tcx, substs) ;
453+ let new_goal = goal. with (
454+ tcx,
455+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( tcx, self_ty) ) ,
456+ ) ;
457+ return ecx. evaluate_all_and_make_canonical_response ( vec ! [ new_goal] ) ;
458+ }
459+ }
460+ }
461+ ty:: Adt ( _, _) => tcx. types . unit ,
462+
463+ ty:: Tuple ( elements) => match elements. last ( ) {
464+ None => tcx. types . unit ,
465+ Some ( & self_ty) => {
466+ let new_goal = goal. with (
467+ tcx,
468+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( tcx, self_ty) ) ,
469+ ) ;
470+ return ecx. evaluate_all_and_make_canonical_response ( vec ! [ new_goal] ) ;
471+ }
472+ } ,
473+
474+ ty:: Infer ( ty:: FreshTy ( ..) | ty:: FreshIntTy ( ..) | ty:: FreshFloatTy ( ..) )
475+ | ty:: Bound ( ..) => bug ! (
476+ "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`" ,
477+ goal. predicate. self_ty( )
478+ ) ,
479+ } ;
480+
481+ let nested_goals =
482+ ecx. infcx . eq ( goal. param_env , goal. predicate . term . ty ( ) . unwrap ( ) , metadata_ty) ?;
483+ ecx. evaluate_all_and_make_canonical_response ( nested_goals)
484+ } )
485+ }
394486}
395487
396488/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
0 commit comments