@@ -812,13 +812,13 @@ impl<'a> TyLoweringContext<'a> {
812
812
infer_args : bool ,
813
813
explicit_self_ty : Option < Ty > ,
814
814
) -> Substitution {
815
- // Remember that the item's own generic args come before its parent's.
816
- let mut substs = Vec :: new ( ) ;
817
- let def = if let Some ( d ) = def {
818
- d
819
- } else {
820
- return Substitution :: empty ( Interner ) ;
821
- } ;
815
+ let Some ( def ) = def else { return Substitution :: empty ( Interner ) } ;
816
+
817
+ // Order is
818
+ // - Optional Self parameter
819
+ // - Type or Const parameters
820
+ // - Lifetime parameters
821
+ // - Parent parameters
822
822
let def_generics = generics ( self . db . upcast ( ) , def) ;
823
823
let (
824
824
parent_params,
@@ -832,45 +832,46 @@ impl<'a> TyLoweringContext<'a> {
832
832
self_param as usize + type_params + const_params + impl_trait_params + lifetime_params;
833
833
let total_len = parent_params + item_len;
834
834
835
- let ty_error = TyKind :: Error . intern ( Interner ) . cast ( Interner ) ;
835
+ let mut substs = Vec :: new ( ) ;
836
836
837
- let mut def_generic_iter = def_generics. iter_id ( ) ;
837
+ // we need to iterate the lifetime and type/const params separately as our order of them
838
+ // differs from the supplied syntax
838
839
839
- let fill_self_params = || {
840
+ let ty_error = || TyKind :: Error . intern ( Interner ) . cast ( Interner ) ;
841
+ let mut def_toc_iter = def_generics. iter_self_type_or_consts_id ( ) ;
842
+ let mut def_lt_iter = def_generics. iter_self_lt_id ( ) ;
843
+ let fill_self_param = || {
840
844
if self_param {
841
- let self_ty =
842
- explicit_self_ty. map ( |x| x. cast ( Interner ) ) . unwrap_or_else ( || ty_error. clone ( ) ) ;
845
+ let self_ty = explicit_self_ty. map ( |x| x. cast ( Interner ) ) . unwrap_or_else ( ty_error) ;
843
846
844
- if let Some ( id) = def_generic_iter. next ( ) {
845
- assert ! ( matches!(
846
- id,
847
- GenericParamId :: TypeParamId ( _) | GenericParamId :: LifetimeParamId ( _)
848
- ) ) ;
847
+ if let Some ( id) = def_toc_iter. next ( ) {
848
+ assert ! ( matches!( id, GenericParamId :: TypeParamId ( _) ) ) ;
849
849
substs. push ( self_ty) ;
850
850
}
851
851
}
852
852
} ;
853
853
let mut had_explicit_args = false ;
854
854
855
- if let Some ( generic_args) = & args_and_bindings {
856
- if !generic_args. has_self_type {
857
- fill_self_params ( ) ;
855
+ let mut lifetimes = SmallVec :: < [ _ ; 1 ] > :: new ( ) ;
856
+ if let Some ( & GenericArgs { ref args, has_self_type, .. } ) = args_and_bindings {
857
+ if !has_self_type {
858
+ fill_self_param ( ) ;
858
859
}
859
- let expected_num = if generic_args . has_self_type {
860
+ let expected_num = if has_self_type {
860
861
self_param as usize + type_params + const_params
861
862
} else {
862
863
type_params + const_params
863
864
} ;
864
- let skip = if generic_args. has_self_type && !self_param { 1 } else { 0 } ;
865
- // if args are provided, it should be all of them, but we can't rely on that
866
- for arg in generic_args
867
- . args
865
+ let skip = if has_self_type && !self_param { 1 } else { 0 } ;
866
+ // if non-lifetime args are provided, it should be all of them, but we can't rely on that
867
+ for arg in args
868
868
. iter ( )
869
869
. filter ( |arg| !matches ! ( arg, GenericArg :: Lifetime ( _) ) )
870
870
. skip ( skip)
871
871
. take ( expected_num)
872
872
{
873
- if let Some ( id) = def_generic_iter. next ( ) {
873
+ if let Some ( id) = def_toc_iter. next ( ) {
874
+ had_explicit_args = true ;
874
875
let arg = generic_arg_to_chalk (
875
876
self . db ,
876
877
id,
@@ -880,20 +881,16 @@ impl<'a> TyLoweringContext<'a> {
880
881
|_, const_ref, ty| self . lower_const ( const_ref, ty) ,
881
882
|_, lifetime_ref| self . lower_lifetime ( lifetime_ref) ,
882
883
) ;
883
- had_explicit_args = true ;
884
884
substs. push ( arg) ;
885
885
}
886
886
}
887
887
888
- for arg in generic_args
889
- . args
888
+ for arg in args
890
889
. iter ( )
891
890
. filter ( |arg| matches ! ( arg, GenericArg :: Lifetime ( _) ) )
892
891
. take ( lifetime_params)
893
892
{
894
- // Taking into the fact that def_generic_iter will always have lifetimes at the end
895
- // Should have some test cases tho to test this behaviour more properly
896
- if let Some ( id) = def_generic_iter. next ( ) {
893
+ if let Some ( id) = def_lt_iter. next ( ) {
897
894
let arg = generic_arg_to_chalk (
898
895
self . db ,
899
896
id,
@@ -903,59 +900,61 @@ impl<'a> TyLoweringContext<'a> {
903
900
|_, const_ref, ty| self . lower_const ( const_ref, ty) ,
904
901
|_, lifetime_ref| self . lower_lifetime ( lifetime_ref) ,
905
902
) ;
906
- had_explicit_args = true ;
907
- substs. push ( arg) ;
903
+ lifetimes. push ( arg) ;
908
904
}
909
905
}
910
906
} else {
911
- fill_self_params ( ) ;
907
+ fill_self_param ( ) ;
912
908
}
913
909
914
- // These params include those of parent.
915
- let remaining_params: SmallVec < [ _ ; 2 ] > = def_generic_iter
916
- . map ( |id| match id {
917
- GenericParamId :: ConstParamId ( x) => {
918
- unknown_const_as_generic ( self . db . const_param_ty ( x) )
919
- }
920
- GenericParamId :: TypeParamId ( _) => ty_error. clone ( ) ,
921
- GenericParamId :: LifetimeParamId ( _) => error_lifetime ( ) . cast ( Interner ) ,
922
- } )
923
- . collect ( ) ;
924
- assert_eq ! ( remaining_params. len( ) + substs. len( ) , total_len) ;
925
-
910
+ let param_to_err = |id| match id {
911
+ GenericParamId :: ConstParamId ( x) => unknown_const_as_generic ( self . db . const_param_ty ( x) ) ,
912
+ GenericParamId :: TypeParamId ( _) => ty_error ( ) ,
913
+ GenericParamId :: LifetimeParamId ( _) => error_lifetime ( ) . cast ( Interner ) ,
914
+ } ;
926
915
// handle defaults. In expression or pattern path segments without
927
916
// explicitly specified type arguments, missing type arguments are inferred
928
917
// (i.e. defaults aren't used).
929
918
// Generic parameters for associated types are not supposed to have defaults, so we just
930
919
// ignore them.
931
- let is_assoc_ty = if let GenericDefId :: TypeAliasId ( id ) = def {
932
- let container = id . lookup ( self . db . upcast ( ) ) . container ;
933
- matches ! ( container, ItemContainerId :: TraitId ( _) )
934
- } else {
935
- false
920
+ let is_assoc_ty = || match def {
921
+ GenericDefId :: TypeAliasId ( id ) => {
922
+ matches ! ( id . lookup ( self . db . upcast ( ) ) . container, ItemContainerId :: TraitId ( _) )
923
+ }
924
+ _ => false ,
936
925
} ;
937
- if !is_assoc_ty && ( !infer_args || had_explicit_args) {
938
- let defaults = self . db . generic_defaults ( def) ;
939
- assert_eq ! ( total_len, defaults. len( ) ) ;
926
+ if ( !infer_args || had_explicit_args) && !is_assoc_ty ( ) {
927
+ let defaults = & * self . db . generic_defaults ( def) ;
928
+ let ( item, _parent) = defaults. split_at ( item_len) ;
929
+ let ( toc, lt) = item. split_at ( item_len - lifetime_params) ;
940
930
let parent_from = item_len - substs. len ( ) ;
941
931
942
- for ( idx, default_ty) in defaults[ substs. len ( ) ..item_len] . iter ( ) . enumerate ( ) {
932
+ let mut rem =
933
+ def_generics. iter_id ( ) . skip ( substs. len ( ) ) . map ( param_to_err) . collect :: < Vec < _ > > ( ) ;
934
+ // Fill in defaults for type/const params
935
+ for ( idx, default_ty) in toc[ substs. len ( ) ..] . iter ( ) . enumerate ( ) {
943
936
// each default can depend on the previous parameters
944
937
let substs_so_far = Substitution :: from_iter (
945
938
Interner ,
946
- substs. iter ( ) . cloned ( ) . chain ( remaining_params [ idx..] . iter ( ) . cloned ( ) ) ,
939
+ substs. iter ( ) . cloned ( ) . chain ( rem [ idx..] . iter ( ) . cloned ( ) ) ,
947
940
) ;
948
941
substs. push ( default_ty. clone ( ) . substitute ( Interner , & substs_so_far) ) ;
949
942
}
950
-
951
- // Keep parent's params as unknown.
952
- let mut remaining_params = remaining_params;
953
- substs. extend ( remaining_params. drain ( parent_from..) ) ;
943
+ let n_lifetimes = lifetimes. len ( ) ;
944
+ substs. extend ( lifetimes) ;
945
+ // Fill in defaults for lifetime params
946
+ for default_ty in & lt[ n_lifetimes..] {
947
+ // these are always errors so skipping is fine
948
+ substs. push ( default_ty. skip_binders ( ) . clone ( ) ) ;
949
+ }
950
+ // Fill in remaining def params and parent params
951
+ substs. extend ( rem. drain ( parent_from..) ) ;
954
952
} else {
955
- substs. extend ( remaining_params) ;
953
+ // Fill in remaining def params and parent params
954
+ substs. extend ( def_generics. iter_id ( ) . skip ( substs. len ( ) ) . map ( param_to_err) ) ;
956
955
}
957
956
958
- assert_eq ! ( substs. len( ) , total_len) ;
957
+ assert_eq ! ( substs. len( ) , total_len, "expected {} substs, got {}" , total_len , substs . len ( ) ) ;
959
958
Substitution :: from_iter ( Interner , substs)
960
959
}
961
960
0 commit comments