@@ -447,12 +447,31 @@ impl<'a> TyLoweringContext<'a> {
447447                            . db 
448448                            . trait_data ( trait_ref. hir_trait_id ( ) ) 
449449                            . associated_type_by_name ( segment. name ) ; 
450+ 
450451                        match  found { 
451452                            Some ( associated_ty)  => { 
452-                                 // FIXME handle type parameters on the segment 
453+                                 // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent 
454+                                 // generic params. It's inefficient to splice the `Substitution`s, so we may want 
455+                                 // that method to optionally take parent `Substitution` as we already know them at 
456+                                 // this point (`trait_ref.substitution`). 
457+                                 let  substitution = self . substs_from_path_segment ( 
458+                                     segment, 
459+                                     Some ( associated_ty. into ( ) ) , 
460+                                     false , 
461+                                     None , 
462+                                 ) ; 
463+                                 let  len_self =
464+                                     generics ( self . db . upcast ( ) ,  associated_ty. into ( ) ) . len_self ( ) ; 
465+                                 let  substitution = Substitution :: from_iter ( 
466+                                     Interner , 
467+                                     substitution
468+                                         . iter ( Interner ) 
469+                                         . take ( len_self) 
470+                                         . chain ( trait_ref. substitution . iter ( Interner ) ) , 
471+                                 ) ; 
453472                                TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy  { 
454473                                    associated_ty_id :  to_assoc_type_id ( associated_ty) , 
455-                                     substitution :  trait_ref . substitution , 
474+                                     substitution, 
456475                                } ) ) 
457476                                . intern ( Interner ) 
458477                            } 
@@ -590,36 +609,48 @@ impl<'a> TyLoweringContext<'a> {
590609            res, 
591610            Some ( segment. name . clone ( ) ) , 
592611            move  |name,  t,  associated_ty| { 
593-                 if  name == segment. name  { 
594-                     let  substs = match  self . type_param_mode  { 
595-                         ParamLoweringMode :: Placeholder  => { 
596-                             // if we're lowering to placeholders, we have to put 
597-                             // them in now 
598-                             let  generics = generics ( 
599-                                 self . db . upcast ( ) , 
600-                                 self . resolver 
601-                                     . generic_def ( ) 
602-                                     . expect ( "there should be generics if there's a generic param" ) , 
603-                             ) ; 
604-                             let  s = generics. placeholder_subst ( self . db ) ; 
605-                             s. apply ( t. substitution . clone ( ) ,  Interner ) 
606-                         } 
607-                         ParamLoweringMode :: Variable  => t. substitution . clone ( ) , 
608-                     } ; 
609-                     // We need to shift in the bound vars, since 
610-                     // associated_type_shorthand_candidates does not do that 
611-                     let  substs = substs. shifted_in_from ( Interner ,  self . in_binders ) ; 
612-                     // FIXME handle type parameters on the segment 
613-                     Some ( 
614-                         TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy  { 
615-                             associated_ty_id :  to_assoc_type_id ( associated_ty) , 
616-                             substitution :  substs, 
617-                         } ) ) 
618-                         . intern ( Interner ) , 
619-                     ) 
620-                 }  else  { 
621-                     None 
612+                 if  name != segment. name  { 
613+                     return  None ; 
622614                } 
615+ 
616+                 // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent 
617+                 // generic params. It's inefficient to splice the `Substitution`s, so we may want 
618+                 // that method to optionally take parent `Substitution` as we already know them at 
619+                 // this point (`t.substitution`). 
620+                 let  substs = self . substs_from_path_segment ( 
621+                     segment. clone ( ) , 
622+                     Some ( associated_ty. into ( ) ) , 
623+                     false , 
624+                     None , 
625+                 ) ; 
626+ 
627+                 let  len_self = generics ( self . db . upcast ( ) ,  associated_ty. into ( ) ) . len_self ( ) ; 
628+ 
629+                 let  substs = Substitution :: from_iter ( 
630+                     Interner , 
631+                     substs. iter ( Interner ) . take ( len_self) . chain ( t. substitution . iter ( Interner ) ) , 
632+                 ) ; 
633+ 
634+                 let  substs = match  self . type_param_mode  { 
635+                     ParamLoweringMode :: Placeholder  => { 
636+                         // if we're lowering to placeholders, we have to put 
637+                         // them in now 
638+                         let  generics = generics ( self . db . upcast ( ) ,  def) ; 
639+                         let  s = generics. placeholder_subst ( self . db ) ; 
640+                         s. apply ( substs,  Interner ) 
641+                     } 
642+                     ParamLoweringMode :: Variable  => substs, 
643+                 } ; 
644+                 // We need to shift in the bound vars, since 
645+                 // associated_type_shorthand_candidates does not do that 
646+                 let  substs = substs. shifted_in_from ( Interner ,  self . in_binders ) ; 
647+                 Some ( 
648+                     TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy  { 
649+                         associated_ty_id :  to_assoc_type_id ( associated_ty) , 
650+                         substitution :  substs, 
651+                     } ) ) 
652+                     . intern ( Interner ) , 
653+                 ) 
623654            } , 
624655        ) ; 
625656
@@ -777,7 +808,15 @@ impl<'a> TyLoweringContext<'a> {
777808        // handle defaults. In expression or pattern path segments without 
778809        // explicitly specified type arguments, missing type arguments are inferred 
779810        // (i.e. defaults aren't used). 
780-         if  !infer_args || had_explicit_args { 
811+         // Generic parameters for associated types are not supposed to have defaults, so we just 
812+         // ignore them. 
813+         let  is_assoc_ty = if  let  GenericDefId :: TypeAliasId ( id)  = def { 
814+             let  container = id. lookup ( self . db . upcast ( ) ) . container ; 
815+             matches ! ( container,  ItemContainerId :: TraitId ( _) ) 
816+         }  else  { 
817+             false 
818+         } ; 
819+         if  !is_assoc_ty && ( !infer_args || had_explicit_args)  { 
781820            let  defaults = self . db . generic_defaults ( def) ; 
782821            assert_eq ! ( total_len,  defaults. len( ) ) ; 
783822            let  parent_from = item_len - substs. len ( ) ; 
@@ -966,9 +1005,28 @@ impl<'a> TyLoweringContext<'a> {
9661005                    None  => return  SmallVec :: new ( ) , 
9671006                    Some ( t)  => t, 
9681007                } ; 
1008+                 // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent 
1009+                 // generic params. It's inefficient to splice the `Substitution`s, so we may want 
1010+                 // that method to optionally take parent `Substitution` as we already know them at 
1011+                 // this point (`super_trait_ref.substitution`). 
1012+                 let  substitution = self . substs_from_path_segment ( 
1013+                     // FIXME: This is hack. We shouldn't really build `PathSegment` directly. 
1014+                     PathSegment  {  name :  & binding. name ,  args_and_bindings :  binding. args . as_deref ( )  } , 
1015+                     Some ( associated_ty. into ( ) ) , 
1016+                     false ,  // this is not relevant 
1017+                     Some ( super_trait_ref. self_type_parameter ( Interner ) ) , 
1018+                 ) ; 
1019+                 let  self_params = generics ( self . db . upcast ( ) ,  associated_ty. into ( ) ) . len_self ( ) ; 
1020+                 let  substitution = Substitution :: from_iter ( 
1021+                     Interner , 
1022+                     substitution
1023+                         . iter ( Interner ) 
1024+                         . take ( self_params) 
1025+                         . chain ( super_trait_ref. substitution . iter ( Interner ) ) , 
1026+                 ) ; 
9691027                let  projection_ty = ProjectionTy  { 
9701028                    associated_ty_id :  to_assoc_type_id ( associated_ty) , 
971-                     substitution :  super_trait_ref . substitution , 
1029+                     substitution, 
9721030                } ; 
9731031                let  mut  preds:  SmallVec < [ _ ;  1 ] >  = SmallVec :: with_capacity ( 
9741032                    binding. type_ref . as_ref ( ) . map_or ( 0 ,  |_| 1 )  + binding. bounds . len ( ) , 
0 commit comments