diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/db.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 54 |
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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use parking_lot::Mutex; | ||
4 | use ra_db::{salsa, SourceDatabase}; | 3 | use ra_db::{salsa, SourceDatabase}; |
5 | use ra_syntax::{ast, Parse, SmolStr, SyntaxNode}; | 4 | use 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)] | ||
150 | pub trait HirDatabase: DefDatabase + AstDatabase { | 150 | pub 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; | |||
4 | use chalk_ir::cast::Cast; | 4 | use chalk_ir::cast::Cast; |
5 | use log::debug; | 5 | use log::debug; |
6 | use parking_lot::Mutex; | 6 | use parking_lot::Mutex; |
7 | use ra_db::salsa; | ||
7 | use ra_prof::profile; | 8 | use ra_prof::profile; |
8 | use rustc_hash::FxHashSet; | 9 | use rustc_hash::FxHashSet; |
9 | 10 | ||
@@ -14,7 +15,34 @@ use self::chalk::{from_chalk, ToChalk}; | |||
14 | 15 | ||
15 | pub(crate) mod chalk; | 16 | pub(crate) mod chalk; |
16 | 17 | ||
17 | pub(crate) type Solver = chalk_solve::Solver; | 18 | #[derive(Debug, Clone)] |
19 | pub struct TraitSolver { | ||
20 | krate: Crate, | ||
21 | inner: Arc<Mutex<chalk_solve::Solver>>, | ||
22 | } | ||
23 | |||
24 | /// We need eq for salsa | ||
25 | impl PartialEq for TraitSolver { | ||
26 | fn eq(&self, other: &TraitSolver) -> bool { | ||
27 | Arc::ptr_eq(&self.inner, &other.inner) | ||
28 | } | ||
29 | } | ||
30 | |||
31 | impl Eq for TraitSolver {} | ||
32 | |||
33 | impl 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 | ||
30 | pub(crate) fn trait_solver_query(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { | 58 | pub(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 | ||
57 | fn 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 | ||