22//!
33//! The layout for generics as expected by chalk are as follows:
44//! - Optional Self parameter
5- //! - Type or Const parameters
65//! - Lifetime parameters
6+ //! - Type or Const parameters
77//! - Parent parameters
88//!
99//! where parent follows the same scheme.
@@ -20,19 +20,23 @@ use hir_def::{
2020 LocalLifetimeParamId , LocalTypeOrConstParamId , Lookup , TypeOrConstParamId , TypeParamId ,
2121} ;
2222use intern:: Interned ;
23+ use itertools:: chain;
2324use stdx:: TupleExt ;
2425
2526use crate :: { db:: HirDatabase , lt_to_placeholder_idx, to_placeholder_idx, Interner , Substitution } ;
2627
2728pub ( crate ) fn generics ( db : & dyn DefDatabase , def : GenericDefId ) -> Generics {
2829 let parent_generics = parent_generic_def ( db, def) . map ( |def| Box :: new ( generics ( db, def) ) ) ;
29- Generics { def, params : db. generic_params ( def) , parent_generics }
30+ let params = db. generic_params ( def) ;
31+ let has_trait_self_param = params. trait_self_param ( ) . is_some ( ) ;
32+ Generics { def, params, parent_generics, has_trait_self_param }
3033}
3134#[ derive( Clone , Debug ) ]
3235pub ( crate ) struct Generics {
3336 def : GenericDefId ,
3437 params : Interned < GenericParams > ,
3538 parent_generics : Option < Box < Generics > > ,
39+ has_trait_self_param : bool ,
3640}
3741
3842impl < T > ops:: Index < T > for Generics
@@ -74,10 +78,6 @@ impl Generics {
7478 self . params . iter_type_or_consts ( ) . map ( from_toc_id ( self ) ) . map ( TupleExt :: head)
7579 }
7680
77- pub ( crate ) fn iter_self_lt_id ( & self ) -> impl DoubleEndedIterator < Item = GenericParamId > + ' _ {
78- self . params . iter_lt ( ) . map ( from_lt_id ( self ) ) . map ( TupleExt :: head)
79- }
80-
8181 /// Iterate over the params followed by the parent params.
8282 pub ( crate ) fn iter (
8383 & self ,
@@ -89,19 +89,19 @@ impl Generics {
8989 pub ( crate ) fn iter_self (
9090 & self ,
9191 ) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' _ > ) > + ' _ {
92- self . params
93- . iter_type_or_consts ( )
94- . map ( from_toc_id ( self ) )
95- . chain ( self . params . iter_lt ( ) . map ( from_lt_id ( self ) ) )
92+ let mut toc = self . params . iter_type_or_consts ( ) . map ( from_toc_id ( self ) ) ;
93+ let trait_self_param = self . has_trait_self_param . then ( || toc. next ( ) ) . flatten ( ) ;
94+ chain ! ( trait_self_param, self . params. iter_lt( ) . map( from_lt_id( self ) ) , toc)
9695 }
9796
9897 /// Iterator over types and const params of parent.
9998 fn iter_parent (
10099 & self ,
101100 ) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' _ > ) > + ' _ {
102101 self . parent_generics ( ) . into_iter ( ) . flat_map ( |it| {
103- let lt_iter = it. params . iter_lt ( ) . map ( from_lt_id ( it) ) ;
104- it. params . iter_type_or_consts ( ) . map ( from_toc_id ( it) ) . chain ( lt_iter)
102+ let mut toc = it. params . iter_type_or_consts ( ) . map ( from_toc_id ( it) ) ;
103+ let trait_self_param = it. has_trait_self_param . then ( || toc. next ( ) ) . flatten ( ) ;
104+ chain ! ( trait_self_param, it. params. iter_lt( ) . map( from_lt_id( it) ) , toc)
105105 } )
106106 }
107107
@@ -146,7 +146,10 @@ impl Generics {
146146 if param. parent == self . def {
147147 let idx = param. local_id . into_raw ( ) . into_u32 ( ) as usize ;
148148 debug_assert ! ( idx <= self . params. len_type_or_consts( ) ) ;
149- Some ( idx)
149+ if self . params . trait_self_param ( ) == Some ( param. local_id ) {
150+ return Some ( idx) ;
151+ }
152+ Some ( self . params . len_lifetimes ( ) + idx)
150153 } else {
151154 debug_assert_eq ! ( self . parent_generics( ) . map( |it| it. def) , Some ( param. parent) ) ;
152155 self . parent_generics ( )
@@ -164,7 +167,7 @@ impl Generics {
164167 if lifetime. parent == self . def {
165168 let idx = lifetime. local_id . into_raw ( ) . into_u32 ( ) as usize ;
166169 debug_assert ! ( idx <= self . params. len_lifetimes( ) ) ;
167- Some ( self . params . len_type_or_consts ( ) + idx)
170+ Some ( self . params . trait_self_param ( ) . is_some ( ) as usize + idx)
168171 } else {
169172 debug_assert_eq ! ( self . parent_generics( ) . map( |it| it. def) , Some ( lifetime. parent) ) ;
170173 self . parent_generics ( )
0 commit comments