diff options
author | Florian Diebold <[email protected]> | 2019-05-07 16:35:45 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-05-11 15:21:20 +0100 |
commit | 7744cd41e2ad79c1b36d3d9fccd3bc0dbfd9e2d9 (patch) | |
tree | 0943a0bfd0ce6d61d28730a37130907507fdc9d1 | |
parent | d8cd0e36f5288dd4c14fb5a07b73533d88f29788 (diff) |
Reduce Chalk max_size parameter, add test for slow case
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 7 |
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] | ||
2585 | fn 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 | ||
2590 | trait Send {} | ||
2591 | |||
2592 | struct S1; impl Send for S1; | ||
2593 | struct S2; impl Send for S2; | ||
2594 | struct U1; | ||
2595 | |||
2596 | trait Trait { fn method(self); } | ||
2597 | |||
2598 | struct X1<A, B> {} | ||
2599 | impl<A, B> Send for X1<A, B> where A: Send, B: Send {} | ||
2600 | |||
2601 | struct S<B, C> {} | ||
2602 | |||
2603 | trait Fn {} | ||
2604 | |||
2605 | impl<B, C> Trait for S<B, C> where C: Fn, B: Send {} | ||
2606 | |||
2607 | fn test() { (S {}).method()<|>; } | ||
2608 | "#, | ||
2609 | ); | ||
2610 | assert_eq!(t, "{unknown}"); | ||
2611 | } | ||
2612 | |||
2584 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 2613 | fn 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 | ||
15 | pub(crate) type Solver = chalk_solve::Solver; | 15 | pub(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. | ||
20 | const CHALK_SOLVER_MAX_SIZE: usize = 2; | ||
21 | |||
17 | #[derive(Debug, Copy, Clone)] | 22 | #[derive(Debug, Copy, Clone)] |
18 | struct ChalkContext<'a, DB> { | 23 | struct ChalkContext<'a, DB> { |
19 | db: &'a DB, | 24 | db: &'a DB, |
@@ -22,7 +27,8 @@ struct ChalkContext<'a, DB> { | |||
22 | 27 | ||
23 | pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { | 28 | pub(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, |