@@ -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