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