@@ -812,13 +812,13 @@ impl<'a> TyLoweringContext<'a> {
812812 infer_args : bool ,
813813 explicit_self_ty : Option < Ty > ,
814814 ) -> 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
822822 let def_generics = generics ( self . db . upcast ( ) , def) ;
823823 let (
824824 parent_params,
@@ -832,45 +832,46 @@ impl<'a> TyLoweringContext<'a> {
832832 self_param as usize + type_params + const_params + impl_trait_params + lifetime_params;
833833 let total_len = parent_params + item_len;
834834
835- let ty_error = TyKind :: Error . intern ( Interner ) . cast ( Interner ) ;
835+ let mut substs = Vec :: new ( ) ;
836836
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
838839
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 = || {
840844 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) ;
843846
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 ( _) ) ) ;
849849 substs. push ( self_ty) ;
850850 }
851851 }
852852 } ;
853853 let mut had_explicit_args = false ;
854854
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 ( ) ;
858859 }
859- let expected_num = if generic_args . has_self_type {
860+ let expected_num = if has_self_type {
860861 self_param as usize + type_params + const_params
861862 } else {
862863 type_params + const_params
863864 } ;
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
868868 . iter ( )
869869 . filter ( |arg| !matches ! ( arg, GenericArg :: Lifetime ( _) ) )
870870 . skip ( skip)
871871 . take ( expected_num)
872872 {
873- if let Some ( id) = def_generic_iter. next ( ) {
873+ if let Some ( id) = def_toc_iter. next ( ) {
874+ had_explicit_args = true ;
874875 let arg = generic_arg_to_chalk (
875876 self . db ,
876877 id,
@@ -880,20 +881,16 @@ impl<'a> TyLoweringContext<'a> {
880881 |_, const_ref, ty| self . lower_const ( const_ref, ty) ,
881882 |_, lifetime_ref| self . lower_lifetime ( lifetime_ref) ,
882883 ) ;
883- had_explicit_args = true ;
884884 substs. push ( arg) ;
885885 }
886886 }
887887
888- for arg in generic_args
889- . args
888+ for arg in args
890889 . iter ( )
891890 . filter ( |arg| matches ! ( arg, GenericArg :: Lifetime ( _) ) )
892891 . take ( lifetime_params)
893892 {
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 ( ) {
897894 let arg = generic_arg_to_chalk (
898895 self . db ,
899896 id,
@@ -903,59 +900,64 @@ impl<'a> TyLoweringContext<'a> {
903900 |_, const_ref, ty| self . lower_const ( const_ref, ty) ,
904901 |_, lifetime_ref| self . lower_lifetime ( lifetime_ref) ,
905902 ) ;
906- had_explicit_args = true ;
907- substs. push ( arg) ;
903+ lifetimes. push ( arg) ;
908904 }
909905 }
910906 } else {
911- fill_self_params ( ) ;
907+ fill_self_param ( ) ;
912908 }
913909
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+ } ;
926915 // handle defaults. In expression or pattern path segments without
927916 // explicitly specified type arguments, missing type arguments are inferred
928917 // (i.e. defaults aren't used).
929918 // Generic parameters for associated types are not supposed to have defaults, so we just
930919 // 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 ,
936925 } ;
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) ;
940930 let parent_from = item_len - substs. len ( ) ;
941931
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 ( ) {
943936 // each default can depend on the previous parameters
944937 let substs_so_far = Substitution :: from_iter (
945938 Interner ,
946- substs. iter ( ) . cloned ( ) . chain ( remaining_params [ idx..] . iter ( ) . cloned ( ) ) ,
939+ substs. iter ( ) . cloned ( ) . chain ( rem [ idx..] . iter ( ) . cloned ( ) ) ,
947940 ) ;
948941 substs. push ( default_ty. clone ( ) . substitute ( Interner , & substs_so_far) ) ;
949942 }
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+ // Fill in deferred lifetimes
945+ substs. extend ( lifetimes) ;
946+ // Fill in defaults for lifetime params
947+ for default_ty in & lt[ n_lifetimes..] {
948+ // these are always errors so skipping is fine
949+ substs. push ( default_ty. skip_binders ( ) . clone ( ) ) ;
950+ }
951+ // Fill in remaining def params and parent params
952+ substs. extend ( rem. drain ( parent_from..) ) ;
954953 } else {
955- substs. extend ( remaining_params) ;
954+ // Fill in deferred lifetimes
955+ substs. extend ( lifetimes) ;
956+ // Fill in remaining def params and parent params
957+ substs. extend ( def_generics. iter_id ( ) . skip ( substs. len ( ) ) . map ( param_to_err) ) ;
956958 }
957959
958- assert_eq ! ( substs. len( ) , total_len) ;
960+ assert_eq ! ( substs. len( ) , total_len, "expected {} substs, got {}" , total_len , substs . len ( ) ) ;
959961 Substitution :: from_iter ( Interner , substs)
960962 }
961963
0 commit comments