1
- use crate :: traits:: specialization_graph;
1
+ use crate :: traits:: specialization_graph:: { self , LeafDef , Node } ;
2
2
3
3
use super :: assembly:: structural_traits:: AsyncCallableRelevantTypes ;
4
4
use super :: assembly:: { self , structural_traits, Candidate } ;
@@ -9,7 +9,6 @@ use rustc_infer::infer::InferCtxt;
9
9
use rustc_infer:: traits:: query:: NoSolution ;
10
10
use rustc_infer:: traits:: solve:: inspect:: ProbeKind ;
11
11
use rustc_infer:: traits:: solve:: MaybeCause ;
12
- use rustc_infer:: traits:: specialization_graph:: LeafDef ;
13
12
use rustc_infer:: traits:: Reveal ;
14
13
use rustc_middle:: traits:: solve:: { CandidateSource , Certainty , Goal , QueryResult } ;
15
14
use rustc_middle:: traits:: BuiltinImplSource ;
@@ -235,16 +234,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
235
234
//
236
235
// And then map these args to the args of the defining impl of `Assoc`, going
237
236
// 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
- ) ;
237
+ let associated_item_args =
238
+ translate_args ( ecx, & assoc_def, goal, impl_def_id, impl_args, impl_trait_ref) ?;
246
239
247
- if !tcx. check_args_compatible ( assoc_def. item . def_id , args ) {
240
+ if !tcx. check_args_compatible ( assoc_def. item . def_id , associated_item_args ) {
248
241
return error_response (
249
242
ecx,
250
243
"associated item has mismatched generic item arguments" ,
@@ -272,7 +265,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
272
265
ty:: AssocKind :: Fn => unreachable ! ( "we should never project to a fn" ) ,
273
266
} ;
274
267
275
- ecx. instantiate_normalizes_to_term ( goal, term. instantiate ( tcx, args ) ) ;
268
+ ecx. instantiate_normalizes_to_term ( goal, term. instantiate ( tcx, associated_item_args ) ) ;
276
269
ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
277
270
} )
278
271
}
@@ -889,6 +882,43 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
889
882
}
890
883
}
891
884
885
+ fn translate_args < ' tcx > (
886
+ ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
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 = ecx. 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 = ecx. fresh_args_for_item ( target_impl_def_id) ;
903
+ let target_trait_ref =
904
+ tcx. impl_trait_ref ( target_impl_def_id) . unwrap ( ) . instantiate ( tcx, target_args) ;
905
+ // Relate source impl to target impl by equating trait refs.
906
+ ecx. eq ( goal. param_env , impl_trait_ref, target_trait_ref) ?;
907
+ // Also add predicates since they may be needed to constrain the
908
+ // target impl's params.
909
+ ecx. add_goals (
910
+ GoalSource :: Misc ,
911
+ tcx. predicates_of ( target_impl_def_id)
912
+ . instantiate ( tcx, target_args)
913
+ . into_iter ( )
914
+ . map ( |( pred, _) | goal. with ( tcx, pred) ) ,
915
+ ) ;
916
+ goal. predicate . alias . args . rebase_onto ( tcx, impl_trait_ref. def_id , target_args)
917
+ }
918
+ }
919
+ } )
920
+ }
921
+
892
922
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
893
923
///
894
924
/// FIXME: We should merge these 3 implementations as it's likely that they otherwise
0 commit comments