@@ -27,23 +27,84 @@ use crate::{
27
27
db:: HirDatabase , ChalkTraitId , Interner , Substitution , TraitRef , TraitRefExt , WhereClause ,
28
28
} ;
29
29
30
- pub ( crate ) fn fn_traits ( db : & dyn DefDatabase , krate : CrateId ) -> impl Iterator < Item = TraitId > {
31
- [
32
- db. lang_item ( krate, LangItem :: Fn ) ,
33
- db. lang_item ( krate, LangItem :: FnMut ) ,
34
- db. lang_item ( krate, LangItem :: FnOnce ) ,
35
- ]
36
- . into_iter ( )
37
- . flatten ( )
38
- . flat_map ( |it| it. as_trait ( ) )
30
+ pub ( crate ) fn fn_traits (
31
+ db : & dyn DefDatabase ,
32
+ krate : CrateId ,
33
+ ) -> impl Iterator < Item = TraitId > + ' _ {
34
+ [ LangItem :: Fn , LangItem :: FnMut , LangItem :: FnOnce ]
35
+ . into_iter ( )
36
+ . filter_map ( move |lang| db. lang_item ( krate, lang) )
37
+ . flat_map ( |it| it. as_trait ( ) )
39
38
}
40
39
41
- fn direct_super_traits ( db : & dyn DefDatabase , trait_ : TraitId ) -> SmallVec < [ TraitId ; 4 ] > {
40
+ /// Returns an iterator over the whole super trait hierarchy (including the
41
+ /// trait itself).
42
+ pub fn all_super_traits ( db : & dyn DefDatabase , trait_ : TraitId ) -> SmallVec < [ TraitId ; 4 ] > {
43
+ // we need to take care a bit here to avoid infinite loops in case of cycles
44
+ // (i.e. if we have `trait A: B; trait B: A;`)
45
+
46
+ let mut result = smallvec ! [ trait_] ;
47
+ let mut i = 0 ;
48
+ while let Some ( & t) = result. get ( i) {
49
+ // yeah this is quadratic, but trait hierarchies should be flat
50
+ // enough that this doesn't matter
51
+ direct_super_traits ( db, t, |tt| {
52
+ if !result. contains ( & tt) {
53
+ result. push ( tt) ;
54
+ }
55
+ } ) ;
56
+ i += 1 ;
57
+ }
58
+ result
59
+ }
60
+
61
+ /// Given a trait ref (`Self: Trait`), builds all the implied trait refs for
62
+ /// super traits. The original trait ref will be included. So the difference to
63
+ /// `all_super_traits` is that we keep track of type parameters; for example if
64
+ /// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
65
+ /// `Self: OtherTrait<i32>`.
66
+ pub ( super ) fn all_super_trait_refs < T > (
67
+ db : & dyn HirDatabase ,
68
+ trait_ref : TraitRef ,
69
+ cb : impl FnMut ( TraitRef ) -> Option < T > ,
70
+ ) -> Option < T > {
71
+ let seen = iter:: once ( trait_ref. trait_id ) . collect ( ) ;
72
+ let mut stack = Vec :: new ( ) ;
73
+ stack. push ( trait_ref) ;
74
+ SuperTraits { db, seen, stack } . find_map ( cb)
75
+ }
76
+
77
+ struct SuperTraits < ' a > {
78
+ db : & ' a dyn HirDatabase ,
79
+ stack : Vec < TraitRef > ,
80
+ seen : FxHashSet < ChalkTraitId > ,
81
+ }
82
+
83
+ impl < ' a > SuperTraits < ' a > {
84
+ fn elaborate ( & mut self , trait_ref : & TraitRef ) {
85
+ direct_super_trait_refs ( self . db , trait_ref, |trait_ref| {
86
+ if !self . seen . contains ( & trait_ref. trait_id ) {
87
+ self . stack . push ( trait_ref) ;
88
+ }
89
+ } ) ;
90
+ }
91
+ }
92
+
93
+ impl < ' a > Iterator for SuperTraits < ' a > {
94
+ type Item = TraitRef ;
95
+
96
+ fn next ( & mut self ) -> Option < Self :: Item > {
97
+ if let Some ( next) = self . stack . pop ( ) {
98
+ self . elaborate ( & next) ;
99
+ Some ( next)
100
+ } else {
101
+ None
102
+ }
103
+ }
104
+ }
105
+
106
+ fn direct_super_traits ( db : & dyn DefDatabase , trait_ : TraitId , cb : impl FnMut ( TraitId ) ) {
42
107
let resolver = trait_. resolver ( db) ;
43
- // returning the iterator directly doesn't easily work because of
44
- // lifetime problems, but since there usually shouldn't be more than a
45
- // few direct traits this should be fine (we could even use some kind of
46
- // SmallVec if performance is a concern)
47
108
let generic_params = db. generic_params ( trait_. into ( ) ) ;
48
109
let trait_self = generic_params. find_trait_self_param ( ) ;
49
110
generic_params
@@ -73,18 +134,14 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[Trait
73
134
Some ( TypeNs :: TraitId ( t) ) => Some ( t) ,
74
135
_ => None ,
75
136
} )
76
- . collect ( )
137
+ . for_each ( cb ) ;
77
138
}
78
139
79
- fn direct_super_trait_refs ( db : & dyn HirDatabase , trait_ref : & TraitRef ) -> Vec < TraitRef > {
80
- // returning the iterator directly doesn't easily work because of
81
- // lifetime problems, but since there usually shouldn't be more than a
82
- // few direct traits this should be fine (we could even use some kind of
83
- // SmallVec if performance is a concern)
140
+ fn direct_super_trait_refs ( db : & dyn HirDatabase , trait_ref : & TraitRef , cb : impl FnMut ( TraitRef ) ) {
84
141
let generic_params = db. generic_params ( trait_ref. hir_trait_id ( ) . into ( ) ) ;
85
142
let trait_self = match generic_params. find_trait_self_param ( ) {
86
143
Some ( p) => TypeOrConstParamId { parent : trait_ref. hir_trait_id ( ) . into ( ) , local_id : p } ,
87
- None => return Vec :: new ( ) ,
144
+ None => return ,
88
145
} ;
89
146
db. generic_predicates_for_param ( trait_self. parent , trait_self, None )
90
147
. iter ( )
@@ -100,72 +157,15 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
100
157
} )
101
158
} )
102
159
. map ( |pred| pred. substitute ( Interner , & trait_ref. substitution ) )
103
- . collect ( )
104
- }
105
-
106
- /// Returns an iterator over the whole super trait hierarchy (including the
107
- /// trait itself).
108
- pub fn all_super_traits ( db : & dyn DefDatabase , trait_ : TraitId ) -> SmallVec < [ TraitId ; 4 ] > {
109
- // we need to take care a bit here to avoid infinite loops in case of cycles
110
- // (i.e. if we have `trait A: B; trait B: A;`)
111
-
112
- let mut result = smallvec ! [ trait_] ;
113
- let mut i = 0 ;
114
- while let Some ( & t) = result. get ( i) {
115
- // yeah this is quadratic, but trait hierarchies should be flat
116
- // enough that this doesn't matter
117
- for tt in direct_super_traits ( db, t) {
118
- if !result. contains ( & tt) {
119
- result. push ( tt) ;
120
- }
121
- }
122
- i += 1 ;
123
- }
124
- result
125
- }
126
-
127
- /// Given a trait ref (`Self: Trait`), builds all the implied trait refs for
128
- /// super traits. The original trait ref will be included. So the difference to
129
- /// `all_super_traits` is that we keep track of type parameters; for example if
130
- /// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
131
- /// `Self: OtherTrait<i32>`.
132
- pub ( super ) fn all_super_trait_refs ( db : & dyn HirDatabase , trait_ref : TraitRef ) -> SuperTraits < ' _ > {
133
- SuperTraits { db, seen : iter:: once ( trait_ref. trait_id ) . collect ( ) , stack : vec ! [ trait_ref] }
134
- }
135
-
136
- pub ( super ) struct SuperTraits < ' a > {
137
- db : & ' a dyn HirDatabase ,
138
- stack : Vec < TraitRef > ,
139
- seen : FxHashSet < ChalkTraitId > ,
140
- }
141
-
142
- impl < ' a > SuperTraits < ' a > {
143
- fn elaborate ( & mut self , trait_ref : & TraitRef ) {
144
- let mut trait_refs = direct_super_trait_refs ( self . db , trait_ref) ;
145
- trait_refs. retain ( |tr| !self . seen . contains ( & tr. trait_id ) ) ;
146
- self . stack . extend ( trait_refs) ;
147
- }
148
- }
149
-
150
- impl < ' a > Iterator for SuperTraits < ' a > {
151
- type Item = TraitRef ;
152
-
153
- fn next ( & mut self ) -> Option < Self :: Item > {
154
- if let Some ( next) = self . stack . pop ( ) {
155
- self . elaborate ( & next) ;
156
- Some ( next)
157
- } else {
158
- None
159
- }
160
- }
160
+ . for_each ( cb) ;
161
161
}
162
162
163
163
pub ( super ) fn associated_type_by_name_including_super_traits (
164
164
db : & dyn HirDatabase ,
165
165
trait_ref : TraitRef ,
166
166
name : & Name ,
167
167
) -> Option < ( TraitRef , TypeAliasId ) > {
168
- all_super_trait_refs ( db, trait_ref) . find_map ( |t| {
168
+ all_super_trait_refs ( db, trait_ref, |t| {
169
169
let assoc_type = db. trait_data ( t. hir_trait_id ( ) ) . associated_type_by_name ( name) ?;
170
170
Some ( ( t, assoc_type) )
171
171
} )
@@ -238,15 +238,18 @@ impl Generics {
238
238
239
239
/// (parent total, self param, type param list, const param list, impl trait)
240
240
pub ( crate ) fn provenance_split ( & self ) -> ( usize , usize , usize , usize , usize ) {
241
- let ty_iter = || self . params . iter ( ) . filter_map ( |x| x. 1 . type_param ( ) ) ;
242
-
243
- let self_params =
244
- ty_iter ( ) . filter ( |p| p. provenance == TypeParamProvenance :: TraitSelf ) . count ( ) ;
245
- let type_params =
246
- ty_iter ( ) . filter ( |p| p. provenance == TypeParamProvenance :: TypeParamList ) . count ( ) ;
247
- let impl_trait_params =
248
- ty_iter ( ) . filter ( |p| p. provenance == TypeParamProvenance :: ArgumentImplTrait ) . count ( ) ;
249
- let const_params = self . params . iter ( ) . filter_map ( |x| x. 1 . const_param ( ) ) . count ( ) ;
241
+ let mut self_params = 0 ;
242
+ let mut type_params = 0 ;
243
+ let mut impl_trait_params = 0 ;
244
+ let mut const_params = 0 ;
245
+ self . params . iter ( ) . for_each ( |( _, data) | match data {
246
+ TypeOrConstParamData :: TypeParamData ( p) => match p. provenance {
247
+ TypeParamProvenance :: TypeParamList => type_params += 1 ,
248
+ TypeParamProvenance :: TraitSelf => self_params += 1 ,
249
+ TypeParamProvenance :: ArgumentImplTrait => impl_trait_params += 1 ,
250
+ } ,
251
+ TypeOrConstParamData :: ConstParamData ( _) => const_params += 1 ,
252
+ } ) ;
250
253
251
254
let parent_len = self . parent_generics ( ) . map_or ( 0 , Generics :: len) ;
252
255
( parent_len, self_params, type_params, const_params, impl_trait_params)
0 commit comments