@@ -112,12 +112,15 @@ pub enum SizedByDefault {
112112 No ,
113113}
114114
115+ #[ derive( Debug ) ]
115116struct ConvertedBinding < ' a , ' tcx > {
116117 item_name : Ident ,
117118 kind : ConvertedBindingKind < ' a , ' tcx > ,
119+ gen_args : & ' a GenericArgs < ' a > ,
118120 span : Span ,
119121}
120122
123+ #[ derive( Debug ) ]
121124enum ConvertedBindingKind < ' a , ' tcx > {
122125 Equality ( Ty < ' tcx > ) ,
123126 Constraint ( & ' a [ hir:: GenericBound < ' a > ] ) ,
@@ -323,6 +326,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
323326
324327 let tcx = self . tcx ( ) ;
325328 let generics = tcx. generics_of ( def_id) ;
329+ debug ! ( "generics: {:?}" , generics) ;
326330
327331 if generics. has_self {
328332 if generics. parent . is_some ( ) {
@@ -557,7 +561,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
557561 ConvertedBindingKind :: Constraint ( bounds)
558562 }
559563 } ;
560- ConvertedBinding { item_name : binding. ident , kind, span : binding. span }
564+ ConvertedBinding {
565+ item_name : binding. ident ,
566+ kind,
567+ gen_args : binding. gen_args ,
568+ span : binding. span ,
569+ }
561570 } )
562571 . collect ( ) ;
563572
@@ -918,60 +927,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
918927 dup_bindings : & mut FxHashMap < DefId , Span > ,
919928 path_span : Span ,
920929 ) -> Result < ( ) , ErrorReported > {
921- let tcx = self . tcx ( ) ;
922-
923- if !speculative {
924- // Given something like `U: SomeTrait<T = X>`, we want to produce a
925- // predicate like `<U as SomeTrait>::T = X`. This is somewhat
926- // subtle in the event that `T` is defined in a supertrait of
927- // `SomeTrait`, because in that case we need to upcast.
928- //
929- // That is, consider this case:
930- //
931- // ```
932- // trait SubTrait: SuperTrait<i32> { }
933- // trait SuperTrait<A> { type T; }
934- //
935- // ... B: SubTrait<T = foo> ...
936- // ```
937- //
938- // We want to produce `<B as SuperTrait<i32>>::T == foo`.
939-
940- // Find any late-bound regions declared in `ty` that are not
941- // declared in the trait-ref. These are not well-formed.
942- //
943- // Example:
944- //
945- // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
946- // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
947- if let ConvertedBindingKind :: Equality ( ty) = binding. kind {
948- let late_bound_in_trait_ref =
949- tcx. collect_constrained_late_bound_regions ( & trait_ref) ;
950- let late_bound_in_ty =
951- tcx. collect_referenced_late_bound_regions ( & ty:: Binder :: bind ( ty) ) ;
952- debug ! ( "late_bound_in_trait_ref = {:?}" , late_bound_in_trait_ref) ;
953- debug ! ( "late_bound_in_ty = {:?}" , late_bound_in_ty) ;
930+ // Given something like `U: SomeTrait<T = X>`, we want to produce a
931+ // predicate like `<U as SomeTrait>::T = X`. This is somewhat
932+ // subtle in the event that `T` is defined in a supertrait of
933+ // `SomeTrait`, because in that case we need to upcast.
934+ //
935+ // That is, consider this case:
936+ //
937+ // ```
938+ // trait SubTrait: SuperTrait<i32> { }
939+ // trait SuperTrait<A> { type T; }
940+ //
941+ // ... B: SubTrait<T = foo> ...
942+ // ```
943+ //
944+ // We want to produce `<B as SuperTrait<i32>>::T == foo`.
954945
955- // FIXME: point at the type params that don't have appropriate lifetimes:
956- // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
957- // ---- ---- ^^^^^^^
958- self . validate_late_bound_regions (
959- late_bound_in_trait_ref,
960- late_bound_in_ty,
961- |br_name| {
962- struct_span_err ! (
963- tcx. sess,
964- binding. span,
965- E0582 ,
966- "binding for associated type `{}` references {}, \
967- which does not appear in the trait input types",
968- binding. item_name,
969- br_name
970- )
971- } ,
972- ) ;
973- }
974- }
946+ debug ! (
947+ "add_predicates_for_ast_type_binding(hir_ref_id {:?}, trait_ref {:?}, binding {:?}, bounds {:?}" ,
948+ hir_ref_id, trait_ref, binding, bounds
949+ ) ;
950+ let tcx = self . tcx ( ) ;
975951
976952 let candidate =
977953 if self . trait_defines_associated_type_named ( trait_ref. def_id ( ) , binding. item_name ) {
@@ -1030,20 +1006,85 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10301006 . or_insert ( binding. span ) ;
10311007 }
10321008
1009+ // Include substitutions for generic parameters of associated types
1010+ let projection_ty = candidate. map_bound ( |trait_ref| {
1011+ let item_segment = hir:: PathSegment {
1012+ ident : assoc_ty. ident ,
1013+ hir_id : None ,
1014+ res : None ,
1015+ args : Some ( binding. gen_args ) ,
1016+ infer_args : false ,
1017+ } ;
1018+
1019+ let substs_trait_ref_and_assoc_item = self . create_substs_for_associated_item (
1020+ tcx,
1021+ path_span,
1022+ assoc_ty. def_id ,
1023+ & item_segment,
1024+ trait_ref. substs ,
1025+ ) ;
1026+
1027+ debug ! (
1028+ "add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}" ,
1029+ substs_trait_ref_and_assoc_item
1030+ ) ;
1031+
1032+ ty:: ProjectionTy {
1033+ item_def_id : assoc_ty. def_id ,
1034+ substs : substs_trait_ref_and_assoc_item,
1035+ }
1036+ } ) ;
1037+
1038+ if !speculative {
1039+ // Find any late-bound regions declared in `ty` that are not
1040+ // declared in the trait-ref or assoc_ty. These are not well-formed.
1041+ //
1042+ // Example:
1043+ //
1044+ // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
1045+ // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
1046+ if let ConvertedBindingKind :: Equality ( ty) = binding. kind {
1047+ let late_bound_in_trait_ref =
1048+ tcx. collect_constrained_late_bound_regions ( & projection_ty) ;
1049+ let late_bound_in_ty =
1050+ tcx. collect_referenced_late_bound_regions ( & ty:: Binder :: bind ( ty) ) ;
1051+ debug ! ( "late_bound_in_trait_ref = {:?}" , late_bound_in_trait_ref) ;
1052+ debug ! ( "late_bound_in_ty = {:?}" , late_bound_in_ty) ;
1053+
1054+ // FIXME: point at the type params that don't have appropriate lifetimes:
1055+ // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
1056+ // ---- ---- ^^^^^^^
1057+ self . validate_late_bound_regions (
1058+ late_bound_in_trait_ref,
1059+ late_bound_in_ty,
1060+ |br_name| {
1061+ struct_span_err ! (
1062+ tcx. sess,
1063+ binding. span,
1064+ E0582 ,
1065+ "binding for associated type `{}` references {}, \
1066+ which does not appear in the trait input types",
1067+ binding. item_name,
1068+ br_name
1069+ )
1070+ } ,
1071+ ) ;
1072+ }
1073+ }
1074+
10331075 match binding. kind {
10341076 ConvertedBindingKind :: Equality ( ref ty) => {
10351077 // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
10361078 // the "projection predicate" for:
10371079 //
10381080 // `<T as Iterator>::Item = u32`
10391081 bounds. projection_bounds . push ( (
1040- candidate. map_bound ( |trait_ref| ty:: ProjectionPredicate {
1041- projection_ty : ty:: ProjectionTy :: from_ref_and_name (
1042- tcx,
1043- trait_ref,
1044- binding. item_name ,
1045- ) ,
1046- ty,
1082+ projection_ty. map_bound ( |projection_ty| {
1083+ debug ! (
1084+ "add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}" ,
1085+ projection_ty, projection_ty. substs
1086+ ) ;
1087+ ty:: ProjectionPredicate { projection_ty, ty }
10471088 } ) ,
10481089 binding. span ,
10491090 ) ) ;
@@ -1055,7 +1096,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10551096 //
10561097 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
10571098 // parameter to have a skipped binder.
1058- let param_ty = tcx. mk_projection ( assoc_ty. def_id , candidate. skip_binder ( ) . substs ) ;
1099+ let param_ty =
1100+ tcx. mk_projection ( assoc_ty. def_id , projection_ty. skip_binder ( ) . substs ) ;
10591101 self . add_bounds ( param_ty, ast_bounds, bounds) ;
10601102 }
10611103 }
0 commit comments