1
1
//! Term search
2
2
3
+ use std:: time:: { Duration , Instant } ;
4
+
3
5
use hir_def:: type_ref:: Mutability ;
4
6
use hir_ty:: db:: HirDatabase ;
5
7
use itertools:: Itertools ;
@@ -190,11 +192,11 @@ impl LookupTable {
190
192
}
191
193
None => {
192
194
self . data . insert ( ty. clone ( ) , AlternativeExprs :: new ( self . many_threshold , exprs) ) ;
195
+ for it in self . new_types . values_mut ( ) {
196
+ it. push ( ty. clone ( ) ) ;
197
+ }
193
198
}
194
199
}
195
- for it in self . new_types . values_mut ( ) {
196
- it. push ( ty. clone ( ) ) ;
197
- }
198
200
}
199
201
200
202
/// Iterate all the reachable types
@@ -269,13 +271,20 @@ pub struct TermSearchConfig {
269
271
pub enable_borrowcheck : bool ,
270
272
/// Indicate when to squash multiple trees to `Many` as there are too many to keep track
271
273
pub many_alternatives_threshold : usize ,
272
- /// Depth of the search eg . number of cycles to run
274
+ /// Depth of the search i.e . number of cycles to run
273
275
pub depth : usize ,
276
+ /// Time fuel for term search
277
+ pub fuel : Option < Duration > ,
274
278
}
275
279
276
280
impl Default for TermSearchConfig {
277
281
fn default ( ) -> Self {
278
- Self { enable_borrowcheck : true , many_alternatives_threshold : 1 , depth : 6 }
282
+ Self {
283
+ enable_borrowcheck : true ,
284
+ many_alternatives_threshold : 1 ,
285
+ depth : 5 ,
286
+ fuel : Some ( Duration :: from_millis ( 100 ) ) ,
287
+ }
279
288
}
280
289
}
281
290
@@ -294,8 +303,7 @@ impl Default for TermSearchConfig {
294
303
/// transformation tactics. For example functions take as from set of types (arguments) to some
295
304
/// type (return type). Other transformations include methods on type, type constructors and
296
305
/// projections to struct fields (field access).
297
- /// 3. Once we manage to find path to type we are interested in we continue for single round to see
298
- /// if we can find more paths that take us to the `goal` type.
306
+ /// 3. If we run out of fuel (term search takes too long) we stop iterating.
299
307
/// 4. Return all the paths (type trees) that take us to the `goal` type.
300
308
///
301
309
/// Note that there are usually more ways we can get to the `goal` type but some are discarded to
@@ -311,6 +319,7 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
311
319
} ) ;
312
320
313
321
let mut lookup = LookupTable :: new ( ctx. config . many_alternatives_threshold , ctx. goal . clone ( ) ) ;
322
+ let start = Instant :: now ( ) ;
314
323
315
324
// Try trivial tactic first, also populates lookup table
316
325
let mut solutions: Vec < Expr > = tactics:: trivial ( ctx, & defs, & mut lookup) . collect ( ) ;
@@ -320,11 +329,29 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
320
329
for _ in 0 ..ctx. config . depth {
321
330
lookup. new_round ( ) ;
322
331
332
+ if ctx. config . fuel . is_some_and ( |timeout| start. elapsed ( ) > timeout) {
333
+ break ;
334
+ }
323
335
solutions. extend ( tactics:: type_constructor ( ctx, & defs, & mut lookup) ) ;
336
+ if ctx. config . fuel . is_some_and ( |timeout| start. elapsed ( ) > timeout) {
337
+ break ;
338
+ }
324
339
solutions. extend ( tactics:: free_function ( ctx, & defs, & mut lookup) ) ;
340
+ if ctx. config . fuel . is_some_and ( |timeout| start. elapsed ( ) > timeout) {
341
+ break ;
342
+ }
325
343
solutions. extend ( tactics:: impl_method ( ctx, & defs, & mut lookup) ) ;
344
+ if ctx. config . fuel . is_some_and ( |timeout| start. elapsed ( ) > timeout) {
345
+ break ;
346
+ }
326
347
solutions. extend ( tactics:: struct_projection ( ctx, & defs, & mut lookup) ) ;
348
+ if ctx. config . fuel . is_some_and ( |timeout| start. elapsed ( ) > timeout) {
349
+ break ;
350
+ }
327
351
solutions. extend ( tactics:: impl_static_method ( ctx, & defs, & mut lookup) ) ;
352
+ if ctx. config . fuel . is_some_and ( |timeout| start. elapsed ( ) > timeout) {
353
+ break ;
354
+ }
328
355
solutions. extend ( tactics:: make_tuple ( ctx, & defs, & mut lookup) ) ;
329
356
330
357
// Discard not interesting `ScopeDef`s for speedup
0 commit comments