1+ //! Utilities for working with generics.
2+ //!
3+ //! The layout for generics as expected by chalk are as follows:
4+ //! - Optional Self parameter
5+ //! - Type or Const parameters
6+ //! - Lifetime parameters
7+ //! - Parent parameters
8+ //!
9+ //! where parent follows the same scheme.
10+ use std:: ops;
11+
112use chalk_ir:: { cast:: Cast as _, BoundVar , DebruijnIndex } ;
213use hir_def:: {
314 db:: DefDatabase ,
415 generics:: {
516 GenericParamDataRef , GenericParams , LifetimeParamData , TypeOrConstParamData ,
617 TypeParamProvenance ,
718 } ,
8- ConstParamId , GenericDefId , GenericParamId , ItemContainerId , LifetimeParamId , Lookup ,
9- TypeOrConstParamId , TypeParamId ,
19+ ConstParamId , GenericDefId , GenericParamId , ItemContainerId , LifetimeParamId ,
20+ LocalLifetimeParamId , LocalTypeOrConstParamId , Lookup , TypeOrConstParamId , TypeParamId ,
1021} ;
1122use intern:: Interned ;
1223
13- use crate :: { db:: HirDatabase , Interner , Substitution } ;
24+ use crate :: { db:: HirDatabase , lt_to_placeholder_idx , to_placeholder_idx , Interner , Substitution } ;
1425
1526pub ( crate ) fn generics ( db : & dyn DefDatabase , def : GenericDefId ) -> Generics {
1627 let parent_generics = parent_generic_def ( db, def) . map ( |def| Box :: new ( generics ( db, def) ) ) ;
@@ -19,85 +30,46 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
1930#[ derive( Clone , Debug ) ]
2031pub ( crate ) struct Generics {
2132 def : GenericDefId ,
22- pub ( crate ) params : Interned < GenericParams > ,
33+ params : Interned < GenericParams > ,
2334 parent_generics : Option < Box < Generics > > ,
2435}
2536
26- impl Generics {
27- pub ( crate ) fn iter_id ( & self ) -> impl Iterator < Item = GenericParamId > + ' _ {
28- self . iter ( ) . map ( |( id, _) | id)
37+ impl < T > ops:: Index < T > for Generics
38+ where
39+ GenericParams : ops:: Index < T > ,
40+ {
41+ type Output = <GenericParams as ops:: Index < T > >:: Output ;
42+ fn index ( & self , index : T ) -> & Self :: Output {
43+ & self . params [ index]
2944 }
45+ }
3046
47+ impl Generics {
3148 pub ( crate ) fn def ( & self ) -> GenericDefId {
3249 self . def
3350 }
3451
35- /// Iterator over types and const params of self, then parent.
36- pub ( crate ) fn iter < ' a > (
37- & ' a self ,
38- ) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' a > ) > + ' a {
39- let from_toc_id = |it : & ' a Generics | {
40- move |( local_id, p) : ( _ , & ' a TypeOrConstParamData ) | {
41- let id = TypeOrConstParamId { parent : it. def , local_id } ;
42- match p {
43- TypeOrConstParamData :: TypeParamData ( p) => (
44- GenericParamId :: TypeParamId ( TypeParamId :: from_unchecked ( id) ) ,
45- GenericParamDataRef :: TypeParamData ( p) ,
46- ) ,
47- TypeOrConstParamData :: ConstParamData ( p) => (
48- GenericParamId :: ConstParamId ( ConstParamId :: from_unchecked ( id) ) ,
49- GenericParamDataRef :: ConstParamData ( p) ,
50- ) ,
51- }
52- }
53- } ;
54-
55- let from_lt_id = |it : & ' a Generics | {
56- move |( local_id, p) : ( _ , & ' a LifetimeParamData ) | {
57- (
58- GenericParamId :: LifetimeParamId ( LifetimeParamId { parent : it. def , local_id } ) ,
59- GenericParamDataRef :: LifetimeParamData ( p) ,
60- )
61- }
62- } ;
63-
64- let lt_iter = self . params . iter_lt ( ) . map ( from_lt_id ( self ) ) ;
65- self . params
66- . iter_type_or_consts ( )
67- . map ( from_toc_id ( self ) )
68- . chain ( lt_iter)
69- . chain ( self . iter_parent ( ) )
52+ pub ( crate ) fn iter_id ( & self ) -> impl Iterator < Item = GenericParamId > + ' _ {
53+ self . iter ( ) . map ( |( id, _) | id)
7054 }
7155
72- /// Iterate over types and const params without parent params.
73- pub ( crate ) fn iter_self < ' a > (
74- & ' a self ,
75- ) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' a > ) > + ' a {
76- let from_toc_id = |it : & ' a Generics | {
77- move |( local_id, p) : ( _ , & ' a TypeOrConstParamData ) | {
78- let id = TypeOrConstParamId { parent : it. def , local_id } ;
79- match p {
80- TypeOrConstParamData :: TypeParamData ( p) => (
81- GenericParamId :: TypeParamId ( TypeParamId :: from_unchecked ( id) ) ,
82- GenericParamDataRef :: TypeParamData ( p) ,
83- ) ,
84- TypeOrConstParamData :: ConstParamData ( p) => (
85- GenericParamId :: ConstParamId ( ConstParamId :: from_unchecked ( id) ) ,
86- GenericParamDataRef :: ConstParamData ( p) ,
87- ) ,
88- }
89- }
90- } ;
56+ pub ( crate ) fn iter_self_type_or_consts (
57+ & self ,
58+ ) -> impl DoubleEndedIterator < Item = ( LocalTypeOrConstParamId , & TypeOrConstParamData ) > {
59+ self . params . iter_type_or_consts ( )
60+ }
9161
92- let from_lt_id = |it : & ' a Generics | {
93- move |( local_id, p) : ( _ , & ' a LifetimeParamData ) | {
94- (
95- GenericParamId :: LifetimeParamId ( LifetimeParamId { parent : it. def , local_id } ) ,
96- GenericParamDataRef :: LifetimeParamData ( p) ,
97- )
98- }
99- } ;
62+ /// Iterate over the params followed by the parent params.
63+ pub ( crate ) fn iter (
64+ & self ,
65+ ) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' _ > ) > + ' _ {
66+ self . iter_self ( ) . chain ( self . iter_parent ( ) )
67+ }
10068
69+ /// Iterate over the params without parent params.
70+ pub ( crate ) fn iter_self (
71+ & self ,
72+ ) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' _ > ) > + ' _ {
10173 self . params
10274 . iter_type_or_consts ( )
10375 . map ( from_toc_id ( self ) )
@@ -109,29 +81,8 @@ impl Generics {
10981 & self ,
11082 ) -> impl DoubleEndedIterator < Item = ( GenericParamId , GenericParamDataRef < ' _ > ) > + ' _ {
11183 self . parent_generics ( ) . into_iter ( ) . flat_map ( |it| {
112- let from_toc_id = move |( local_id, p) | {
113- let p: & _ = p;
114- let id = TypeOrConstParamId { parent : it. def , local_id } ;
115- match p {
116- TypeOrConstParamData :: TypeParamData ( p) => (
117- GenericParamId :: TypeParamId ( TypeParamId :: from_unchecked ( id) ) ,
118- GenericParamDataRef :: TypeParamData ( p) ,
119- ) ,
120- TypeOrConstParamData :: ConstParamData ( p) => (
121- GenericParamId :: ConstParamId ( ConstParamId :: from_unchecked ( id) ) ,
122- GenericParamDataRef :: ConstParamData ( p) ,
123- ) ,
124- }
125- } ;
126-
127- let from_lt_id = move |( local_id, p) : ( _ , _ ) | {
128- (
129- GenericParamId :: LifetimeParamId ( LifetimeParamId { parent : it. def , local_id } ) ,
130- GenericParamDataRef :: LifetimeParamData ( p) ,
131- )
132- } ;
133- let lt_iter = it. params . iter_lt ( ) . map ( from_lt_id) ;
134- it. params . iter_type_or_consts ( ) . map ( from_toc_id) . chain ( lt_iter)
84+ let lt_iter = it. params . iter_lt ( ) . map ( from_lt_id ( it) ) ;
85+ it. params . iter_type_or_consts ( ) . map ( from_toc_id ( it) ) . chain ( lt_iter)
13586 } )
13687 }
13788
@@ -147,11 +98,6 @@ impl Generics {
14798 self . params . len ( )
14899 }
149100
150- /// Returns number of generic parameter excluding those from parent
151- fn len_type_and_const_params ( & self ) -> usize {
152- self . params . type_or_consts . len ( )
153- }
154-
155101 /// (parent total, self param, type params, const params, impl trait list, lifetimes)
156102 pub ( crate ) fn provenance_split ( & self ) -> ( usize , usize , usize , usize , usize , usize ) {
157103 let mut self_params = 0 ;
@@ -207,7 +153,7 @@ impl Generics {
207153 return None ;
208154 }
209155 Some ( (
210- self . len_type_and_const_params ( ) + idx,
156+ self . params . type_or_consts . len ( ) + idx,
211157 & self . params . lifetimes [ lifetime. local_id ] ,
212158 ) )
213159 } else {
@@ -253,13 +199,13 @@ impl Generics {
253199 Interner ,
254200 self . iter_id ( ) . map ( |id| match id {
255201 GenericParamId :: TypeParamId ( id) => {
256- crate :: to_placeholder_idx ( db, id. into ( ) ) . to_ty ( Interner ) . cast ( Interner )
202+ to_placeholder_idx ( db, id. into ( ) ) . to_ty ( Interner ) . cast ( Interner )
257203 }
258- GenericParamId :: ConstParamId ( id) => crate :: to_placeholder_idx ( db, id. into ( ) )
204+ GenericParamId :: ConstParamId ( id) => to_placeholder_idx ( db, id. into ( ) )
259205 . to_const ( Interner , db. const_param_ty ( id) )
260206 . cast ( Interner ) ,
261207 GenericParamId :: LifetimeParamId ( id) => {
262- crate :: lt_to_placeholder_idx ( db, id) . to_lifetime ( Interner ) . cast ( Interner )
208+ lt_to_placeholder_idx ( db, id) . to_lifetime ( Interner ) . cast ( Interner )
263209 }
264210 } ) ,
265211 )
@@ -284,3 +230,35 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<Generic
284230 ItemContainerId :: ModuleId ( _) | ItemContainerId :: ExternBlockId ( _) => None ,
285231 }
286232}
233+
234+ fn from_toc_id < ' a > (
235+ it : & ' a Generics ,
236+ ) -> impl Fn (
237+ ( LocalTypeOrConstParamId , & ' a TypeOrConstParamData ) ,
238+ ) -> ( GenericParamId , GenericParamDataRef < ' a > ) {
239+ move |( local_id, p) : ( _ , _ ) | {
240+ let id = TypeOrConstParamId { parent : it. def , local_id } ;
241+ match p {
242+ TypeOrConstParamData :: TypeParamData ( p) => (
243+ GenericParamId :: TypeParamId ( TypeParamId :: from_unchecked ( id) ) ,
244+ GenericParamDataRef :: TypeParamData ( p) ,
245+ ) ,
246+ TypeOrConstParamData :: ConstParamData ( p) => (
247+ GenericParamId :: ConstParamId ( ConstParamId :: from_unchecked ( id) ) ,
248+ GenericParamDataRef :: ConstParamData ( p) ,
249+ ) ,
250+ }
251+ }
252+ }
253+
254+ fn from_lt_id < ' a > (
255+ it : & ' a Generics ,
256+ ) -> impl Fn ( ( LocalLifetimeParamId , & ' a LifetimeParamData ) ) -> ( GenericParamId , GenericParamDataRef < ' a > )
257+ {
258+ move |( local_id, p) : ( _ , _ ) | {
259+ (
260+ GenericParamId :: LifetimeParamId ( LifetimeParamId { parent : it. def , local_id } ) ,
261+ GenericParamDataRef :: LifetimeParamData ( p) ,
262+ )
263+ }
264+ }
0 commit comments