@@ -72,6 +72,10 @@ impl AlternativeExprs {
72
72
AlternativeExprs :: Many => ( ) ,
73
73
}
74
74
}
75
+
76
+ fn is_many ( & self ) -> bool {
77
+ matches ! ( self , AlternativeExprs :: Many )
78
+ }
75
79
}
76
80
77
81
/// # Lookup table for term search
@@ -103,27 +107,36 @@ struct LookupTable {
103
107
104
108
impl LookupTable {
105
109
/// Initialize lookup table
106
- fn new ( many_threshold : usize ) -> Self {
110
+ fn new ( many_threshold : usize , goal : Type ) -> Self {
107
111
let mut res = Self { many_threshold, ..Default :: default ( ) } ;
108
112
res. new_types . insert ( NewTypesKey :: ImplMethod , Vec :: new ( ) ) ;
109
113
res. new_types . insert ( NewTypesKey :: StructProjection , Vec :: new ( ) ) ;
114
+ res. types_wishlist . insert ( goal) ;
110
115
res
111
116
}
112
117
113
118
/// Find all `Expr`s that unify with the `ty`
114
- fn find ( & self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
115
- self . data
119
+ fn find ( & mut self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
120
+ let res = self
121
+ . data
116
122
. iter ( )
117
123
. find ( |( t, _) | t. could_unify_with_deeply ( db, ty) )
118
- . map ( |( t, tts) | tts. exprs ( t) )
124
+ . map ( |( t, tts) | tts. exprs ( t) ) ;
125
+
126
+ if res. is_none ( ) {
127
+ self . types_wishlist . insert ( ty. clone ( ) ) ;
128
+ }
129
+
130
+ res
119
131
}
120
132
121
133
/// Same as find but automatically creates shared reference of types in the lookup
122
134
///
123
135
/// For example if we have type `i32` in data and we query for `&i32` it map all the type
124
136
/// trees we have for `i32` with `Expr::Reference` and returns them.
125
- fn find_autoref ( & self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
126
- self . data
137
+ fn find_autoref ( & mut self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
138
+ let res = self
139
+ . data
127
140
. iter ( )
128
141
. find ( |( t, _) | t. could_unify_with_deeply ( db, ty) )
129
142
. map ( |( t, it) | it. exprs ( t) )
@@ -139,7 +152,13 @@ impl LookupTable {
139
152
. map ( |expr| Expr :: Reference ( Box :: new ( expr) ) )
140
153
. collect ( )
141
154
} )
142
- } )
155
+ } ) ;
156
+
157
+ if res. is_none ( ) {
158
+ self . types_wishlist . insert ( ty. clone ( ) ) ;
159
+ }
160
+
161
+ res
143
162
}
144
163
145
164
/// Insert new type trees for type
@@ -149,7 +168,12 @@ impl LookupTable {
149
168
/// but they clearly do not unify themselves.
150
169
fn insert ( & mut self , ty : Type , exprs : impl Iterator < Item = Expr > ) {
151
170
match self . data . get_mut ( & ty) {
152
- Some ( it) => it. extend_with_threshold ( self . many_threshold , exprs) ,
171
+ Some ( it) => {
172
+ it. extend_with_threshold ( self . many_threshold , exprs) ;
173
+ if it. is_many ( ) {
174
+ self . types_wishlist . remove ( & ty) ;
175
+ }
176
+ }
153
177
None => {
154
178
self . data . insert ( ty. clone ( ) , AlternativeExprs :: new ( self . many_threshold , exprs) ) ;
155
179
for it in self . new_types . values_mut ( ) {
@@ -206,8 +230,8 @@ impl LookupTable {
206
230
}
207
231
208
232
/// Types queried but not found
209
- fn take_types_wishlist ( & mut self ) -> FxHashSet < Type > {
210
- std :: mem :: take ( & mut self . types_wishlist )
233
+ fn types_wishlist ( & mut self ) -> & FxHashSet < Type > {
234
+ & self . types_wishlist
211
235
}
212
236
}
213
237
@@ -272,7 +296,7 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
272
296
defs. insert ( def) ;
273
297
} ) ;
274
298
275
- let mut lookup = LookupTable :: new ( ctx. config . many_alternatives_threshold ) ;
299
+ let mut lookup = LookupTable :: new ( ctx. config . many_alternatives_threshold , ctx . goal . clone ( ) ) ;
276
300
277
301
// Try trivial tactic first, also populates lookup table
278
302
let mut solutions: Vec < Expr > = tactics:: trivial ( ctx, & defs, & mut lookup) . collect ( ) ;
0 commit comments