Skip to content

Commit 20fb0f7

Browse files
committed
Make it possible to cache the result of env elaboration
`program_clauses_for_env` can take a huge amount of time -- rust-analyzer is unusably slow on the Chalk codebase itself, spending most of that time in env elaboration because one `I: Interner` results in ~300 clauses, which gets repeated tens of times per query. This adds a method to `RustIrDatabase` that should basically just be a pass-through for `program_clauses_for_env`, but which makes it possible to cache the results in Salsa. The effect of this is a ~20% speedup of analysis of rust-analyzer on itself, and turning analysis of the Chalk codebase from seemingly forever to ~1 minute.
1 parent 27a9850 commit 20fb0f7

File tree

4 files changed

+37
-15
lines changed

4 files changed

+37
-15
lines changed

chalk-integration/src/db.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use chalk_ir::tls;
88
use chalk_ir::AssocTypeId;
99
use chalk_ir::Canonical;
1010
use chalk_ir::ConstrainedSubst;
11+
use chalk_ir::Environment;
1112
use chalk_ir::Goal;
1213
use chalk_ir::ImplId;
1314
use chalk_ir::InEnvironment;
@@ -17,7 +18,7 @@ use chalk_ir::ProgramClause;
1718
use chalk_ir::StructId;
1819
use chalk_ir::TraitId;
1920
use chalk_ir::TypeName;
20-
use chalk_ir::UCanonical;
21+
use chalk_ir::{ProgramClauses, UCanonical};
2122
use chalk_rust_ir::AssociatedTyDatum;
2223
use chalk_rust_ir::AssociatedTyValue;
2324
use chalk_rust_ir::AssociatedTyValueId;
@@ -150,6 +151,13 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
150151
.well_known_trait_id(well_known_trait)
151152
}
152153

154+
fn program_clauses_for_env(
155+
&self,
156+
environment: &Environment<ChalkIr>,
157+
) -> ProgramClauses<ChalkIr> {
158+
chalk_solve::program_clauses_for_env(self, environment)
159+
}
160+
153161
fn interner(&self) -> &ChalkIr {
154162
&ChalkIr
155163
}

chalk-integration/src/program.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,13 @@ impl RustIrDatabase<ChalkIr> for Program {
390390
self.well_known_traits.get(&well_known_trait).map(|x| *x)
391391
}
392392

393+
fn program_clauses_for_env(
394+
&self,
395+
environment: &chalk_ir::Environment<ChalkIr>,
396+
) -> ProgramClauses<ChalkIr> {
397+
chalk_solve::program_clauses_for_env(self, environment)
398+
}
399+
393400
fn interner(&self) -> &ChalkIr {
394401
&ChalkIr
395402
}

chalk-solve/src/clauses.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,13 @@ pub(crate) fn program_clauses_for_goal<'db, I: Interner>(
127127
let mut vec = vec![];
128128
vec.extend(db.custom_clauses());
129129
program_clauses_that_could_match(db, environment, goal, &mut vec)?;
130-
program_clauses_for_env(db, environment, &mut vec);
131130
vec.retain(|c| c.could_match(interner, goal));
131+
vec.extend(
132+
db.program_clauses_for_env(environment)
133+
.iter(interner)
134+
.filter(|c| (*c).could_match(interner, goal))
135+
.cloned(),
136+
);
132137

133138
debug!("vec = {:#?}", vec);
134139

@@ -468,20 +473,16 @@ fn match_struct<I: Interner>(builder: &mut ClauseBuilder<'_, I>, struct_id: Stru
468473
.to_program_clauses(builder)
469474
}
470475

471-
fn program_clauses_for_env<'db, I: Interner>(
476+
pub fn program_clauses_for_env<'db, I: Interner>(
472477
db: &'db dyn RustIrDatabase<I>,
473478
environment: &Environment<I>,
474-
clauses: &mut Vec<ProgramClause<I>>,
475-
) {
476-
clauses.extend(environment.clauses.iter(db.interner()).cloned());
477-
478-
let mut last_round = FxHashSet::default();
479-
elaborate_env_clauses(
480-
db,
481-
environment.clauses.as_slice(db.interner()),
482-
&mut last_round,
483-
);
484-
479+
) -> ProgramClauses<I> {
480+
let mut last_round = environment
481+
.clauses
482+
.as_slice(db.interner())
483+
.iter()
484+
.cloned()
485+
.collect::<FxHashSet<_>>();
485486
let mut closure = last_round.clone();
486487
let mut next_round = FxHashSet::default();
487488
while !last_round.is_empty() {
@@ -493,5 +494,5 @@ fn program_clauses_for_env<'db, I: Interner>(
493494
);
494495
}
495496

496-
clauses.extend(closure.drain())
497+
ProgramClauses::from(db.interner(), closure)
497498
}

chalk-solve/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,15 @@ pub trait RustIrDatabase<I: Interner>: Debug {
8787
/// Returns id of a trait lang item, if found
8888
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option<TraitId<I>>;
8989

90+
/// Calculates program clauses from an env. This is intended to call the
91+
/// `program_clauses_for_env` function and then possibly cache the clauses.
92+
fn program_clauses_for_env(&self, environment: &Environment<I>) -> ProgramClauses<I>;
93+
9094
fn interner(&self) -> &I;
9195
}
9296

97+
pub use clauses::program_clauses_for_env;
98+
9399
pub use solve::Guidance;
94100
pub use solve::Solution;
95101
pub use solve::Solver;

0 commit comments

Comments
 (0)