diff options
Diffstat (limited to 'crates/ra_hir/src/ty/traits.rs')
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index a1ed0c028..4260f7ef7 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::sync::{Arc, Mutex}; | 2 | use std::sync::{Arc, Mutex}; |
3 | 3 | ||
4 | use rustc_hash::FxHashSet; | ||
4 | use log::debug; | 5 | use log::debug; |
5 | use chalk_ir::cast::Cast; | 6 | use chalk_ir::cast::Cast; |
6 | 7 | ||
@@ -13,6 +14,11 @@ mod chalk; | |||
13 | 14 | ||
14 | pub(crate) type Solver = chalk_solve::Solver; | 15 | pub(crate) type Solver = chalk_solve::Solver; |
15 | 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 | |||
16 | #[derive(Debug, Copy, Clone)] | 22 | #[derive(Debug, Copy, Clone)] |
17 | struct ChalkContext<'a, DB> { | 23 | struct ChalkContext<'a, DB> { |
18 | db: &'a DB, | 24 | db: &'a DB, |
@@ -21,7 +27,8 @@ struct ChalkContext<'a, DB> { | |||
21 | 27 | ||
22 | 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>> { |
23 | // 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 |
24 | 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); | ||
25 | Arc::new(Mutex::new(solver_choice.into_solver())) | 32 | Arc::new(Mutex::new(solver_choice.into_solver())) |
26 | } | 33 | } |
27 | 34 | ||
@@ -31,7 +38,7 @@ pub(crate) fn impls_for_trait( | |||
31 | krate: Crate, | 38 | krate: Crate, |
32 | trait_: Trait, | 39 | trait_: Trait, |
33 | ) -> Arc<[ImplBlock]> { | 40 | ) -> Arc<[ImplBlock]> { |
34 | let mut impls = Vec::new(); | 41 | let mut impls = FxHashSet::default(); |
35 | // We call the query recursively here. On the one hand, this means we can | 42 | // We call the query recursively here. On the one hand, this means we can |
36 | // reuse results from queries for different crates; on the other hand, this | 43 | // reuse results from queries for different crates; on the other hand, this |
37 | // will only ever get called for a few crates near the root of the tree (the | 44 | // will only ever get called for a few crates near the root of the tree (the |
@@ -42,7 +49,7 @@ pub(crate) fn impls_for_trait( | |||
42 | } | 49 | } |
43 | let crate_impl_blocks = db.impls_in_crate(krate); | 50 | let crate_impl_blocks = db.impls_in_crate(krate); |
44 | impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_)); | 51 | impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_)); |
45 | impls.into() | 52 | impls.into_iter().collect::<Vec<_>>().into() |
46 | } | 53 | } |
47 | 54 | ||
48 | fn solve( | 55 | fn solve( |
@@ -52,6 +59,7 @@ fn solve( | |||
52 | ) -> Option<chalk_solve::Solution> { | 59 | ) -> Option<chalk_solve::Solution> { |
53 | let context = ChalkContext { db, krate }; | 60 | let context = ChalkContext { db, krate }; |
54 | let solver = db.solver(krate); | 61 | let solver = db.solver(krate); |
62 | debug!("solve goal: {:?}", goal); | ||
55 | let solution = solver.lock().unwrap().solve(&context, goal); | 63 | let solution = solver.lock().unwrap().solve(&context, goal); |
56 | debug!("solve({:?}) => {:?}", goal, solution); | 64 | debug!("solve({:?}) => {:?}", goal, solution); |
57 | solution | 65 | solution |
@@ -125,11 +133,11 @@ fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) - | |||
125 | } | 133 | } |
126 | 134 | ||
127 | #[derive(Clone, Debug, PartialEq, Eq)] | 135 | #[derive(Clone, Debug, PartialEq, Eq)] |
128 | pub(crate) struct SolutionVariables(pub Canonical<Vec<Ty>>); | 136 | pub struct SolutionVariables(pub Canonical<Vec<Ty>>); |
129 | 137 | ||
130 | #[derive(Clone, Debug, PartialEq, Eq)] | 138 | #[derive(Clone, Debug, PartialEq, Eq)] |
131 | /// A (possible) solution for a proposed goal. | 139 | /// A (possible) solution for a proposed goal. |
132 | pub(crate) enum Solution { | 140 | pub enum Solution { |
133 | /// The goal indeed holds, and there is a unique value for all existential | 141 | /// The goal indeed holds, and there is a unique value for all existential |
134 | /// variables. | 142 | /// variables. |
135 | Unique(SolutionVariables), | 143 | Unique(SolutionVariables), |
@@ -144,7 +152,7 @@ pub(crate) enum Solution { | |||
144 | #[derive(Clone, Debug, PartialEq, Eq)] | 152 | #[derive(Clone, Debug, PartialEq, Eq)] |
145 | /// When a goal holds ambiguously (e.g., because there are multiple possible | 153 | /// When a goal holds ambiguously (e.g., because there are multiple possible |
146 | /// solutions), we issue a set of *guidance* back to type inference. | 154 | /// solutions), we issue a set of *guidance* back to type inference. |
147 | pub(crate) enum Guidance { | 155 | pub enum Guidance { |
148 | /// The existential variables *must* have the given values if the goal is | 156 | /// The existential variables *must* have the given values if the goal is |
149 | /// ever to hold, but that alone isn't enough to guarantee the goal will | 157 | /// ever to hold, but that alone isn't enough to guarantee the goal will |
150 | /// actually hold. | 158 | /// actually hold. |