aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-05-07 16:35:45 +0100
committerFlorian Diebold <[email protected]>2019-05-11 15:21:20 +0100
commit7744cd41e2ad79c1b36d3d9fccd3bc0dbfd9e2d9 (patch)
tree0943a0bfd0ce6d61d28730a37130907507fdc9d1 /crates/ra_hir/src
parentd8cd0e36f5288dd4c14fb5a07b73533d88f29788 (diff)
Reduce Chalk max_size parameter, add test for slow case
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty/tests.rs29
-rw-r--r--crates/ra_hir/src/ty/traits.rs9
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs7
3 files changed, 42 insertions, 3 deletions
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f0793bfb4..6f8d8fa49 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2581,6 +2581,35 @@ fn test() { foo.call()<|>; }
2581 ); 2581 );
2582} 2582}
2583 2583
2584#[test]
2585fn method_resolution_slow() {
2586 // this can get quite slow if we set the solver size limit too high
2587 let t = type_at(
2588 r#"
2589//- /main.rs
2590trait Send {}
2591
2592struct S1; impl Send for S1;
2593struct S2; impl Send for S2;
2594struct U1;
2595
2596trait Trait { fn method(self); }
2597
2598struct X1<A, B> {}
2599impl<A, B> Send for X1<A, B> where A: Send, B: Send {}
2600
2601struct S<B, C> {}
2602
2603trait Fn {}
2604
2605impl<B, C> Trait for S<B, C> where C: Fn, B: Send {}
2606
2607fn test() { (S {}).method()<|>; }
2608"#,
2609 );
2610 assert_eq!(t, "{unknown}");
2611}
2612
2584fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 2613fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
2585 let file = db.parse(pos.file_id); 2614 let file = db.parse(pos.file_id);
2586 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 2615 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 4bbc99f0e..4260f7ef7 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -14,6 +14,11 @@ mod chalk;
14 14
15pub(crate) type Solver = chalk_solve::Solver; 15pub(crate) type Solver = chalk_solve::Solver;
16 16
17/// This controls the maximum size of types Chalk considers. If we set this too
18/// high, we can run into slow edge cases; if we set it too low, Chalk won't
19/// find some solutions.
20const CHALK_SOLVER_MAX_SIZE: usize = 2;
21
17#[derive(Debug, Copy, Clone)] 22#[derive(Debug, Copy, Clone)]
18struct ChalkContext<'a, DB> { 23struct ChalkContext<'a, DB> {
19 db: &'a DB, 24 db: &'a DB,
@@ -22,7 +27,8 @@ struct ChalkContext<'a, DB> {
22 27
23pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { 28pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> {
24 // krate parameter is just so we cache a unique solver per crate 29 // krate parameter is just so we cache a unique solver per crate
25 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: 10 }; 30 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
31 debug!("Creating new solver for crate {:?}", _krate);
26 Arc::new(Mutex::new(solver_choice.into_solver())) 32 Arc::new(Mutex::new(solver_choice.into_solver()))
27} 33}
28 34
@@ -53,6 +59,7 @@ fn solve(
53) -> Option<chalk_solve::Solution> { 59) -> Option<chalk_solve::Solution> {
54 let context = ChalkContext { db, krate }; 60 let context = ChalkContext { db, krate };
55 let solver = db.solver(krate); 61 let solver = db.solver(krate);
62 debug!("solve goal: {:?}", goal);
56 let solution = solver.lock().unwrap().solve(&context, goal); 63 let solution = solver.lock().unwrap().solve(&context, goal);
57 debug!("solve({:?}) => {:?}", goal, solution); 64 debug!("solve({:?}) => {:?}", goal, solution);
58 solution 65 solution
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 7bb6a4f4a..8fa0ba7a5 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -345,11 +345,14 @@ where
345 return Vec::new(); 345 return Vec::new();
346 } 346 }
347 let trait_ = from_chalk(self.db, trait_id); 347 let trait_ = from_chalk(self.db, trait_id);
348 self.db 348 let result: Vec<_> = self
349 .db
349 .impls_for_trait(self.krate, trait_) 350 .impls_for_trait(self.krate, trait_)
350 .iter() 351 .iter()
351 .map(|impl_block| impl_block.to_chalk(self.db)) 352 .map(|impl_block| impl_block.to_chalk(self.db))
352 .collect() 353 .collect();
354 debug!("impls_for_trait returned {} impls", result.len());
355 result
353 } 356 }
354 fn impl_provided_for( 357 fn impl_provided_for(
355 &self, 358 &self,