2
2
//!
3
3
//! The layout for generics as expected by chalk are as follows:
4
4
//! - Optional Self parameter
5
- //! - Type or Const parameters
6
5
//! - Lifetime parameters
6
+ //! - Type or Const parameters
7
7
//! - Parent parameters
8
8
//!
9
9
//! where parent follows the same scheme.
@@ -20,19 +20,23 @@ use hir_def::{
20
20
LocalLifetimeParamId , LocalTypeOrConstParamId , Lookup , TypeOrConstParamId , TypeParamId ,
21
21
} ;
22
22
use intern:: Interned ;
23
+ use itertools:: chain;
23
24
use stdx:: TupleExt ;
24
25
25
26
use crate :: { db:: HirDatabase , lt_to_placeholder_idx, to_placeholder_idx, Interner , Substitution } ;
26
27
27
28
pub ( crate ) fn generics ( db : & dyn DefDatabase , def : GenericDefId ) -> Generics {
28
29
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 }
30
33
}
31
34
#[ derive( Clone , Debug ) ]
32
35
pub ( crate ) struct Generics {
33
36
def : GenericDefId ,
34
37
params : Interned < GenericParams > ,
35
38
parent_generics : Option < Box < Generics > > ,
39
+ has_trait_self_param : bool ,
36
40
}
37
41
38
42
impl < T > ops:: Index < T > for Generics
@@ -74,10 +78,6 @@ impl Generics {
74
78
self . params . iter_type_or_consts ( ) . map ( from_toc_id ( self ) ) . map ( TupleExt :: head)
75
79
}
76
80
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
-
81
81
/// Iterate over the params followed by the parent params.
82
82
pub ( crate ) fn iter (
83
83
& self ,
@@ -89,19 +89,19 @@ impl Generics {
89
89
pub ( crate ) fn iter_self (
90
90
& self ,
91
91
) -> 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)
96
95
}
97
96
98
97
/// Iterator over types and const params of parent.
99
98
fn iter_parent (
100
99
& self ,
101
100
) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' _ > ) > + ' _ {
102
101
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)
105
105
} )
106
106
}
107
107
@@ -146,7 +146,10 @@ impl Generics {
146
146
if param. parent == self . def {
147
147
let idx = param. local_id . into_raw ( ) . into_u32 ( ) as usize ;
148
148
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)
150
153
} else {
151
154
debug_assert_eq ! ( self . parent_generics( ) . map( |it| it. def) , Some ( param. parent) ) ;
152
155
self . parent_generics ( )
@@ -164,7 +167,7 @@ impl Generics {
164
167
if lifetime. parent == self . def {
165
168
let idx = lifetime. local_id . into_raw ( ) . into_u32 ( ) as usize ;
166
169
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)
168
171
} else {
169
172
debug_assert_eq ! ( self . parent_generics( ) . map( |it| it. def) , Some ( lifetime. parent) ) ;
170
173
self . parent_generics ( )
0 commit comments