Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/borrowck.rs')
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs82
1 files changed, 50 insertions, 32 deletions
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index 17715d3fcd..dcd06ae25f 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/crates/hir-ty/src/mir/borrowck.rs
@@ -5,11 +5,11 @@
use std::iter;
+use either::Either;
use hir_def::{DefWithBodyId, ExpressionStoreOwnerId, HasModule};
use la_arena::ArenaMap;
use rustc_hash::FxHashMap;
use stdx::never;
-use triomphe::Arc;
use crate::{
closure_analysis::ProjectionKind as HirProjectionKind,
@@ -57,68 +57,86 @@ pub struct BorrowRegion {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BorrowckResult {
- pub mir_body: Arc<MirBody>,
+ owner: Either<DefWithBodyId, InternedClosureId>,
pub mutability_of_locals: ArenaMap<LocalId, MutabilityReason>,
pub moved_out_of_ref: Vec<MovedOutOfRef>,
pub partially_moved: Vec<PartiallyMoved>,
pub borrow_regions: Vec<BorrowRegion>,
}
-fn all_mir_bodies(
- db: &dyn HirDatabase,
+impl BorrowckResult {
+ pub fn mir_body<'db>(&self, db: &'db dyn HirDatabase) -> &'db MirBody {
+ match self.owner {
+ Either::Left(it) => db.mir_body(it).unwrap(),
+ Either::Right(it) => db.mir_body_for_closure(it).unwrap(),
+ }
+ }
+}
+
+fn all_mir_bodies<'db>(
+ db: &'db dyn HirDatabase,
def: DefWithBodyId,
- mut cb: impl FnMut(Arc<MirBody>) -> BorrowckResult,
- mut merge_from_closures: impl FnMut(&mut BorrowckResult, &BorrowckResult),
-) -> Result<Arc<[BorrowckResult]>, MirLowerError> {
- fn for_closure(
- db: &dyn HirDatabase,
+ mut cb: impl FnMut(&'db MirBody, Either<DefWithBodyId, InternedClosureId>) -> BorrowckResult,
+ mut merge_from_closures: impl FnMut(
+ (&mut BorrowckResult, &'db MirBody),
+ (&BorrowckResult, &'db MirBody),
+ ),
+) -> Result<Box<[BorrowckResult]>, MirLowerError> {
+ fn for_closure<'db>(
+ db: &'db dyn HirDatabase,
c: InternedClosureId,
- results: &mut Vec<BorrowckResult>,
- cb: &mut impl FnMut(Arc<MirBody>) -> BorrowckResult,
- merge_from_closures: &mut impl FnMut(&mut BorrowckResult, &BorrowckResult),
+ results: &mut Vec<(BorrowckResult, &'db MirBody)>,
+ cb: &mut impl FnMut(&'db MirBody, Either<DefWithBodyId, InternedClosureId>) -> BorrowckResult,
+ merge_from_closures: &mut impl FnMut(
+ (&mut BorrowckResult, &'db MirBody),
+ (&BorrowckResult, &'db MirBody),
+ ),
) -> Result<(), MirLowerError> {
match db.mir_body_for_closure(c) {
Ok(body) => {
let parent_index = results.len();
- results.push(cb(body.clone()));
+ results.push((cb(body, Either::Right(c)), body));
body.closures
.iter()
.try_for_each(|&it| for_closure(db, it, results, cb, merge_from_closures))?;
merge(results, merge_from_closures, parent_index);
Ok(())
}
- Err(e) => Err(e),
+ Err(e) => Err(e.clone()),
}
}
- fn merge(
- results: &mut [BorrowckResult],
- merge: &mut impl FnMut(&mut BorrowckResult, &BorrowckResult),
+ fn merge<'db>(
+ results: &mut [(BorrowckResult, &'db MirBody)],
+ merge: &mut impl FnMut((&mut BorrowckResult, &'db MirBody), (&BorrowckResult, &'db MirBody)),
parent_index: usize,
) {
let (parent_and_before, children) = results.split_at_mut(parent_index + 1);
- let parent = &mut parent_and_before[parent_and_before.len() - 1];
- children.iter().for_each(|child| merge(parent, child));
+ let (parent, parent_mir_body) = &mut parent_and_before[parent_and_before.len() - 1];
+ children.iter().for_each(|(child, child_mir_body)| {
+ merge((parent, parent_mir_body), (child, child_mir_body))
+ });
}
let mut results = Vec::new();
match db.mir_body(def) {
Ok(body) => {
- results.push(cb(body.clone()));
+ results.push((cb(body, Either::Left(def)), body));
body.closures.iter().try_for_each(|&it| {
for_closure(db, it, &mut results, &mut cb, &mut merge_from_closures)
})?;
merge(&mut results, &mut merge_from_closures, 0);
- Ok(results.into())
+ Ok(results.into_iter().map(|(it, _)| it).collect())
}
- Err(e) => Err(e),
+ Err(e) => Err(e.clone()),
}
}
+#[salsa_macros::tracked(returns(ref), lru = 2024)]
pub fn borrowck_query(
db: &dyn HirDatabase,
def: DefWithBodyId,
-) -> Result<Arc<[BorrowckResult]>, MirLowerError> {
+) -> Result<Box<[BorrowckResult]>, MirLowerError> {
let _p = tracing::info_span!("borrowck_query").entered();
let module = def.module(db);
let interner = DbInterner::new_with(db, module.krate(db));
@@ -128,20 +146,20 @@ pub fn borrowck_query(
let res = all_mir_bodies(
db,
def,
- |body| {
+ |body, owner| {
// FIXME(next-solver): Opaques.
let infcx = interner.infer_ctxt().build(typing_mode);
BorrowckResult {
- mutability_of_locals: mutability_of_locals(&infcx, env, &body),
- moved_out_of_ref: moved_out_of_ref(&infcx, env, &body),
- partially_moved: partially_moved(&infcx, env, &body),
- borrow_regions: borrow_regions(db, &body),
- mir_body: body,
+ owner,
+ mutability_of_locals: mutability_of_locals(&infcx, env, body),
+ moved_out_of_ref: moved_out_of_ref(&infcx, env, body),
+ partially_moved: partially_moved(&infcx, env, body),
+ borrow_regions: borrow_regions(db, body),
}
},
- |parent, child| {
- for (upvar, child_locals) in &child.mir_body.upvar_locals {
- let Some(&parent_local) = parent.mir_body.binding_locals.get(*upvar) else {
+ |(parent, parent_mir_body), (child, child_mir_body)| {
+ for (upvar, child_locals) in &child_mir_body.upvar_locals {
+ let Some(&parent_local) = parent_mir_body.binding_locals.get(*upvar) else {
continue;
};
for (child_local, capture_place) in child_locals {