@@ -447,12 +447,31 @@ impl<'a> TyLoweringContext<'a> {
447
447
. db
448
448
. trait_data ( trait_ref. hir_trait_id ( ) )
449
449
. associated_type_by_name ( segment. name ) ;
450
+
450
451
match found {
451
452
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
+ ) ;
453
472
TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy {
454
473
associated_ty_id : to_assoc_type_id ( associated_ty) ,
455
- substitution : trait_ref . substitution ,
474
+ substitution,
456
475
} ) )
457
476
. intern ( Interner )
458
477
}
@@ -590,36 +609,48 @@ impl<'a> TyLoweringContext<'a> {
590
609
res,
591
610
Some ( segment. name . clone ( ) ) ,
592
611
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 ;
622
614
}
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
+ )
623
654
} ,
624
655
) ;
625
656
@@ -777,7 +808,15 @@ impl<'a> TyLoweringContext<'a> {
777
808
// handle defaults. In expression or pattern path segments without
778
809
// explicitly specified type arguments, missing type arguments are inferred
779
810
// (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) {
781
820
let defaults = self . db . generic_defaults ( def) ;
782
821
assert_eq ! ( total_len, defaults. len( ) ) ;
783
822
let parent_from = item_len - substs. len ( ) ;
@@ -966,9 +1005,28 @@ impl<'a> TyLoweringContext<'a> {
966
1005
None => return SmallVec :: new ( ) ,
967
1006
Some ( t) => t,
968
1007
} ;
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
+ ) ;
969
1027
let projection_ty = ProjectionTy {
970
1028
associated_ty_id : to_assoc_type_id ( associated_ty) ,
971
- substitution : super_trait_ref . substitution ,
1029
+ substitution,
972
1030
} ;
973
1031
let mut preds: SmallVec < [ _ ; 1 ] > = SmallVec :: with_capacity (
974
1032
binding. type_ref . as_ref ( ) . map_or ( 0 , |_| 1 ) + binding. bounds . len ( ) ,
0 commit comments