aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/traits.rs')
-rw-r--r--crates/ra_hir/src/ty/traits.rs20
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.
2use std::sync::{Arc, Mutex}; 2use std::sync::{Arc, Mutex};
3 3
4use rustc_hash::FxHashSet;
4use log::debug; 5use log::debug;
5use chalk_ir::cast::Cast; 6use chalk_ir::cast::Cast;
6 7
@@ -13,6 +14,11 @@ mod chalk;
13 14
14pub(crate) type Solver = chalk_solve::Solver; 15pub(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.
20const CHALK_SOLVER_MAX_SIZE: usize = 2;
21
16#[derive(Debug, Copy, Clone)] 22#[derive(Debug, Copy, Clone)]
17struct ChalkContext<'a, DB> { 23struct ChalkContext<'a, DB> {
18 db: &'a DB, 24 db: &'a DB,
@@ -21,7 +27,8 @@ struct ChalkContext<'a, DB> {
21 27
22pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { 28pub(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
48fn solve( 55fn 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)]
128pub(crate) struct SolutionVariables(pub Canonical<Vec<Ty>>); 136pub 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.
132pub(crate) enum Solution { 140pub 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.
147pub(crate) enum Guidance { 155pub 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.