mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
switch from volatile to untracked read
This commit is contained in:
parent
5ed6a13a2c
commit
9266c18ce6
2 changed files with 41 additions and 22 deletions
|
@ -1,6 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use ra_db::{salsa, SourceDatabase};
|
||||
use ra_syntax::{ast, Parse, SmolStr, SyntaxNode};
|
||||
|
||||
|
@ -147,6 +146,7 @@ pub trait DefDatabase: InternDatabase {
|
|||
}
|
||||
|
||||
#[salsa::query_group(HirDatabaseStorage)]
|
||||
#[salsa::requires(salsa::Database)]
|
||||
pub trait HirDatabase: DefDatabase + AstDatabase {
|
||||
#[salsa::invoke(ExprScopes::expr_scopes_query)]
|
||||
fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>;
|
||||
|
@ -187,11 +187,10 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
|
|||
/// This provides the Chalk trait solver instance. Because Chalk always
|
||||
/// works from a specific crate, this query is keyed on the crate; and
|
||||
/// because Chalk does its own internal caching, the solver is wrapped in a
|
||||
/// Mutex and the query is marked volatile, to make sure the cached state is
|
||||
/// thrown away when input facts change.
|
||||
/// Mutex and the query does an untracked read internally, to make sure the
|
||||
/// cached state is thrown away when input facts change.
|
||||
#[salsa::invoke(crate::ty::traits::trait_solver_query)]
|
||||
#[salsa::volatile]
|
||||
fn trait_solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>;
|
||||
fn trait_solver(&self, krate: Crate) -> crate::ty::traits::TraitSolver;
|
||||
|
||||
#[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
|
||||
fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::sync::Arc;
|
|||
use chalk_ir::cast::Cast;
|
||||
use log::debug;
|
||||
use parking_lot::Mutex;
|
||||
use ra_db::salsa;
|
||||
use ra_prof::profile;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
|
@ -14,7 +15,34 @@ use self::chalk::{from_chalk, ToChalk};
|
|||
|
||||
pub(crate) mod chalk;
|
||||
|
||||
pub(crate) type Solver = chalk_solve::Solver;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TraitSolver {
|
||||
krate: Crate,
|
||||
inner: Arc<Mutex<chalk_solve::Solver>>,
|
||||
}
|
||||
|
||||
/// We need eq for salsa
|
||||
impl PartialEq for TraitSolver {
|
||||
fn eq(&self, other: &TraitSolver) -> bool {
|
||||
Arc::ptr_eq(&self.inner, &other.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for TraitSolver {}
|
||||
|
||||
impl TraitSolver {
|
||||
fn solve(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal>>,
|
||||
) -> Option<chalk_solve::Solution> {
|
||||
let context = ChalkContext { db, krate: self.krate };
|
||||
debug!("solve goal: {:?}", goal);
|
||||
let solution = self.inner.lock().solve_with_fuel(&context, goal, Some(1000));
|
||||
debug!("solve({:?}) => {:?}", goal, solution);
|
||||
solution
|
||||
}
|
||||
}
|
||||
|
||||
/// This controls the maximum size of types Chalk considers. If we set this too
|
||||
/// 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> {
|
|||
krate: Crate,
|
||||
}
|
||||
|
||||
pub(crate) fn trait_solver_query(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> {
|
||||
pub(crate) fn trait_solver_query(
|
||||
db: &(impl HirDatabase + salsa::Database),
|
||||
krate: Crate,
|
||||
) -> TraitSolver {
|
||||
db.salsa_runtime().report_untracked_read();
|
||||
// krate parameter is just so we cache a unique solver per crate
|
||||
let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
|
||||
debug!("Creating new solver for crate {:?}", _krate);
|
||||
Arc::new(Mutex::new(solver_choice.into_solver()))
|
||||
debug!("Creating new solver for crate {:?}", krate);
|
||||
TraitSolver { krate, inner: Arc::new(Mutex::new(solver_choice.into_solver())) }
|
||||
}
|
||||
|
||||
/// Collects impls for the given trait in the whole dependency tree of `krate`.
|
||||
|
@ -54,18 +86,6 @@ pub(crate) fn impls_for_trait_query(
|
|||
impls.into_iter().collect::<Vec<_>>().into()
|
||||
}
|
||||
|
||||
fn solve(
|
||||
db: &impl HirDatabase,
|
||||
krate: Crate,
|
||||
goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal>>,
|
||||
) -> Option<chalk_solve::Solution> {
|
||||
let context = ChalkContext { db, krate };
|
||||
let solver = db.trait_solver(krate);
|
||||
let solution = solver.lock().solve(&context, goal);
|
||||
debug!("solve({:?}) => {:?}", goal, solution);
|
||||
solution
|
||||
}
|
||||
|
||||
/// A set of clauses that we assume to be true. E.g. if we are inside this function:
|
||||
/// ```rust
|
||||
/// fn foo<T: Default>(t: T) {}
|
||||
|
@ -127,7 +147,7 @@ pub(crate) fn trait_solve_query(
|
|||
// We currently don't deal with universes (I think / hope they're not yet
|
||||
// relevant for our use cases?)
|
||||
let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
|
||||
let solution = solve(db, krate, &u_canonical);
|
||||
let solution = db.trait_solver(krate).solve(db, &u_canonical);
|
||||
solution.map(|solution| solution_from_chalk(db, solution))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue