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.rs54
1 files changed, 37 insertions, 17 deletions
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index fde5d8a47..b634f0b79 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -4,6 +4,7 @@ use std::sync::Arc;
4use chalk_ir::cast::Cast; 4use chalk_ir::cast::Cast;
5use log::debug; 5use log::debug;
6use parking_lot::Mutex; 6use parking_lot::Mutex;
7use ra_db::salsa;
7use ra_prof::profile; 8use ra_prof::profile;
8use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
9 10
@@ -14,7 +15,34 @@ use self::chalk::{from_chalk, ToChalk};
14 15
15pub(crate) mod chalk; 16pub(crate) mod chalk;
16 17
17pub(crate) type Solver = chalk_solve::Solver; 18#[derive(Debug, Clone)]
19pub struct TraitSolver {
20 krate: Crate,
21 inner: Arc<Mutex<chalk_solve::Solver>>,
22}
23
24/// We need eq for salsa
25impl PartialEq for TraitSolver {
26 fn eq(&self, other: &TraitSolver) -> bool {
27 Arc::ptr_eq(&self.inner, &other.inner)
28 }
29}
30
31impl Eq for TraitSolver {}
32
33impl TraitSolver {
34 fn solve(
35 &self,
36 db: &impl HirDatabase,
37 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal>>,
38 ) -> Option<chalk_solve::Solution> {
39 let context = ChalkContext { db, krate: self.krate };
40 debug!("solve goal: {:?}", goal);
41 let solution = self.inner.lock().solve(&context, goal);
42 debug!("solve({:?}) => {:?}", goal, solution);
43 solution
44 }
45}
18 46
19/// This controls the maximum size of types Chalk considers. If we set this too 47/// This controls the maximum size of types Chalk considers. If we set this too
20/// high, we can run into slow edge cases; if we set it too low, Chalk won't 48/// high, we can run into slow edge cases; if we set it too low, Chalk won't
@@ -27,11 +55,15 @@ struct ChalkContext<'a, DB> {
27 krate: Crate, 55 krate: Crate,
28} 56}
29 57
30pub(crate) fn trait_solver_query(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { 58pub(crate) fn trait_solver_query(
59 db: &(impl HirDatabase + salsa::Database),
60 krate: Crate,
61) -> TraitSolver {
62 db.salsa_runtime().report_untracked_read();
31 // krate parameter is just so we cache a unique solver per crate 63 // krate parameter is just so we cache a unique solver per crate
32 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE }; 64 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
33 debug!("Creating new solver for crate {:?}", _krate); 65 debug!("Creating new solver for crate {:?}", krate);
34 Arc::new(Mutex::new(solver_choice.into_solver())) 66 TraitSolver { krate, inner: Arc::new(Mutex::new(solver_choice.into_solver())) }
35} 67}
36 68
37/// Collects impls for the given trait in the whole dependency tree of `krate`. 69/// Collects impls for the given trait in the whole dependency tree of `krate`.
@@ -54,18 +86,6 @@ pub(crate) fn impls_for_trait_query(
54 impls.into_iter().collect::<Vec<_>>().into() 86 impls.into_iter().collect::<Vec<_>>().into()
55} 87}
56 88
57fn solve(
58 db: &impl HirDatabase,
59 krate: Crate,
60 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal>>,
61) -> Option<chalk_solve::Solution> {
62 let context = ChalkContext { db, krate };
63 let solver = db.trait_solver(krate);
64 let solution = solver.lock().solve(&context, goal);
65 debug!("solve({:?}) => {:?}", goal, solution);
66 solution
67}
68
69/// A set of clauses that we assume to be true. E.g. if we are inside this function: 89/// A set of clauses that we assume to be true. E.g. if we are inside this function:
70/// ```rust 90/// ```rust
71/// fn foo<T: Default>(t: T) {} 91/// fn foo<T: Default>(t: T) {}
@@ -127,7 +147,7 @@ pub(crate) fn trait_solve_query(
127 // We currently don't deal with universes (I think / hope they're not yet 147 // We currently don't deal with universes (I think / hope they're not yet
128 // relevant for our use cases?) 148 // relevant for our use cases?)
129 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; 149 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
130 let solution = solve(db, krate, &u_canonical); 150 let solution = db.trait_solver(krate).solve(db, &u_canonical);
131 solution.map(|solution| solution_from_chalk(db, solution)) 151 solution.map(|solution| solution_from_chalk(db, solution))
132} 152}
133 153