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 std::sync::Arc;
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use ra_db::{salsa, SourceDatabase};
|
use ra_db::{salsa, SourceDatabase};
|
||||||
use ra_syntax::{ast, Parse, SmolStr, SyntaxNode};
|
use ra_syntax::{ast, Parse, SmolStr, SyntaxNode};
|
||||||
|
|
||||||
|
@ -147,6 +146,7 @@ pub trait DefDatabase: InternDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::query_group(HirDatabaseStorage)]
|
#[salsa::query_group(HirDatabaseStorage)]
|
||||||
|
#[salsa::requires(salsa::Database)]
|
||||||
pub trait HirDatabase: DefDatabase + AstDatabase {
|
pub trait HirDatabase: DefDatabase + AstDatabase {
|
||||||
#[salsa::invoke(ExprScopes::expr_scopes_query)]
|
#[salsa::invoke(ExprScopes::expr_scopes_query)]
|
||||||
fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>;
|
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
|
/// This provides the Chalk trait solver instance. Because Chalk always
|
||||||
/// works from a specific crate, this query is keyed on the crate; and
|
/// 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
|
/// 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
|
/// Mutex and the query does an untracked read internally, to make sure the
|
||||||
/// thrown away when input facts change.
|
/// cached state is thrown away when input facts change.
|
||||||
#[salsa::invoke(crate::ty::traits::trait_solver_query)]
|
#[salsa::invoke(crate::ty::traits::trait_solver_query)]
|
||||||
#[salsa::volatile]
|
fn trait_solver(&self, krate: Crate) -> crate::ty::traits::TraitSolver;
|
||||||
fn trait_solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>;
|
|
||||||
|
|
||||||
#[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
|
#[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
|
||||||
fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;
|
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 chalk_ir::cast::Cast;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use ra_db::salsa;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
|
@ -14,7 +15,34 @@ use self::chalk::{from_chalk, ToChalk};
|
||||||
|
|
||||||
pub(crate) mod chalk;
|
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
|
/// 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
|
/// 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,
|
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
|
// 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 };
|
let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
|
||||||
debug!("Creating new solver for crate {:?}", _krate);
|
debug!("Creating new solver for crate {:?}", krate);
|
||||||
Arc::new(Mutex::new(solver_choice.into_solver()))
|
TraitSolver { krate, inner: Arc::new(Mutex::new(solver_choice.into_solver())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collects impls for the given trait in the whole dependency tree of `krate`.
|
/// 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()
|
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:
|
/// A set of clauses that we assume to be true. E.g. if we are inside this function:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// fn foo<T: Default>(t: T) {}
|
/// 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
|
// We currently don't deal with universes (I think / hope they're not yet
|
||||||
// relevant for our use cases?)
|
// relevant for our use cases?)
|
||||||
let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
|
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))
|
solution.map(|solution| solution_from_chalk(db, solution))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue