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 | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs index c8729af86a..5b2bca955f 100644 --- a/crates/hir-ty/src/mir/borrowck.rs +++ b/crates/hir-ty/src/mir/borrowck.rs @@ -3,13 +3,13 @@ // Currently it is an ad-hoc implementation, only useful for mutability analysis. Feel free to remove all of these // if needed for implementing a proper borrow checker. -use std::sync::Arc; +use std::{iter, sync::Arc}; use hir_def::DefWithBodyId; use la_arena::ArenaMap; use stdx::never; -use crate::db::HirDatabase; +use crate::{db::HirDatabase, ClosureId}; use super::{ BasicBlockId, BorrowKind, LocalId, MirBody, MirLowerError, MirSpan, Place, ProjectionElem, @@ -29,14 +29,48 @@ pub struct BorrowckResult { pub mutability_of_locals: ArenaMap<LocalId, MutabilityReason>, } +fn all_mir_bodies( + db: &dyn HirDatabase, + def: DefWithBodyId, +) -> Box<dyn Iterator<Item = Result<Arc<MirBody>, MirLowerError>> + '_> { + fn for_closure( + db: &dyn HirDatabase, + c: ClosureId, + ) -> Box<dyn Iterator<Item = Result<Arc<MirBody>, MirLowerError>> + '_> { + match db.mir_body_for_closure(c) { + Ok(body) => { + let closures = body.closures.clone(); + Box::new( + iter::once(Ok(body)) + .chain(closures.into_iter().flat_map(|x| for_closure(db, x))), + ) + } + Err(e) => Box::new(iter::once(Err(e))), + } + } + match db.mir_body(def) { + Ok(body) => { + let closures = body.closures.clone(); + Box::new( + iter::once(Ok(body)).chain(closures.into_iter().flat_map(|x| for_closure(db, x))), + ) + } + Err(e) => Box::new(iter::once(Err(e))), + } +} + pub fn borrowck_query( db: &dyn HirDatabase, def: DefWithBodyId, -) -> Result<Arc<BorrowckResult>, MirLowerError> { +) -> Result<Arc<[BorrowckResult]>, MirLowerError> { let _p = profile::span("borrowck_query"); - let body = db.mir_body(def)?; - let r = BorrowckResult { mutability_of_locals: mutability_of_locals(&body), mir_body: body }; - Ok(Arc::new(r)) + let r = all_mir_bodies(db, def) + .map(|body| { + let body = body?; + Ok(BorrowckResult { mutability_of_locals: mutability_of_locals(&body), mir_body: body }) + }) + .collect::<Result<Vec<_>, MirLowerError>>()?; + Ok(r.into()) } fn is_place_direct(lvalue: &Place) -> bool { @@ -60,7 +94,7 @@ fn place_case(lvalue: &Place) -> ProjectionCase { ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Field(_) - | ProjectionElem::TupleField(_) + | ProjectionElem::TupleOrClosureField(_) | ProjectionElem::Index(_) => { is_part_of = true; } |