aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/db.rs9
-rw-r--r--crates/ra_hir/src/ty/traits.rs54
2 files changed, 41 insertions, 22 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 358365176..7b7974f5b 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,6 +1,5 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use parking_lot::Mutex;
4use ra_db::{salsa, SourceDatabase}; 3use ra_db::{salsa, SourceDatabase};
5use ra_syntax::{ast, Parse, SmolStr, SyntaxNode}; 4use ra_syntax::{ast, Parse, SmolStr, SyntaxNode};
6 5
@@ -147,6 +146,7 @@ pub trait DefDatabase: InternDatabase {
147} 146}
148 147
149#[salsa::query_group(HirDatabaseStorage)] 148#[salsa::query_group(HirDatabaseStorage)]
149#[salsa::requires(salsa::Database)]
150pub trait HirDatabase: DefDatabase + AstDatabase { 150pub trait HirDatabase: DefDatabase + AstDatabase {
151 #[salsa::invoke(ExprScopes::expr_scopes_query)] 151 #[salsa::invoke(ExprScopes::expr_scopes_query)]
152 fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>; 152 fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>;
@@ -187,11 +187,10 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
187 /// This provides the Chalk trait solver instance. Because Chalk always 187 /// This provides the Chalk trait solver instance. Because Chalk always
188 /// works from a specific crate, this query is keyed on the crate; and 188 /// works from a specific crate, this query is keyed on the crate; and
189 /// because Chalk does its own internal caching, the solver is wrapped in a 189 /// because Chalk does its own internal caching, the solver is wrapped in a
190 /// Mutex and the query is marked volatile, to make sure the cached state is 190 /// Mutex and the query does an untracked read internally, to make sure the
191 /// thrown away when input facts change. 191 /// cached state is thrown away when input facts change.
192 #[salsa::invoke(crate::ty::traits::trait_solver_query)] 192 #[salsa::invoke(crate::ty::traits::trait_solver_query)]
193 #[salsa::volatile] 193 fn trait_solver(&self, krate: Crate) -> crate::ty::traits::TraitSolver;
194 fn trait_solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>;
195 194
196 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] 195 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
197 fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>; 196 fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index fde5d8a47..5406fb4a6 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_with_fuel(&context, goal, Some(1000));
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