Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22474 from flodiebold/intern-mir-projections
refactor: Intern MIR projections using the new ty interning infrastructure
Florian Diebold 6 days ago
parent 1669108 · parent 231f156 · commit 5ebf65c
-rw-r--r--crates/hir-ty/src/mir.rs190
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs20
-rw-r--r--crates/hir-ty/src/mir/eval.rs38
-rw-r--r--crates/hir-ty/src/mir/lower.rs182
-rw-r--r--crates/hir-ty/src/mir/lower/as_place.rs64
-rw-r--r--crates/hir-ty/src/mir/lower/pattern_matching.rs125
-rw-r--r--crates/hir-ty/src/mir/pretty.rs2
-rw-r--r--crates/hir-ty/src/next_solver.rs8
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs2
-rw-r--r--crates/ide/src/inlay_hints/implicit_drop.rs2
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
}