1- use  crate :: traits:: specialization_graph; 
1+ use  crate :: traits:: specialization_graph:: { self ,   LeafDef ,   Node } ; 
22
33use  super :: assembly:: structural_traits:: AsyncCallableRelevantTypes ; 
44use  super :: assembly:: { self ,  structural_traits,  Candidate } ; 
@@ -9,7 +9,6 @@ use rustc_infer::infer::InferCtxt;
99use  rustc_infer:: traits:: query:: NoSolution ; 
1010use  rustc_infer:: traits:: solve:: inspect:: ProbeKind ; 
1111use  rustc_infer:: traits:: solve:: MaybeCause ; 
12- use  rustc_infer:: traits:: specialization_graph:: LeafDef ; 
1312use  rustc_infer:: traits:: Reveal ; 
1413use  rustc_middle:: traits:: solve:: { CandidateSource ,  Certainty ,  Goal ,  QueryResult } ; 
1514use  rustc_middle:: traits:: BuiltinImplSource ; 
@@ -189,8 +188,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
189188            // In case the associated item is hidden due to specialization, we have to 
190189            // return ambiguity this would otherwise be incomplete, resulting in 
191190            // unsoundness during coherence (#105782). 
192-             let  Some ( assoc_def)  = fetch_eligible_assoc_item_def ( 
193-                 ecx, 
191+             let  Some ( assoc_def)  = ecx. fetch_eligible_assoc_item_def ( 
194192                goal. param_env , 
195193                goal_trait_ref, 
196194                goal. predicate . def_id ( ) , 
@@ -235,16 +233,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
235233            // 
236234            // And then map these args to the args of the defining impl of `Assoc`, going 
237235            // from `[u32, u64]` to `[u32, i32, u64]`. 
238-             let  impl_args_with_gat =
239-                 goal. predicate . alias . args . rebase_onto ( tcx,  goal_trait_ref. def_id ,  impl_args) ; 
240-             let  args = ecx. translate_args ( 
241-                 goal. param_env , 
242-                 impl_def_id, 
243-                 impl_args_with_gat, 
244-                 assoc_def. defining_node , 
245-             ) ; 
236+             let  associated_item_args =
237+                 ecx. translate_args ( & assoc_def,  goal,  impl_def_id,  impl_args,  impl_trait_ref) ?; 
246238
247-             if  !tcx. check_args_compatible ( assoc_def. item . def_id ,  args )  { 
239+             if  !tcx. check_args_compatible ( assoc_def. item . def_id ,  associated_item_args )  { 
248240                return  error_response ( 
249241                    ecx, 
250242                    "associated item has mismatched generic item arguments" , 
@@ -272,7 +264,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
272264                ty:: AssocKind :: Fn  => unreachable ! ( "we should never project to a fn" ) , 
273265            } ; 
274266
275-             ecx. instantiate_normalizes_to_term ( goal,  term. instantiate ( tcx,  args ) ) ; 
267+             ecx. instantiate_normalizes_to_term ( goal,  term. instantiate ( tcx,  associated_item_args ) ) ; 
276268            ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) 
277269        } ) 
278270    } 
@@ -889,38 +881,79 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
889881    } 
890882} 
891883
892- /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. 
893- /// 
894- /// FIXME: We should merge these 3 implementations as it's likely that they otherwise 
895- /// diverge. 
896- #[ instrument( level = "trace" ,  skip( ecx,  param_env) ,  ret) ]  
897- fn  fetch_eligible_assoc_item_def < ' tcx > ( 
898-     ecx :  & EvalCtxt < ' _ ,  InferCtxt < ' tcx > > , 
899-     param_env :  ty:: ParamEnv < ' tcx > , 
900-     goal_trait_ref :  ty:: TraitRef < ' tcx > , 
901-     trait_assoc_def_id :  DefId , 
902-     impl_def_id :  DefId , 
903- )  -> Result < Option < LeafDef > ,  NoSolution >  { 
904-     let  node_item =
905-         specialization_graph:: assoc_def ( ecx. interner ( ) ,  impl_def_id,  trait_assoc_def_id) 
906-             . map_err ( |ErrorGuaranteed  {  .. } | NoSolution ) ?; 
907- 
908-     let  eligible = if  node_item. is_final ( )  { 
909-         // Non-specializable items are always projectable. 
910-         true 
911-     }  else  { 
912-         // Only reveal a specializable default if we're past type-checking 
913-         // and the obligation is monomorphic, otherwise passes such as 
914-         // transmute checking and polymorphic MIR optimizations could 
915-         // get a result which isn't correct for all monomorphizations. 
916-         if  param_env. reveal ( )  == Reveal :: All  { 
917-             let  poly_trait_ref = ecx. resolve_vars_if_possible ( goal_trait_ref) ; 
918-             !poly_trait_ref. still_further_specializable ( ) 
884+ impl < ' tcx >  EvalCtxt < ' _ ,  InferCtxt < ' tcx > >  { 
885+     fn  translate_args ( 
886+         & mut  self , 
887+         assoc_def :  & LeafDef , 
888+         goal :  Goal < ' tcx ,  ty:: NormalizesTo < ' tcx > > , 
889+         impl_def_id :  DefId , 
890+         impl_args :  ty:: GenericArgsRef < ' tcx > , 
891+         impl_trait_ref :  rustc_type_ir:: TraitRef < TyCtxt < ' tcx > > , 
892+     )  -> Result < ty:: GenericArgsRef < ' tcx > ,  NoSolution >  { 
893+         let  tcx = self . interner ( ) ; 
894+         Ok ( match  assoc_def. defining_node  { 
895+             Node :: Trait ( _)  => goal. predicate . alias . args , 
896+             Node :: Impl ( target_impl_def_id)  => { 
897+                 if  target_impl_def_id == impl_def_id { 
898+                     // Same impl, no need to fully translate, just a rebase from 
899+                     // the trait is sufficient. 
900+                     goal. predicate . alias . args . rebase_onto ( tcx,  impl_trait_ref. def_id ,  impl_args) 
901+                 }  else  { 
902+                     let  target_args = self . fresh_args_for_item ( target_impl_def_id) ; 
903+                     let  target_trait_ref = tcx
904+                         . impl_trait_ref ( target_impl_def_id) 
905+                         . unwrap ( ) 
906+                         . instantiate ( tcx,  target_args) ; 
907+                     // Relate source impl to target impl by equating trait refs. 
908+                     self . eq ( goal. param_env ,  impl_trait_ref,  target_trait_ref) ?; 
909+                     // Also add predicates since they may be needed to constrain the 
910+                     // target impl's params. 
911+                     self . add_goals ( 
912+                         GoalSource :: Misc , 
913+                         tcx. predicates_of ( target_impl_def_id) 
914+                             . instantiate ( tcx,  target_args) 
915+                             . into_iter ( ) 
916+                             . map ( |( pred,  _) | goal. with ( tcx,  pred) ) , 
917+                     ) ; 
918+                     goal. predicate . alias . args . rebase_onto ( tcx,  impl_trait_ref. def_id ,  target_args) 
919+                 } 
920+             } 
921+         } ) 
922+     } 
923+ 
924+     /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. 
925+ /// 
926+ /// FIXME: We should merge these 3 implementations as it's likely that they otherwise 
927+ /// diverge. 
928+ #[ instrument( level = "trace" ,  skip( self ,  param_env) ,  ret) ]  
929+     fn  fetch_eligible_assoc_item_def ( 
930+         & self , 
931+         param_env :  ty:: ParamEnv < ' tcx > , 
932+         goal_trait_ref :  ty:: TraitRef < ' tcx > , 
933+         trait_assoc_def_id :  DefId , 
934+         impl_def_id :  DefId , 
935+     )  -> Result < Option < LeafDef > ,  NoSolution >  { 
936+         let  node_item =
937+             specialization_graph:: assoc_def ( self . interner ( ) ,  impl_def_id,  trait_assoc_def_id) 
938+                 . map_err ( |ErrorGuaranteed  {  .. } | NoSolution ) ?; 
939+ 
940+         let  eligible = if  node_item. is_final ( )  { 
941+             // Non-specializable items are always projectable. 
942+             true 
919943        }  else  { 
920-             trace ! ( ?node_item. item. def_id,  "not eligible due to default" ) ; 
921-             false 
922-         } 
923-     } ; 
944+             // Only reveal a specializable default if we're past type-checking 
945+             // and the obligation is monomorphic, otherwise passes such as 
946+             // transmute checking and polymorphic MIR optimizations could 
947+             // get a result which isn't correct for all monomorphizations. 
948+             if  param_env. reveal ( )  == Reveal :: All  { 
949+                 let  poly_trait_ref = self . resolve_vars_if_possible ( goal_trait_ref) ; 
950+                 !poly_trait_ref. still_further_specializable ( ) 
951+             }  else  { 
952+                 trace ! ( ?node_item. item. def_id,  "not eligible due to default" ) ; 
953+                 false 
954+             } 
955+         } ; 
924956
925-     if  eligible {  Ok ( Some ( node_item) )  }  else  {  Ok ( None )  } 
957+         if  eligible {  Ok ( Some ( node_item) )  }  else  {  Ok ( None )  } 
958+     } 
926959} 
0 commit comments