Unnamed repository; edit this file 'description' to name the repository.
Intern MIR projections using the new ty interning infrastructure
This allows creating projections from other queries, paving the way for further MIR analyses.
conflict fixes
some cleanups
clean up into_place
| -rw-r--r-- | crates/hir-ty/src/mir.rs | 190 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/borrowck.rs | 20 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/eval.rs | 38 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/lower.rs | 182 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/lower/as_place.rs | 64 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/lower/pattern_matching.rs | 125 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/pretty.rs | 2 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver.rs | 8 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/interner.rs | 2 | ||||
| -rw-r--r-- | crates/ide/src/inlay_hints/implicit_drop.rs | 2 |
10 files changed, 330 insertions, 303 deletions
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index 5f61b1defb..e82038907c 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -1,6 +1,6 @@ //! MIR definitions and implementation -use std::{collections::hash_map::Entry, fmt::Display, iter}; +use std::{fmt::Display, iter}; use base_db::Crate; use either::Either; @@ -8,10 +8,14 @@ use hir_def::{ FieldId, StaticId, TupleFieldId, UnionId, VariantId, hir::{BindingId, Expr, ExprId, Ordering, PatId}, }; +use intern::{InternedSlice, InternedSliceRef, impl_slice_internable}; use la_arena::{Arena, ArenaMap, Idx, RawIdx}; use rustc_ast_ir::Mutability; use rustc_hash::FxHashMap; -use rustc_type_ir::inherent::{GenericArgs as _, IntoKind, Ty as _}; +use rustc_type_ir::{ + CollectAndApply, GenericTypeVisitable, + inherent::{GenericArgs as _, IntoKind, Ty as _}, +}; use smallvec::{SmallVec, smallvec}; use stdx::{impl_from, never}; @@ -24,6 +28,7 @@ use crate::{ next_solver::{ Allocation, AllocationData, DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, StoredAllocation, StoredConst, StoredGenericArgs, StoredTy, Ty, TyKind, + impl_stored_interned_slice, infer::{InferCtxt, traits::ObligationCause}, obligation_ctxt::ObligationCtxt, }, @@ -145,7 +150,7 @@ impl<'db> Operand { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum ProjectionElem<V: PartialEq> { Deref, Field(Either<FieldId, TupleFieldId>), @@ -155,7 +160,7 @@ pub enum ProjectionElem<V: PartialEq> { ConstantIndex { offset: u64, from_end: bool }, Subslice { from: u64, to: u64 }, //Downcast(Option<Symbol>, VariantIdx), - OpaqueCast(StoredTy), + OpaqueCast(std::convert::Infallible), } impl<V: PartialEq> ProjectionElem<V> { @@ -260,97 +265,114 @@ impl<V: PartialEq> ProjectionElem<V> { type PlaceElem = ProjectionElem<LocalId>; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct ProjectionId(u32); +impl<W: crate::next_solver::WorldExposer> GenericTypeVisitable<W> for PlaceElem { + fn generic_visit_with(&self, _: &mut W) {} +} + +impl_slice_internable!(gc; ProjectionStorage, (), PlaceElem); +impl_stored_interned_slice!(ProjectionStorage, Projection, StoredProjection); -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ProjectionStore { - id_to_proj: FxHashMap<ProjectionId, Box<[PlaceElem]>>, - proj_to_id: FxHashMap<Box<[PlaceElem]>, ProjectionId>, +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct Projection<'db> { + interned: InternedSliceRef<'db, ProjectionStorage>, } -impl Default for ProjectionStore { - fn default() -> Self { - let mut this = Self { id_to_proj: Default::default(), proj_to_id: Default::default() }; - // Ensure that [] will get the id 0 which is used in `ProjectionId::Empty` - this.intern(Box::new([])); - this +impl<'db> std::fmt::Debug for Projection<'db> { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + (*self).as_slice().fmt(fmt) } } -impl ProjectionStore { - pub fn shrink_to_fit(&mut self) { - self.id_to_proj.shrink_to_fit(); - self.proj_to_id.shrink_to_fit(); +impl<'db> Projection<'db> { + pub fn new_from_iter<I, T>(args: I) -> T::Output + where + I: IntoIterator<Item = T>, + T: CollectAndApply<PlaceElem, Self>, + { + CollectAndApply::collect_and_apply(args.into_iter(), Self::new_from_slice) } - pub fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option<ProjectionId> { - self.proj_to_id.get(projection).copied() + #[inline] + pub fn new_from_slice(slice: &[PlaceElem]) -> Self { + Self { interned: InternedSlice::from_header_and_slice((), slice) } } - pub fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { - let new_id = ProjectionId(self.proj_to_id.len() as u32); - match self.proj_to_id.entry(projection) { - Entry::Occupied(id) => *id.get(), - Entry::Vacant(e) => { - let key_clone = e.key().clone(); - e.insert(new_id); - self.id_to_proj.insert(new_id, key_clone); - new_id - } - } + #[inline] + pub fn as_slice(self) -> &'db [PlaceElem] { + &self.interned.get().slice + } + + pub fn project(self, projection: PlaceElem) -> Projection<'db> { + Projection::new_from_iter(self.as_slice().iter().copied().chain([projection])) } } -impl ProjectionId { - pub const EMPTY: ProjectionId = ProjectionId(0); +impl<'db> std::ops::Deref for Projection<'db> { + type Target = [PlaceElem]; - pub fn is_empty(self) -> bool { - self == ProjectionId::EMPTY + fn deref(&self) -> &Self::Target { + self.as_slice() } +} - pub fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] { - store.id_to_proj.get(&self).unwrap() +impl StoredProjection { + // FIXME: rename to as_slice + pub fn lookup(&self) -> &[PlaceElem] { + self.as_ref().as_slice() } - pub fn project(self, projection: PlaceElem, store: &mut ProjectionStore) -> ProjectionId { - let mut current = self.lookup(store).to_vec(); - current.push(projection); - store.intern(current.into()) + pub fn is_empty(&self) -> bool { + self.lookup().is_empty() } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +// FIXME: would be nicer to rename PlaceRef -> Place, Place -> StoredPlace, but I didn't want to blow up the diff +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct PlaceRef<'db> { + pub local: LocalId, + pub projection: Projection<'db>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Place { pub local: LocalId, - pub projection: ProjectionId, + pub projection: StoredProjection, } impl Place { - fn is_parent(&self, child: &Place, store: &ProjectionStore) -> bool { + pub fn as_ref<'db>(&self) -> PlaceRef<'db> { + PlaceRef { local: self.local, projection: self.projection.as_ref() } + } +} + +impl<'db> PlaceRef<'db> { + fn is_parent(&self, child: PlaceRef<'db>) -> bool { self.local == child.local - && child.projection.lookup(store).starts_with(self.projection.lookup(store)) + && child.projection.as_slice().starts_with(self.projection.as_slice()) } /// The place itself is not included - fn iterate_over_parents<'a>( - &'a self, - store: &'a ProjectionStore, - ) -> impl Iterator<Item = Place> + 'a { - let projection = self.projection.lookup(store); - (0..projection.len()).map(|x| &projection[0..x]).filter_map(move |x| { - Some(Place { local: self.local, projection: store.intern_if_exist(x)? }) + fn iterate_over_parents<'a>(&'a self) -> impl Iterator<Item = PlaceRef<'db>> + 'a { + let projection = self.projection.as_slice(); + (0..projection.len()).map(move |x| PlaceRef { + local: self.local, + projection: Projection::new_from_slice(&projection[0..x]), }) } - fn project(&self, projection: PlaceElem, store: &mut ProjectionStore) -> Place { - Place { local: self.local, projection: self.projection.project(projection, store) } + fn project(&self, projection: PlaceElem) -> PlaceRef<'db> { + PlaceRef { local: self.local, projection: self.projection.project(projection) } + } + + pub fn store(&self) -> Place { + Place { local: self.local, projection: self.projection.store() } } } -impl From<LocalId> for Place { +impl<'db> From<LocalId> for PlaceRef<'db> { fn from(local: LocalId) -> Self { - Self { local, projection: ProjectionId::EMPTY } + let empty: &[PlaceElem] = &[]; + PlaceRef { local, projection: Projection::new_from_slice(empty) } } } @@ -1081,7 +1103,6 @@ pub struct BasicBlock { #[derive(Debug, Clone, PartialEq, Eq)] pub struct MirBody { - pub projection_store: ProjectionStore, pub basic_blocks: Arena<BasicBlock>, pub locals: Arena<Local>, pub start_block: BasicBlockId, @@ -1099,15 +1120,11 @@ impl MirBody { self.binding_locals.iter().map(|(it, y)| (*y, it)).collect() } - fn walk_places(&mut self, mut f: impl FnMut(&mut Place, &mut ProjectionStore)) { - fn for_operand( - op: &mut Operand, - f: &mut impl FnMut(&mut Place, &mut ProjectionStore), - store: &mut ProjectionStore, - ) { + fn walk_places(&mut self, mut f: impl FnMut(&mut Place)) { + fn for_operand(op: &mut Operand, f: &mut impl FnMut(&mut Place)) { match &mut op.kind { OperandKind::Copy(p) | OperandKind::Move(p) => { - f(p, store); + f(p); } OperandKind::Constant { .. } | OperandKind::Static(_) @@ -1118,25 +1135,25 @@ impl MirBody { for statement in &mut block.statements { match &mut statement.kind { StatementKind::Assign(p, r) => { - f(p, &mut self.projection_store); + f(p); match r { Rvalue::ShallowInitBoxWithAlloc(_) => (), Rvalue::ShallowInitBox(o, _) | Rvalue::UnaryOp(_, o) | Rvalue::Cast(_, o, _) | Rvalue::Repeat(o, _) - | Rvalue::Use(o) => for_operand(o, &mut f, &mut self.projection_store), + | Rvalue::Use(o) => for_operand(o, &mut f), Rvalue::CopyForDeref(p) | Rvalue::Discriminant(p) | Rvalue::Len(p) - | Rvalue::Ref(_, p) => f(p, &mut self.projection_store), + | Rvalue::Ref(_, p) => f(p), Rvalue::CheckedBinaryOp(_, o1, o2) => { - for_operand(o1, &mut f, &mut self.projection_store); - for_operand(o2, &mut f, &mut self.projection_store); + for_operand(o1, &mut f); + for_operand(o2, &mut f); } Rvalue::Aggregate(_, ops) => { for op in ops.iter_mut() { - for_operand(op, &mut f, &mut self.projection_store); + for_operand(op, &mut f); } } Rvalue::ThreadLocalRef(n) @@ -1145,9 +1162,7 @@ impl MirBody { | Rvalue::NullaryOp(n) => match *n {}, } } - StatementKind::FakeRead(p) | StatementKind::Deinit(p) => { - f(p, &mut self.projection_store) - } + StatementKind::FakeRead(p) | StatementKind::Deinit(p) => f(p), StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), @@ -1155,9 +1170,7 @@ impl MirBody { } match &mut block.terminator { Some(x) => match &mut x.kind { - TerminatorKind::SwitchInt { discr, .. } => { - for_operand(discr, &mut f, &mut self.projection_store) - } + TerminatorKind::SwitchInt { discr, .. } => for_operand(discr, &mut f), TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Goto { .. } @@ -1167,24 +1180,23 @@ impl MirBody { | TerminatorKind::Return | TerminatorKind::Unreachable => (), TerminatorKind::Drop { place, .. } => { - f(place, &mut self.projection_store); + f(place); } TerminatorKind::DropAndReplace { place, value, .. } => { - f(place, &mut self.projection_store); - for_operand(value, &mut f, &mut self.projection_store); + f(place); + for_operand(value, &mut f); } TerminatorKind::Call { func, args, destination, .. } => { - for_operand(func, &mut f, &mut self.projection_store); - args.iter_mut() - .for_each(|x| for_operand(x, &mut f, &mut self.projection_store)); - f(destination, &mut self.projection_store); + for_operand(func, &mut f); + args.iter_mut().for_each(|x| for_operand(x, &mut f)); + f(destination); } TerminatorKind::Assert { cond, .. } => { - for_operand(cond, &mut f, &mut self.projection_store); + for_operand(cond, &mut f); } TerminatorKind::Yield { value, resume_arg, .. } => { - for_operand(value, &mut f, &mut self.projection_store); - f(resume_arg, &mut self.projection_store); + for_operand(value, &mut f); + f(resume_arg); } }, None => (), @@ -1202,9 +1214,7 @@ impl MirBody { upvar_locals, param_locals, closures, - projection_store, } = self; - projection_store.shrink_to_fit(); basic_blocks.shrink_to_fit(); locals.shrink_to_fit(); binding_locals.shrink_to_fit(); diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs index bc158ac884..ff963fc121 100644 --- a/crates/hir-ty/src/mir/borrowck.rs +++ b/crates/hir-ty/src/mir/borrowck.rs @@ -195,11 +195,11 @@ fn moved_out_of_ref<'db>( ) -> Vec<MovedOutOfRef> { let db = infcx.interner.db; let mut result = vec![]; - let mut for_operand = |op: &Operand, span: MirSpan| match op.kind { + let mut for_operand = |op: &Operand, span: MirSpan| match &op.kind { OperandKind::Copy(p) | OperandKind::Move(p) => { let mut ty: Ty<'db> = body.locals[p.local].ty.as_ref(); let mut is_dereference_of_ref = false; - for proj in p.projection.lookup(&body.projection_store) { + for proj in p.projection.lookup() { if *proj == ProjectionElem::Deref && ty.as_reference().is_some() { is_dereference_of_ref = true; } @@ -290,10 +290,10 @@ fn partially_moved<'db>( ) -> Vec<PartiallyMoved> { let db = infcx.interner.db; let mut result = vec![]; - let mut for_operand = |op: &Operand, span: MirSpan| match op.kind { + let mut for_operand = |op: &Operand, span: MirSpan| match &op.kind { OperandKind::Copy(p) | OperandKind::Move(p) => { let mut ty: Ty<'db> = body.locals[p.local].ty.as_ref(); - for proj in p.projection.lookup(&body.projection_store) { + for proj in p.projection.lookup() { ty = proj.projected_ty(infcx, env, ty, body.owner.module(db).krate(db)); } if !infcx.type_is_copy_modulo_regions(env, ty) && !ty.references_non_lt_error() { @@ -430,7 +430,7 @@ fn place_case<'db>( let db = infcx.interner.db; let mut is_part_of = false; let mut ty = body.locals[lvalue.local].ty.as_ref(); - for proj in lvalue.projection.lookup(&body.projection_store).iter() { + for proj in lvalue.projection.lookup().iter() { match proj { ProjectionElem::Deref if ty.as_adt().is_none() => return ProjectionCase::Indirect, // It's indirect in case of reference and raw ProjectionElem::Deref // It's direct in case of `Box<T>` @@ -470,7 +470,7 @@ fn ever_initialized_map( for statement in &block.statements { match &statement.kind { StatementKind::Assign(p, _) => { - if p.projection.lookup(&body.projection_store).is_empty() && p.local == l { + if p.projection.is_empty() && p.local == l { is_ever_initialized = true; } } @@ -508,9 +508,7 @@ fn ever_initialized_map( | TerminatorKind::Return | TerminatorKind::Unreachable => (), TerminatorKind::Call { target, cleanup, destination, .. } => { - if destination.projection.lookup(&body.projection_store).is_empty() - && destination.local == l - { + if destination.projection.is_empty() && destination.local == l { is_ever_initialized = true; } target.iter().chain(cleanup).for_each(|&it| process(it, is_ever_initialized)); @@ -566,7 +564,7 @@ fn record_usage(local: LocalId, result: &mut ArenaMap<LocalId, MutabilityReason> } fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap<LocalId, MutabilityReason>) { - if let OperandKind::Copy(p) | OperandKind::Move(p) = arg.kind { + if let OperandKind::Copy(p) | OperandKind::Move(p) = &arg.kind { record_usage(p.local, result); } } @@ -674,7 +672,7 @@ fn mutability_of_locals<'db>( for arg in args.iter() { record_usage_for_operand(arg, &mut result); } - if destination.projection.lookup(&body.projection_store).is_empty() { + if destination.projection.is_empty() { if ever_init_map.get(destination.local).copied().unwrap_or_default() { push_mut_span(destination.local, terminator.span, &mut result); } else { diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 1ee18e09ba..78b70edeee 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -56,7 +56,7 @@ use crate::{ use super::{ AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError, MirSpan, - Operand, OperandKind, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind, + Operand, OperandKind, Place, PlaceElem, PlaceRef, ProjectionElem, Rvalue, StatementKind, TerminatorKind, UnOp, return_slot, }; @@ -567,26 +567,26 @@ impl std::fmt::Debug for MirEvalError { type Result<'db, T> = std::result::Result<T, MirEvalError>; #[derive(Debug, Default)] -struct DropFlags { - need_drop: FxHashSet<Place>, +struct DropFlags<'db> { + need_drop: FxHashSet<PlaceRef<'db>>, } -impl DropFlags { - fn add_place(&mut self, p: Place, store: &ProjectionStore) { - if p.iterate_over_parents(store).any(|it| self.need_drop.contains(&it)) { +impl<'db> DropFlags<'db> { + fn add_place(&mut self, p: PlaceRef<'db>) { + if p.iterate_over_parents().any(|it| self.need_drop.contains(&it)) { return; } - self.need_drop.retain(|it| !p.is_parent(it, store)); + self.need_drop.retain(|it| !p.is_parent(*it)); self.need_drop.insert(p); } - fn remove_place(&mut self, p: &Place, store: &ProjectionStore) -> bool { + fn remove_place(&mut self, p: PlaceRef<'db>) -> bool { // FIXME: replace parents with parts - if let Some(parent) = p.iterate_over_parents(store).find(|it| self.need_drop.contains(it)) { + if let Some(parent) = p.iterate_over_parents().find(|it| self.need_drop.contains(it)) { self.need_drop.remove(&parent); return true; } - self.need_drop.remove(p) + self.need_drop.remove(&p) } fn clear(&mut self) { @@ -598,7 +598,7 @@ impl DropFlags { struct Locals<'a> { ptr: ArenaMap<LocalId, Interval>, body: &'a MirBody, - drop_flags: DropFlags, + drop_flags: DropFlags<'a>, } pub struct MirOutput { @@ -757,9 +757,9 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { let mut addr = locals.ptr[p.local].addr; let mut ty: Ty<'db> = locals.body.locals[p.local].ty.as_ref(); let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized - for proj in p.projection.lookup(&locals.body.projection_store) { + for proj in p.projection.lookup() { let prev_ty = ty; - ty = self.projected_ty(ty, proj.clone()); + ty = self.projected_ty(ty, *proj); match proj { ProjectionElem::Deref => { metadata = if self.size_align_of(ty, locals)?.is_none() { @@ -955,7 +955,7 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { let addr = self.place_addr(l, locals)?; let result = self.eval_rvalue(r, locals)?; self.copy_from_interval_or_owned(addr, result)?; - locals.drop_flags.add_place(*l, &locals.body.projection_store); + locals.drop_flags.add_place(l.as_ref()); } StatementKind::Deinit(_) => not_supported!("de-init statement"), StatementKind::StorageLive(_) @@ -1008,9 +1008,7 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { )?, it => not_supported!("unknown function type {it:?}"), }; - locals - .drop_flags - .add_place(*destination, &locals.body.projection_store); + locals.drop_flags.add_place(destination.as_ref()); if let Some(stack_frame) = stack_frame { self.code_stack.push(my_stack_frame); current_block_idx = stack_frame.locals.body.start_block; @@ -1091,7 +1089,7 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { ) -> Result<'db, ()> { let mut remain_args = body.param_locals.len(); for ((l, interval), value) in locals.ptr.iter().skip(1).zip(args) { - locals.drop_flags.add_place(l.into(), &locals.body.projection_store); + locals.drop_flags.add_place(l.into()); match value { IntervalOrOwned::Owned(value) => interval.write_from_bytes(self, &value)?, IntervalOrOwned::Borrowed(value) => interval.write_from_interval(self, value)?, @@ -1915,7 +1913,7 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { fn eval_operand(&mut self, it: &Operand, locals: &mut Locals<'a>) -> Result<'db, Interval> { Ok(match &it.kind { OperandKind::Copy(p) | OperandKind::Move(p) => { - locals.drop_flags.remove_place(p, &locals.body.projection_store); + locals.drop_flags.remove_place(p.as_ref()); self.eval_place(p, locals)? } OperandKind::Static(st) => { @@ -3036,7 +3034,7 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { span: MirSpan, ) -> Result<'db, ()> { let (addr, ty, metadata) = self.place_addr_and_ty_and_metadata(place, locals)?; - if !locals.drop_flags.remove_place(place, &locals.body.projection_store) { + if !locals.drop_flags.remove_place(place.as_ref()) { return Ok(()); } let metadata = match metadata { diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 394cac8065..4e52c1f7c3 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -45,9 +45,9 @@ use crate::{ mir::{ AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, BorrowKind, CastKind, Either, Expr, FieldId, GenericArgs, Idx, InferenceResult, Local, LocalId, MemoryMap, MirBody, MirSpan, - Mutability, Operand, Place, PlaceElem, PointerCast, ProjectionElem, ProjectionStore, - RawIdx, Rvalue, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, - TupleFieldId, Ty, UnOp, VariantId, return_slot, + Mutability, Operand, Place, PlaceElem, PointerCast, Projection, ProjectionElem, RawIdx, + Rvalue, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, TupleFieldId, + Ty, UnOp, VariantId, return_slot, }, next_solver::{ Const, DbInterner, ParamConst, ParamEnv, Region, StoredGenericArgs, StoredTy, TyKind, @@ -57,7 +57,7 @@ use crate::{ }, }; -use super::OperandKind; +use super::{OperandKind, PlaceRef}; mod as_place; mod pattern_matching; @@ -303,7 +303,6 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { let locals = Arena::new(); let binding_locals: ArenaMap<BindingId, LocalId> = ArenaMap::new(); let mir = MirBody { - projection_store: ProjectionStore::default(), basic_blocks, locals, start_block, @@ -371,13 +370,16 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { let Some((p, current)) = self.lower_expr_as_place(current, expr_id, true)? else { return Ok(None); }; - Ok(Some((Operand { kind: OperandKind::Copy(p), span: Some(expr_id.into()) }, current))) + Ok(Some(( + Operand { kind: OperandKind::Copy(p.store()), span: Some(expr_id.into()) }, + current, + ))) } fn lower_expr_to_place_with_adjust( &mut self, expr_id: ExprId, - place: Place, + place: PlaceRef<'db>, current: BasicBlockId, adjustments: &[Adjustment], ) -> Result<'db, Option<BasicBlockId>> { @@ -396,7 +398,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.push_assignment( current, place, - Operand { kind: OperandKind::Copy(p), span: None }.into(), + Operand { kind: OperandKind::Copy(p.store()), span: None }.into(), expr_id.into(), ); Ok(Some(current)) @@ -422,7 +424,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { place, Rvalue::Cast( CastKind::PointerCoercion(*cast), - Operand { kind: OperandKind::Copy(p), span: None }, + Operand { kind: OperandKind::Copy(p.store()), span: None }, last.target.clone(), ), expr_id.into(), @@ -437,7 +439,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_expr_to_place_with_borrow_adjust( &mut self, expr_id: ExprId, - place: Place, + place: PlaceRef<'db>, current: BasicBlockId, rest: &[Adjustment], m: Mutability, @@ -448,14 +450,14 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { return Ok(None); }; let bk = BorrowKind::from_rustc_mutability(m); - self.push_assignment(current, place, Rvalue::Ref(bk, p), expr_id.into()); + self.push_assignment(current, place, Rvalue::Ref(bk, p.store()), expr_id.into()); Ok(Some(current)) } fn lower_expr_to_place( &mut self, expr_id: ExprId, - place: Place, + place: PlaceRef<'db>, prev_block: BasicBlockId, ) -> Result<'db, Option<BasicBlockId>> { if let Some(adjustments) = self.infer.expr_adjustments.get(&expr_id) { @@ -467,7 +469,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_expr_to_place_without_adjust( &mut self, expr_id: ExprId, - place: Place, + place: PlaceRef<'db>, mut current: BasicBlockId, ) -> Result<'db, Option<BasicBlockId>> { match &self.store[expr_id] { @@ -535,7 +537,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.push_assignment( current, place, - Operand { kind: OperandKind::Copy(temp), span: None }.into(), + Operand { kind: OperandKind::Copy(temp.store()), span: None }.into(), expr_id.into(), ); Ok(Some(current)) @@ -831,7 +833,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { .as_ref() .ok_or(MirLowerError::BreakWithoutLoop)?, }; - let Some(c) = self.lower_expr_to_place(expr, loop_data.place, current)? else { + let Some(c) = + self.lower_expr_to_place(expr, loop_data.place.as_ref(), current)? + else { return Ok(None); }; current = c; @@ -921,16 +925,18 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { .map(|(i, it)| match it { Some(it) => it, None => { - let p = sp.project( - ProjectionElem::Field(Either::Left(FieldId { + let p = sp.project(ProjectionElem::Field( + Either::Left(FieldId { parent: variant_id, local_id: LocalFieldId::from_raw(RawIdx::from( i as u32, )), - })), - &mut self.result.projection_store, - ); - Operand { kind: OperandKind::Copy(p), span: None } + }), + )); + Operand { + kind: OperandKind::Copy(p.store()), + span: None, + } } }) .collect(), @@ -948,13 +954,10 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { }; let local_id = variant_fields.field(name).ok_or(MirLowerError::UnresolvedField)?; - let place = place.project( - PlaceElem::Field(Either::Left(FieldId { - parent: union_id.into(), - local_id, - })), - &mut self.result.projection_store, - ); + let place = place.project(PlaceElem::Field(Either::Left(FieldId { + parent: union_id.into(), + local_id, + }))); self.lower_expr_to_place(*expr, place, current) } } @@ -1001,7 +1004,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { return Ok(None); }; let bk = BorrowKind::from_hir_mutability(*mutability); - self.push_assignment(current, place, Rvalue::Ref(bk, p), expr_id.into()); + self.push_assignment(current, place, Rvalue::Ref(bk, p.store()), expr_id.into()); Ok(Some(current)) } Expr::Box { expr } => { @@ -1016,7 +1019,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { else { return Ok(None); }; - let p = place.project(ProjectionElem::Deref, &mut self.result.projection_store); + let p = place.project(ProjectionElem::Deref); self.push_assignment(current, p, operand.into(), expr_id.into()); Ok(Some(current)) } @@ -1031,7 +1034,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.push_assignment( current, place, - Operand { kind: OperandKind::Copy(p), span: None }.into(), + Operand { kind: OperandKind::Copy(p.store()), span: None }.into(), expr_id.into(), ); Ok(Some(current)) @@ -1124,7 +1127,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { }; let r_value = Rvalue::CheckedBinaryOp( op.into(), - Operand { kind: OperandKind::Copy(lhs_place), span: None }, + Operand { kind: OperandKind::Copy(lhs_place.store()), span: None }, rhs_op, ); self.push_assignment(current, lhs_place, r_value, expr_id.into()); @@ -1273,16 +1276,16 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { }; Ok(Place { local: this.binding_local(local)?, - projection: this - .result - .projection_store - .intern(convert_closure_capture_projections(self.db, place).collect()), + projection: Projection::new_from_iter(convert_closure_capture_projections( + self.db, place, + )) + .store(), }) }; for (place, _, sources) in &closure_data.fake_reads { let p = convert_place(self, place)?; - self.push_fake_read(current, p, span(sources)); + self.push_fake_read(current, p.as_ref(), span(sources)); } let captures = closure_data.min_captures.values().flatten(); @@ -1294,14 +1297,15 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { let tmp_ty = capture.captured_ty(self.db); // FIXME: Handle more than one span. let capture_span = span(&capture.info.sources); - let tmp: Place = self.temp(tmp_ty, current, capture_span)?.into(); + let tmp = self.temp(tmp_ty, current, capture_span)?.into(); self.push_assignment( current, tmp, Rvalue::Ref(BorrowKind::from_hir(bk), p), capture_span, ); - operands.push(Operand { kind: OperandKind::Move(tmp), span: None }); + operands + .push(Operand { kind: OperandKind::Move(tmp.store()), span: None }); } UpvarCapture::ByValue => { operands.push(Operand { kind: OperandKind::Move(p), span: None }) @@ -1396,24 +1400,24 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { } } - fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<'db, ()> { + fn push_field_projection( + &mut self, + place: &mut PlaceRef<'db>, + expr_id: ExprId, + ) -> Result<'db, ()> { if let Expr::Field { expr, name } = &self.store[expr_id] { if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind() { let index = name.as_tuple_index().ok_or(MirLowerError::TypeError("named field on tuple"))? as u32; - *place = place.project( - ProjectionElem::Field(Either::Right(TupleFieldId { - tuple: TupleId(!0), // dummy as its unused - index, - })), - &mut self.result.projection_store, - ) + *place = place.project(ProjectionElem::Field(Either::Right(TupleFieldId { + tuple: TupleId(!0), // dummy as its unused + index, + }))) } else { let field = self.infer.field_resolution(expr_id).ok_or(MirLowerError::UnresolvedField)?; - *place = - place.project(ProjectionElem::Field(field), &mut self.result.projection_store); + *place = place.project(ProjectionElem::Field(field)); } } else { not_supported!("") @@ -1528,7 +1532,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { &mut self, const_id: GeneralConstId, prev_block: BasicBlockId, - place: Place, + place: PlaceRef<'db>, subst: GenericArgs<'db>, span: MirSpan, ) -> Result<'db, ()> { @@ -1561,7 +1565,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn write_bytes_to_place( &mut self, prev_block: BasicBlockId, - place: Place, + place: PlaceRef<'db>, cv: Box<[u8]>, ty: Ty<'db>, span: MirSpan, @@ -1574,7 +1578,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { &mut self, variant_id: EnumVariantId, prev_block: BasicBlockId, - place: Place, + place: PlaceRef<'db>, ty: Ty<'db>, fields: Box<[Operand]>, span: MirSpan, @@ -1596,7 +1600,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { &mut self, func: Operand, args: impl Iterator<Item = ExprId>, - place: Place, + place: PlaceRef<'db>, mut current: BasicBlockId, is_uninhabited: bool, span: MirSpan, @@ -1621,7 +1625,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { &mut self, func: Operand, args: Box<[Operand]>, - place: Place, + place: PlaceRef<'db>, current: BasicBlockId, is_uninhabited: bool, span: MirSpan, @@ -1632,7 +1636,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { TerminatorKind::Call { func, args, - destination: place, + destination: place.store(), target: b, cleanup: None, from_hir_call: true, @@ -1672,31 +1676,31 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.result.basic_blocks[block].statements.push(statement); } - fn push_fake_read(&mut self, block: BasicBlockId, p: Place, span: MirSpan) { - self.push_statement(block, StatementKind::FakeRead(p).with_span(span)); + fn push_fake_read(&mut self, block: BasicBlockId, p: PlaceRef<'db>, span: MirSpan) { + self.push_statement(block, StatementKind::FakeRead(p.store()).with_span(span)); } fn push_assignment( &mut self, block: BasicBlockId, - place: Place, + place: PlaceRef<'db>, rvalue: Rvalue, span: MirSpan, ) { - self.push_statement(block, StatementKind::Assign(place, rvalue).with_span(span)); + self.push_statement(block, StatementKind::Assign(place.store(), rvalue).with_span(span)); } - fn discr_temp_place(&mut self, current: BasicBlockId) -> Place { + fn discr_temp_place(&mut self, current: BasicBlockId) -> PlaceRef<'db> { match &self.discr_temp { - Some(it) => *it, + Some(it) => it.as_ref(), None => { // FIXME: rustc's ty is dependent on the adt type, maybe we need to do that as well let discr_ty = Ty::new_int(self.interner(), rustc_type_ir::IntTy::I128); - let tmp: Place = self + let tmp: PlaceRef<'_> = self .temp(discr_ty, current, MirSpan::Unknown) .expect("discr_ty is never unsized") .into(); - self.discr_temp = Some(tmp); + self.discr_temp = Some(tmp.store()); tmp } } @@ -1705,7 +1709,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_loop( &mut self, prev_block: BasicBlockId, - place: Place, + place: PlaceRef<'db>, label: Option<LabelId>, span: MirSpan, f: impl FnOnce(&mut MirLowerCtx<'_, 'db>, BasicBlockId) -> Result<'db, ()>, @@ -1714,7 +1718,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { let prev = self.current_loop_blocks.replace(LoopBlocks { begin, end: None, - place, + place: place.store(), drop_scope_index: self.drop_scopes.len(), }); let prev_label = if let Some(label) = label { @@ -1816,7 +1820,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { statements: &[hir_def::hir::Statement], mut current: BasicBlockId, tail: Option<ExprId>, - place: Place, + place: PlaceRef<'db>, span: MirSpan, ) -> Result<'db, Option<Idx<BasicBlock>>> { let scope = self.push_drop_scope(); @@ -2068,7 +2072,11 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { let prev = std::mem::replace(current, self.new_basic_block()); self.set_terminator( prev, - TerminatorKind::Drop { place: l.into(), target: *current, unwind: None }, + TerminatorKind::Drop { + place: PlaceRef::from(l).store(), + target: *current, + unwind: None, + }, span, ); } @@ -2202,15 +2210,18 @@ pub fn mir_body_for_closure_query<'db>( projections.push(ProjectionElem::ClosureField(capture_idx)); let capture_param_place = Place { local: closure_local, - projection: ctx.result.projection_store.intern(projections.into_boxed_slice()), - }; - let capture_local_place = Place { - local: capture_local, - projection: ctx.result.projection_store.intern(Box::new([])), + projection: Projection::new_from_slice(&projections).store(), }; + let capture_local_place = + Place { local: capture_local, projection: Projection::new_from_slice(&[]).store() }; let capture_local_rvalue = Rvalue::Use(Operand { kind: OperandKind::Move(capture_param_place), span: None }); - ctx.push_assignment(current, capture_local_place, capture_local_rvalue, MirSpan::Unknown); + ctx.push_assignment( + current, + capture_local_place.as_ref(), + capture_local_rvalue, + MirSpan::Unknown, + ); let local = capture.captured_local(); let local = ctx.binding_local(local)?; @@ -2230,8 +2241,8 @@ pub fn mir_body_for_closure_query<'db>( } let mut err = None; - ctx.result.walk_places(|mir_place, store| { - let mir_projections = mir_place.projection.lookup(store); + ctx.result.walk_places(|mir_place| { + let mir_projections = mir_place.projection.lookup(); if let Some(hir_places) = upvar_map.get(&mir_place.local) { let projections = hir_places.iter().find_map(|hir_place| { let iter = mir_projections @@ -2267,18 +2278,17 @@ pub fn mir_body_for_closure_query<'db>( match projections { Some((skip_projections_up_to, (hir_place, upvar_local))) => { mir_place.local = *upvar_local; - let mut result_projections = Vec::with_capacity( - usize::from(hir_place.is_by_ref()) - + (mir_projections.len() - skip_projections_up_to), - ); - if hir_place.is_by_ref() { - result_projections.push(ProjectionElem::Deref); - } - result_projections - .extend(mir_projections[skip_projections_up_to..].iter().cloned()); - mir_place.projection = store.intern(result_projections.into()); + let maybe_deref: &[PlaceElem] = + if hir_place.is_by_ref() { &[ProjectionElem::Deref] } else { &[] }; + mir_place.projection = Projection::new_from_iter( + maybe_deref + .iter() + .copied() + .chain(mir_projections[skip_projections_up_to..].iter().copied()), + ) + .store(); } - None => err = Some(*mir_place), + None => err = Some(mir_place.clone()), } } }); diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs index 2ed7aedecf..bb00a79480 100644 --- a/crates/hir-ty/src/mir/lower/as_place.rs +++ b/crates/hir-ty/src/mir/lower/as_place.rs @@ -14,15 +14,14 @@ impl<'db> MirLowerCtx<'_, 'db> { &mut self, expr_id: ExprId, prev_block: BasicBlockId, - ) -> Result<'db, Option<(Place, BasicBlockId)>> { + ) -> Result<'db, Option<(PlaceRef<'db>, BasicBlockId)>> { let ty = self.expr_ty_without_adjust(expr_id); - let place = self.temp(ty, prev_block, expr_id.into())?; - let Some(current) = - self.lower_expr_to_place_without_adjust(expr_id, place.into(), prev_block)? + let place = self.temp(ty, prev_block, expr_id.into())?.into(); + let Some(current) = self.lower_expr_to_place_without_adjust(expr_id, place, prev_block)? else { return Ok(None); }; - Ok(Some((place.into(), current))) + Ok(Some((place, current))) } fn lower_expr_to_some_place_with_adjust( @@ -30,18 +29,18 @@ impl<'db> MirLowerCtx<'_, 'db> { expr_id: ExprId, prev_block: BasicBlockId, adjustments: &[Adjustment], - ) -> Result<'db, Option<(Place, BasicBlockId)>> { + ) -> Result<'db, Option<(PlaceRef<'db>, BasicBlockId)>> { let ty = adjustments .last() .map(|it| it.target.as_ref()) .unwrap_or_else(|| self.expr_ty_without_adjust(expr_id)); - let place = self.temp(ty, prev_block, expr_id.into())?; + let place = self.temp(ty, prev_block, expr_id.into())?.into(); let Some(current) = - self.lower_expr_to_place_with_adjust(expr_id, place.into(), prev_block, adjustments)? + self.lower_expr_to_place_with_adjust(expr_id, place, prev_block, adjustments)? else { return Ok(None); }; - Ok(Some((place.into(), current))) + Ok(Some((place, current))) } pub(super) fn lower_expr_as_place_with_adjust( @@ -50,7 +49,7 @@ impl<'db> MirLowerCtx<'_, 'db> { expr_id: ExprId, upgrade_rvalue: bool, adjustments: &[Adjustment], - ) -> Result<'db, Option<(Place, BasicBlockId)>> { + ) -> Result<'db, Option<(PlaceRef<'db>, BasicBlockId)>> { let try_rvalue = |this: &mut MirLowerCtx<'_, 'db>| { if !upgrade_rvalue { return Err(MirLowerError::MutatingRvalue); @@ -69,7 +68,7 @@ impl<'db> MirLowerCtx<'_, 'db> { else { return Ok(None); }; - it.0 = it.0.project(ProjectionElem::Deref, &mut self.result.projection_store); + it.0 = it.0.project(ProjectionElem::Deref); Ok(Some(it)) } Adjust::Deref(Some(od)) => { @@ -108,7 +107,7 @@ impl<'db> MirLowerCtx<'_, 'db> { current: BasicBlockId, expr_id: ExprId, upgrade_rvalue: bool, - ) -> Result<'db, Option<(Place, BasicBlockId)>> { + ) -> Result<'db, Option<(PlaceRef<'db>, BasicBlockId)>> { match self.infer.expr_adjustments.get(&expr_id) { Some(a) => self.lower_expr_as_place_with_adjust(current, expr_id, upgrade_rvalue, a), None => self.lower_expr_as_place_without_adjust(current, expr_id, upgrade_rvalue), @@ -120,7 +119,7 @@ impl<'db> MirLowerCtx<'_, 'db> { current: BasicBlockId, expr_id: ExprId, upgrade_rvalue: bool, - ) -> Result<'db, Option<(Place, BasicBlockId)>> { + ) -> Result<'db, Option<(PlaceRef<'db>, BasicBlockId)>> { let try_rvalue = |this: &mut MirLowerCtx<'_, 'db>| { if !upgrade_rvalue { return Err(MirLowerError::MutatingRvalue); @@ -149,17 +148,14 @@ impl<'db> MirLowerCtx<'_, 'db> { ty, Mutability::Not, ); - let temp: Place = self.temp(ref_ty, current, expr_id.into())?.into(); + let temp = self.temp(ref_ty, current, expr_id.into())?.into(); self.push_assignment( current, temp, Operand { kind: OperandKind::Static(s), span: None }.into(), expr_id.into(), ); - Ok(Some(( - temp.project(ProjectionElem::Deref, &mut self.result.projection_store), - current, - ))) + Ok(Some((temp.project(ProjectionElem::Deref), current))) } _ => try_rvalue(self), } @@ -193,7 +189,7 @@ impl<'db> MirLowerCtx<'_, 'db> { let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? else { return Ok(None); }; - r = r.project(ProjectionElem::Deref, &mut self.result.projection_store); + r = r.project(ProjectionElem::Deref); Ok(Some((r, current))) } Expr::UnaryOp { .. } => try_rvalue(self), @@ -256,8 +252,7 @@ impl<'db> MirLowerCtx<'_, 'db> { else { return Ok(None); }; - p_base = p_base - .project(ProjectionElem::Index(l_index), &mut self.result.projection_store); + p_base = p_base.project(ProjectionElem::Index(l_index)); Ok(Some((p_base, current))) } _ => try_rvalue(self), @@ -267,20 +262,20 @@ impl<'db> MirLowerCtx<'_, 'db> { fn lower_overloaded_index( &mut self, current: BasicBlockId, - place: Place, + place: PlaceRef<'db>, base_ty: Ty<'db>, result_ty: Ty<'db>, index_operand: Operand, span: MirSpan, index_fn: (FunctionId, GenericArgs<'db>), - ) -> Result<'db, Option<(Place, BasicBlockId)>> { + ) -> Result<'db, Option<(PlaceRef<'db>, BasicBlockId)>> { let mutability = match base_ty.as_reference() { Some((_, _, mutability)) => mutability, None => Mutability::Not, }; let result_ref = Ty::new_ref(self.interner(), Region::error(self.interner()), result_ty, mutability); - let mut result: Place = self.temp(result_ref, current, span)?.into(); + let mut result = self.temp(result_ref, current, span)?.into(); let index_fn_op = Operand::const_zst(Ty::new_fn_def( self.interner(), CallableDefId::FunctionId(index_fn.0).into(), @@ -288,7 +283,10 @@ impl<'db> MirLowerCtx<'_, 'db> { )); let Some(current) = self.lower_call( index_fn_op, - Box::new([Operand { kind: OperandKind::Copy(place), span: None }, index_operand]), + Box::new([ + Operand { kind: OperandKind::Copy(place.store()), span: None }, + index_operand, + ]), result, current, false, @@ -297,19 +295,19 @@ impl<'db> MirLowerCtx<'_, 'db> { else { return Ok(None); }; - result = result.project(ProjectionElem::Deref, &mut self.result.projection_store); + result = result.project(ProjectionElem::Deref); Ok(Some((result, current))) } fn lower_overloaded_deref( &mut self, current: BasicBlockId, - place: Place, + place: PlaceRef<'db>, source_ty: Ty<'db>, target_ty: Ty<'db>, span: MirSpan, mutability: bool, - ) -> Result<'db, Option<(Place, BasicBlockId)>> { + ) -> Result<'db, Option<(PlaceRef<'db>, BasicBlockId)>> { let lang_items = self.lang_items(); let (mutability, deref_fn, borrow_kind) = if !mutability { (Mutability::Not, lang_items.Deref_deref, BorrowKind::Shared) @@ -323,18 +321,18 @@ impl<'db> MirLowerCtx<'_, 'db> { let error_region = Region::error(self.interner()); let ty_ref = Ty::new_ref(self.interner(), error_region, source_ty, mutability); let target_ty_ref = Ty::new_ref(self.interner(), error_region, target_ty, mutability); - let ref_place: Place = self.temp(ty_ref, current, span)?.into(); - self.push_assignment(current, ref_place, Rvalue::Ref(borrow_kind, place), span); + let ref_place = self.temp(ty_ref, current, span)?.into(); + self.push_assignment(current, ref_place, Rvalue::Ref(borrow_kind, place.store()), span); let deref_fn = deref_fn.ok_or(MirLowerError::LangItemNotFound)?; let deref_fn_op = Operand::const_zst(Ty::new_fn_def( self.interner(), CallableDefId::FunctionId(deref_fn).into(), GenericArgs::new_from_slice(&[source_ty.into()]), )); - let mut result: Place = self.temp(target_ty_ref, current, span)?.into(); + let mut result = self.temp(target_ty_ref, current, span)?.into(); let Some(current) = self.lower_call( deref_fn_op, - Box::new([Operand { kind: OperandKind::Copy(ref_place), span: None }]), + Box::new([Operand { kind: OperandKind::Copy(ref_place.store()), span: None }]), result, current, false, @@ -343,7 +341,7 @@ impl<'db> MirLowerCtx<'_, 'db> { else { return Ok(None); }; - result = result.project(ProjectionElem::Deref, &mut self.result.projection_store); + result = result.project(ProjectionElem::Deref); Ok(Some((result, current))) } } diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 2cb2143229..c306b6ca15 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -6,10 +6,10 @@ use rustc_type_ir::inherent::{IntoKind, Ty as _}; use crate::{ BindingMode, ByRef, mir::{ - LocalId, MutBorrowKind, Operand, OperandKind, + LocalId, MutBorrowKind, Operand, OperandKind, PlaceRef, Projection, lower::{ BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, MemoryMap, - MirLowerCtx, MirLowerError, MirSpan, Pat, PatId, Place, PlaceElem, ProjectionElem, + MirLowerCtx, MirLowerError, MirSpan, Pat, PatId, PlaceElem, ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, Ty, TyKind, ValueNs, VariantId, }, @@ -65,7 +65,7 @@ impl<'db> MirLowerCtx<'_, 'db> { &mut self, current: BasicBlockId, current_else: Option<BasicBlockId>, - cond_place: Place, + cond_place: PlaceRef<'db>, pattern: PatId, ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> { let (current, current_else) = self.pattern_match_inner( @@ -88,7 +88,7 @@ impl<'db> MirLowerCtx<'_, 'db> { pub(super) fn pattern_match_assignment( &mut self, current: BasicBlockId, - value: Place, + value: PlaceRef<'db>, pattern: PatId, ) -> Result<'db, BasicBlockId> { let (current, _) = @@ -116,20 +116,18 @@ impl<'db> MirLowerCtx<'_, 'db> { &mut self, mut current: BasicBlockId, mut current_else: Option<BasicBlockId>, - mut cond_place: Place, + mut cond_place: PlaceRef<'db>, pattern: PatId, mode: MatchingMode, ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> { let cnt = self.infer.pat_adjustments.get(&pattern).map(|x| x.len()).unwrap_or_default(); - cond_place.projection = self.result.projection_store.intern( + cond_place.projection = Projection::new_from_iter( cond_place .projection - .lookup(&self.result.projection_store) + .as_slice() .iter() .cloned() - .chain((0..cnt).map(|_| ProjectionElem::Deref)) - .collect::<Vec<_>>() - .into(), + .chain((0..cnt).map(|_| ProjectionElem::Deref)), ); Ok(match &self.store[pattern] { Pat::Missing | Pat::Rest | Pat::NotNull => { @@ -215,7 +213,7 @@ impl<'db> MirLowerCtx<'_, 'db> { self.lower_literal_or_const_to_operand(self.infer.pat_ty(pattern), l)?; let else_target = *current_else.get_or_insert_with(|| self.new_basic_block()); let next = self.new_basic_block(); - let discr: Place = + let discr = self.temp(Ty::new_bool(self.interner()), current, pattern.into())?.into(); self.push_assignment( current, @@ -223,11 +221,11 @@ impl<'db> MirLowerCtx<'_, 'db> { Rvalue::CheckedBinaryOp( binop, lv, - Operand { kind: OperandKind::Copy(cond_place), span: None }, + Operand { kind: OperandKind::Copy(cond_place.store()), span: None }, ), pattern.into(), ); - let discr = Operand { kind: OperandKind::Copy(discr), span: None }; + let discr = Operand { kind: OperandKind::Copy(discr.store()), span: None }; self.set_terminator( current, TerminatorKind::SwitchInt { @@ -263,13 +261,13 @@ impl<'db> MirLowerCtx<'_, 'db> { // emit runtime length check for slice if let TyKind::Slice(_) = pat_ty.kind() { let pattern_len = prefix.len() + suffix.len(); - let place_len: Place = self + let place_len = self .temp(Ty::new_usize(self.interner()), current, pattern.into())? .into(); self.push_assignment( current, place_len, - Rvalue::Len(cond_place), + Rvalue::Len(cond_place.store()), pattern.into(), ); let else_target = @@ -280,7 +278,7 @@ impl<'db> MirLowerCtx<'_, 'db> { current, TerminatorKind::SwitchInt { discr: Operand { - kind: OperandKind::Copy(place_len), + kind: OperandKind::Copy(place_len.store()), span: None, }, targets: SwitchTargets::static_if( @@ -297,7 +295,7 @@ impl<'db> MirLowerCtx<'_, 'db> { MemoryMap::default(), Ty::new_usize(self.interner()), ); - let discr: Place = self + let discr = self .temp(Ty::new_bool(self.interner()), current, pattern.into())? .into(); self.push_assignment( @@ -306,11 +304,15 @@ impl<'db> MirLowerCtx<'_, 'db> { Rvalue::CheckedBinaryOp( BinOp::Le, c, - Operand { kind: OperandKind::Copy(place_len), span: None }, + Operand { + kind: OperandKind::Copy(place_len.store()), + span: None, + }, ), pattern.into(), ); - let discr = Operand { kind: OperandKind::Copy(discr), span: None }; + let discr = + Operand { kind: OperandKind::Copy(discr.store()), span: None }; self.set_terminator( current, TerminatorKind::SwitchInt { @@ -324,10 +326,10 @@ impl<'db> MirLowerCtx<'_, 'db> { } } for (i, &pat) in prefix.iter().enumerate() { - let next_place = cond_place.project( - ProjectionElem::ConstantIndex { offset: i as u64, from_end: false }, - &mut self.result.projection_store, - ); + let next_place = cond_place.project(ProjectionElem::ConstantIndex { + offset: i as u64, + from_end: false, + }); (current, current_else) = self.pattern_match_inner(current, current_else, next_place, pat, mode)?; } @@ -335,13 +337,10 @@ impl<'db> MirLowerCtx<'_, 'db> { && mode != MatchingMode::Check && let Pat::Bind { id, subpat: _ } = self.store[slice] { - let next_place = cond_place.project( - ProjectionElem::Subslice { - from: prefix.len() as u64, - to: suffix.len() as u64, - }, - &mut self.result.projection_store, - ); + let next_place = cond_place.project(ProjectionElem::Subslice { + from: prefix.len() as u64, + to: suffix.len() as u64, + }); let mode = self.infer.binding_modes[slice]; (current, current_else) = self.pattern_match_binding( id, @@ -353,10 +352,10 @@ impl<'db> MirLowerCtx<'_, 'db> { )?; } for (i, &pat) in suffix.iter().enumerate() { - let next_place = cond_place.project( - ProjectionElem::ConstantIndex { offset: i as u64, from_end: true }, - &mut self.result.projection_store, - ); + let next_place = cond_place.project(ProjectionElem::ConstantIndex { + offset: i as u64, + from_end: true, + }); (current, current_else) = self.pattern_match_inner(current, current_else, next_place, pat, mode)?; } @@ -420,19 +419,19 @@ impl<'db> MirLowerCtx<'_, 'db> { } not_supported!("path in pattern position that is not const or variant") }; - let tmp: Place = + let tmp = self.temp(self.infer.pat_ty(pattern), current, pattern.into())?.into(); let span = pattern.into(); self.lower_const(c.into(), current, tmp, subst, span)?; - let tmp2: Place = + let tmp2 = self.temp(Ty::new_bool(self.interner()), current, pattern.into())?.into(); self.push_assignment( current, tmp2, Rvalue::CheckedBinaryOp( BinOp::Eq, - Operand { kind: OperandKind::Copy(tmp), span: None }, - Operand { kind: OperandKind::Copy(cond_place), span: None }, + Operand { kind: OperandKind::Copy(tmp.store()), span: None }, + Operand { kind: OperandKind::Copy(cond_place.store()), span: None }, ), span, ); @@ -441,7 +440,7 @@ impl<'db> MirLowerCtx<'_, 'db> { self.set_terminator( current, TerminatorKind::SwitchInt { - discr: Operand { kind: OperandKind::Copy(tmp2), span: None }, + discr: Operand { kind: OperandKind::Copy(tmp2.store()), span: None }, targets: SwitchTargets::static_if(1, next, else_target), }, span, @@ -494,8 +493,7 @@ impl<'db> MirLowerCtx<'_, 'db> { )? } Pat::Ref { pat, mutability: _ } => { - let cond_place = - cond_place.project(ProjectionElem::Deref, &mut self.result.projection_store); + let cond_place = cond_place.project(ProjectionElem::Deref); self.pattern_match_inner(current, current_else, cond_place, *pat, mode)? } &Pat::Expr(expr) => { @@ -510,7 +508,7 @@ impl<'db> MirLowerCtx<'_, 'db> { self.push_assignment( current, lhs_place, - Operand { kind: OperandKind::Copy(cond_place), span: None }.into(), + Operand { kind: OperandKind::Copy(cond_place.store()), span: None }.into(), expr.into(), ); (current, current_else) @@ -525,7 +523,7 @@ impl<'db> MirLowerCtx<'_, 'db> { &mut self, id: BindingId, mode: BindingMode, - cond_place: Place, + cond_place: PlaceRef<'db>, span: MirSpan, current: BasicBlockId, current_else: Option<BasicBlockId>, @@ -541,7 +539,7 @@ impl<'db> MirLowerCtx<'_, 'db> { current: BasicBlockId, target_place: LocalId, mode: BindingMode, - cond_place: Place, + cond_place: PlaceRef<'db>, span: MirSpan, ) { self.push_assignment( @@ -549,14 +547,15 @@ impl<'db> MirLowerCtx<'_, 'db> { target_place.into(), match mode { BindingMode(ByRef::No, _) => { - Operand { kind: OperandKind::Copy(cond_place), span: None }.into() + Operand { kind: OperandKind::Copy(cond_place.store()), span: None }.into() } BindingMode(ByRef::Yes(rustc_ast_ir::Mutability::Not), _) => { - Rvalue::Ref(BorrowKind::Shared, cond_place) - } - BindingMode(ByRef::Yes(rustc_ast_ir::Mutability::Mut), _) => { - Rvalue::Ref(BorrowKind::Mut { kind: MutBorrowKind::Default }, cond_place) + Rvalue::Ref(BorrowKind::Shared, cond_place.store()) } + BindingMode(ByRef::Yes(rustc_ast_ir::Mutability::Mut), _) => Rvalue::Ref( + BorrowKind::Mut { kind: MutBorrowKind::Default }, + cond_place.store(), + ), }, span, ); @@ -567,24 +566,23 @@ impl<'db> MirLowerCtx<'_, 'db> { current_else: Option<BasicBlockId>, current: BasicBlockId, c: Operand, - cond_place: Place, + cond_place: PlaceRef<'db>, pattern: Idx<Pat>, ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> { let then_target = self.new_basic_block(); let else_target = current_else.unwrap_or_else(|| self.new_basic_block()); - let discr: Place = - self.temp(Ty::new_bool(self.interner()), current, pattern.into())?.into(); + let discr = self.temp(Ty::new_bool(self.interner()), current, pattern.into())?.into(); self.push_assignment( current, discr, Rvalue::CheckedBinaryOp( BinOp::Eq, c, - Operand { kind: OperandKind::Copy(cond_place), span: None }, + Operand { kind: OperandKind::Copy(cond_place.store()), span: None }, ), pattern.into(), ); - let discr = Operand { kind: OperandKind::Copy(discr), span: None }; + let discr = Operand { kind: OperandKind::Copy(discr.store()), span: None }; self.set_terminator( current, TerminatorKind::SwitchInt { @@ -598,7 +596,7 @@ impl<'db> MirLowerCtx<'_, 'db> { fn pattern_matching_variant( &mut self, - cond_place: Place, + cond_place: PlaceRef<'db>, variant: VariantId, mut current: BasicBlockId, span: MirSpan, @@ -611,13 +609,18 @@ impl<'db> MirLowerCtx<'_, 'db> { if mode == MatchingMode::Check { let e = self.const_eval_discriminant(v)? as u128; let tmp = self.discr_temp_place(current); - self.push_assignment(current, tmp, Rvalue::Discriminant(cond_place), span); + self.push_assignment( + current, + tmp, + Rvalue::Discriminant(cond_place.store()), + span, + ); let next = self.new_basic_block(); let else_target = current_else.get_or_insert_with(|| self.new_basic_block()); self.set_terminator( current, TerminatorKind::SwitchInt { - discr: Operand { kind: OperandKind::Copy(tmp), span: None }, + discr: Operand { kind: OperandKind::Copy(tmp.store()), span: None }, targets: SwitchTargets::static_if(e, next, *else_target), }, span, @@ -656,7 +659,7 @@ impl<'db> MirLowerCtx<'_, 'db> { v: VariantId, current: BasicBlockId, current_else: Option<BasicBlockId>, - cond_place: &Place, + cond_place: &PlaceRef<'db>, mode: MatchingMode, ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> { Ok(match shape { @@ -700,11 +703,11 @@ impl<'db> MirLowerCtx<'_, 'db> { mut current: BasicBlockId, mut current_else: Option<BasicBlockId>, args: impl Iterator<Item = (PlaceElem, PatId)>, - cond_place: &Place, + cond_place: &PlaceRef<'db>, mode: MatchingMode, ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> { for (proj, arg) in args { - let cond_place = cond_place.project(proj, &mut self.result.projection_store); + let cond_place = cond_place.project(proj); (current, current_else) = self.pattern_match_inner(current, current_else, cond_place, arg, mode)?; } @@ -718,7 +721,7 @@ impl<'db> MirLowerCtx<'_, 'db> { args: &[PatId], ellipsis: Option<u32>, fields: impl DoubleEndedIterator<Item = PlaceElem> + Clone, - cond_place: &Place, + cond_place: &PlaceRef<'db>, mode: MatchingMode, ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> { let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize)); diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs index a534e50997..9054987066 100644 --- a/crates/hir-ty/src/mir/pretty.rs +++ b/crates/hir-ty/src/mir/pretty.rs @@ -373,7 +373,7 @@ impl<'a, 'db> MirPrettyCtx<'a, 'db> { } } } - f(self, p.local, p.projection.lookup(&self.body.projection_store)); + f(self, p.local, p.projection.lookup()); } fn operand(&mut self, r: &Operand) { diff --git a/crates/hir-ty/src/next_solver.rs b/crates/hir-ty/src/next_solver.rs index 47b4b1dc4a..f0d33ad2dd 100644 --- a/crates/hir-ty/src/next_solver.rs +++ b/crates/hir-ty/src/next_solver.rs @@ -120,6 +120,7 @@ pub struct DefaultEmpty<'db> { pub clauses: Clauses<'db>, pub region_assumptions: RegionAssumptions<'db>, pub consts: Consts<'db>, + pub projection: crate::mir::Projection<'db>, } pub struct DefaultAny<'db> { @@ -237,6 +238,12 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> { let ty = ManuallyDrop::new(ty.store()); ty.as_ref() }; + let create_projection = |slice| { + let it = crate::mir::Projection::new_from_slice(slice); + // We need to increase the refcount (forever), so that the types won't be freed. + let it = ManuallyDrop::new(it.store()); + it.as_ref() + }; let str = create_ty(TyKind::Str); let statik = create_region(RegionKind::ReStatic); @@ -303,6 +310,7 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> { clauses: create_clauses(&[]), region_assumptions: create_region_assumptions(&[]), consts: create_consts(&[]), + projection: create_projection(&[]), }, one_invariant: create_variances_of(&[rustc_type_ir::Variance::Invariant]), one_covariant: create_variances_of(&[rustc_type_ir::Variance::Covariant]), diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs index 5ca0e67d29..172b1a245f 100644 --- a/crates/hir-ty/src/next_solver/interner.rs +++ b/crates/hir-ty/src/next_solver/interner.rs @@ -2582,6 +2582,7 @@ pub unsafe fn collect_ty_garbage() { gc.add_slice_storage::<super::predicate::BoundExistentialPredicatesStorage>(); gc.add_slice_storage::<super::region::RegionAssumptionsStorage>(); gc.add_slice_storage::<super::ty::TysStorage>(); + gc.add_slice_storage::<crate::mir::ProjectionStorage>(); // SAFETY: // - By our precondition, there are no unrecorded types. @@ -2646,4 +2647,5 @@ impl_gc_visit_slice!( super::region::RegionAssumptionsStorage, super::ty::TysStorage, super::consts::ConstsStorage, + crate::mir::ProjectionStorage, ); diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs index 57aba51b4e..f6b13cbe0b 100644 --- a/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/crates/ide/src/inlay_hints/implicit_drop.rs @@ -43,7 +43,7 @@ pub(super) fn hints( for (_, bb) in mir.basic_blocks.iter() { let terminator = bb.terminator.as_ref()?; - if let TerminatorKind::Drop { place, .. } = terminator.kind { + if let TerminatorKind::Drop { place, .. } = &terminator.kind { if !place.projection.is_empty() { continue; // Ignore complex cases for now } |