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.rs | 82 |
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 { |