mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-04 14:07:36 +00:00
Intern projections in mir place
This commit is contained in:
parent
e4c469321c
commit
9708a29e57
@ -1,6 +1,6 @@
|
|||||||
//! MIR definitions and implementation
|
//! MIR definitions and implementation
|
||||||
|
|
||||||
use std::{fmt::Display, iter};
|
use std::{collections::hash_map::Entry, fmt::Display, iter};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
consteval::usize_const,
|
consteval::usize_const,
|
||||||
@ -37,6 +37,7 @@ pub use monomorphization::{
|
|||||||
monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query,
|
monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query,
|
||||||
monomorphized_mir_body_query, monomorphized_mir_body_recover,
|
monomorphized_mir_body_query, monomorphized_mir_body_recover,
|
||||||
};
|
};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use stdx::{impl_from, never};
|
use stdx::{impl_from, never};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
@ -223,35 +224,93 @@ impl<V, T> ProjectionElem<V, T> {
|
|||||||
|
|
||||||
type PlaceElem = ProjectionElem<LocalId, Ty>;
|
type PlaceElem = ProjectionElem<LocalId, Ty>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ProjectionId(u32);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct ProjectionStore {
|
||||||
|
id_to_proj: FxHashMap<ProjectionId, Box<[PlaceElem]>>,
|
||||||
|
proj_to_id: FxHashMap<Box<[PlaceElem]>, ProjectionId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ProjectionStore {
|
||||||
|
fn shrink_to_fit(&mut self) {
|
||||||
|
self.id_to_proj.shrink_to_fit();
|
||||||
|
self.proj_to_id.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option<ProjectionId> {
|
||||||
|
self.proj_to_id.get(projection).copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProjectionId {
|
||||||
|
const EMPTY: ProjectionId = ProjectionId(0);
|
||||||
|
|
||||||
|
fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] {
|
||||||
|
store.id_to_proj.get(&self).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn project(self, projection: PlaceElem, store: &mut ProjectionStore) -> ProjectionId {
|
||||||
|
let mut current = self.lookup(store).to_vec();
|
||||||
|
current.push(projection);
|
||||||
|
store.intern(current.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Place {
|
pub struct Place {
|
||||||
pub local: LocalId,
|
pub local: LocalId,
|
||||||
pub projection: Box<[PlaceElem]>,
|
pub projection: ProjectionId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Place {
|
impl Place {
|
||||||
fn is_parent(&self, child: &Place) -> bool {
|
fn is_parent(&self, child: &Place, store: &ProjectionStore) -> bool {
|
||||||
self.local == child.local && child.projection.starts_with(&self.projection)
|
self.local == child.local
|
||||||
|
&& child.projection.lookup(store).starts_with(&self.projection.lookup(store))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The place itself is not included
|
/// The place itself is not included
|
||||||
fn iterate_over_parents(&self) -> impl Iterator<Item = Place> + '_ {
|
fn iterate_over_parents<'a>(
|
||||||
(0..self.projection.len())
|
&'a self,
|
||||||
.map(|x| &self.projection[0..x])
|
store: &'a ProjectionStore,
|
||||||
.map(|x| Place { local: self.local, projection: x.to_vec().into() })
|
) -> 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 project(&self, projection: PlaceElem) -> Place {
|
fn project(&self, projection: PlaceElem, store: &mut ProjectionStore) -> Place {
|
||||||
Place {
|
Place { local: self.local, projection: self.projection.project(projection, store) }
|
||||||
local: self.local,
|
|
||||||
projection: self.projection.iter().cloned().chain([projection]).collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LocalId> for Place {
|
impl From<LocalId> for Place {
|
||||||
fn from(local: LocalId) -> Self {
|
fn from(local: LocalId) -> Self {
|
||||||
Self { local, projection: vec![].into() }
|
Self { local, projection: ProjectionId::EMPTY }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,6 +1056,7 @@ pub struct BasicBlock {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct MirBody {
|
pub struct MirBody {
|
||||||
|
pub projection_store: ProjectionStore,
|
||||||
pub basic_blocks: Arena<BasicBlock>,
|
pub basic_blocks: Arena<BasicBlock>,
|
||||||
pub locals: Arena<Local>,
|
pub locals: Arena<Local>,
|
||||||
pub start_block: BasicBlockId,
|
pub start_block: BasicBlockId,
|
||||||
@ -1009,11 +1069,15 @@ pub struct MirBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MirBody {
|
impl MirBody {
|
||||||
fn walk_places(&mut self, mut f: impl FnMut(&mut Place)) {
|
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)) {
|
fn for_operand(
|
||||||
|
op: &mut Operand,
|
||||||
|
f: &mut impl FnMut(&mut Place, &mut ProjectionStore),
|
||||||
|
store: &mut ProjectionStore,
|
||||||
|
) {
|
||||||
match op {
|
match op {
|
||||||
Operand::Copy(p) | Operand::Move(p) => {
|
Operand::Copy(p) | Operand::Move(p) => {
|
||||||
f(p);
|
f(p, store);
|
||||||
}
|
}
|
||||||
Operand::Constant(_) | Operand::Static(_) => (),
|
Operand::Constant(_) | Operand::Static(_) => (),
|
||||||
}
|
}
|
||||||
@ -1022,30 +1086,30 @@ impl MirBody {
|
|||||||
for statement in &mut block.statements {
|
for statement in &mut block.statements {
|
||||||
match &mut statement.kind {
|
match &mut statement.kind {
|
||||||
StatementKind::Assign(p, r) => {
|
StatementKind::Assign(p, r) => {
|
||||||
f(p);
|
f(p, &mut self.projection_store);
|
||||||
match r {
|
match r {
|
||||||
Rvalue::ShallowInitBoxWithAlloc(_) => (),
|
Rvalue::ShallowInitBoxWithAlloc(_) => (),
|
||||||
Rvalue::ShallowInitBox(o, _)
|
Rvalue::ShallowInitBox(o, _)
|
||||||
| Rvalue::UnaryOp(_, o)
|
| Rvalue::UnaryOp(_, o)
|
||||||
| Rvalue::Cast(_, o, _)
|
| Rvalue::Cast(_, o, _)
|
||||||
| Rvalue::Repeat(o, _)
|
| Rvalue::Repeat(o, _)
|
||||||
| Rvalue::Use(o) => for_operand(o, &mut f),
|
| Rvalue::Use(o) => for_operand(o, &mut f, &mut self.projection_store),
|
||||||
Rvalue::CopyForDeref(p)
|
Rvalue::CopyForDeref(p)
|
||||||
| Rvalue::Discriminant(p)
|
| Rvalue::Discriminant(p)
|
||||||
| Rvalue::Len(p)
|
| Rvalue::Len(p)
|
||||||
| Rvalue::Ref(_, p) => f(p),
|
| Rvalue::Ref(_, p) => f(p, &mut self.projection_store),
|
||||||
Rvalue::CheckedBinaryOp(_, o1, o2) => {
|
Rvalue::CheckedBinaryOp(_, o1, o2) => {
|
||||||
for_operand(o1, &mut f);
|
for_operand(o1, &mut f, &mut self.projection_store);
|
||||||
for_operand(o2, &mut f);
|
for_operand(o2, &mut f, &mut self.projection_store);
|
||||||
}
|
}
|
||||||
Rvalue::Aggregate(_, ops) => {
|
Rvalue::Aggregate(_, ops) => {
|
||||||
for op in ops.iter_mut() {
|
for op in ops.iter_mut() {
|
||||||
for_operand(op, &mut f);
|
for_operand(op, &mut f, &mut self.projection_store);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementKind::Deinit(p) => f(p),
|
StatementKind::Deinit(p) => f(p, &mut self.projection_store),
|
||||||
StatementKind::StorageLive(_)
|
StatementKind::StorageLive(_)
|
||||||
| StatementKind::StorageDead(_)
|
| StatementKind::StorageDead(_)
|
||||||
| StatementKind::Nop => (),
|
| StatementKind::Nop => (),
|
||||||
@ -1053,7 +1117,9 @@ impl MirBody {
|
|||||||
}
|
}
|
||||||
match &mut block.terminator {
|
match &mut block.terminator {
|
||||||
Some(x) => match &mut x.kind {
|
Some(x) => match &mut x.kind {
|
||||||
TerminatorKind::SwitchInt { discr, .. } => for_operand(discr, &mut f),
|
TerminatorKind::SwitchInt { discr, .. } => {
|
||||||
|
for_operand(discr, &mut f, &mut self.projection_store)
|
||||||
|
}
|
||||||
TerminatorKind::FalseEdge { .. }
|
TerminatorKind::FalseEdge { .. }
|
||||||
| TerminatorKind::FalseUnwind { .. }
|
| TerminatorKind::FalseUnwind { .. }
|
||||||
| TerminatorKind::Goto { .. }
|
| TerminatorKind::Goto { .. }
|
||||||
@ -1063,23 +1129,24 @@ impl MirBody {
|
|||||||
| TerminatorKind::Return
|
| TerminatorKind::Return
|
||||||
| TerminatorKind::Unreachable => (),
|
| TerminatorKind::Unreachable => (),
|
||||||
TerminatorKind::Drop { place, .. } => {
|
TerminatorKind::Drop { place, .. } => {
|
||||||
f(place);
|
f(place, &mut self.projection_store);
|
||||||
}
|
}
|
||||||
TerminatorKind::DropAndReplace { place, value, .. } => {
|
TerminatorKind::DropAndReplace { place, value, .. } => {
|
||||||
f(place);
|
f(place, &mut self.projection_store);
|
||||||
for_operand(value, &mut f);
|
for_operand(value, &mut f, &mut self.projection_store);
|
||||||
}
|
}
|
||||||
TerminatorKind::Call { func, args, destination, .. } => {
|
TerminatorKind::Call { func, args, destination, .. } => {
|
||||||
for_operand(func, &mut f);
|
for_operand(func, &mut f, &mut self.projection_store);
|
||||||
args.iter_mut().for_each(|x| for_operand(x, &mut f));
|
args.iter_mut()
|
||||||
f(destination);
|
.for_each(|x| for_operand(x, &mut f, &mut self.projection_store));
|
||||||
|
f(destination, &mut self.projection_store);
|
||||||
}
|
}
|
||||||
TerminatorKind::Assert { cond, .. } => {
|
TerminatorKind::Assert { cond, .. } => {
|
||||||
for_operand(cond, &mut f);
|
for_operand(cond, &mut f, &mut self.projection_store);
|
||||||
}
|
}
|
||||||
TerminatorKind::Yield { value, resume_arg, .. } => {
|
TerminatorKind::Yield { value, resume_arg, .. } => {
|
||||||
for_operand(value, &mut f);
|
for_operand(value, &mut f, &mut self.projection_store);
|
||||||
f(resume_arg);
|
f(resume_arg, &mut self.projection_store);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => (),
|
None => (),
|
||||||
@ -1096,7 +1163,9 @@ impl MirBody {
|
|||||||
binding_locals,
|
binding_locals,
|
||||||
param_locals,
|
param_locals,
|
||||||
closures,
|
closures,
|
||||||
|
projection_store,
|
||||||
} = self;
|
} = self;
|
||||||
|
projection_store.shrink_to_fit();
|
||||||
basic_blocks.shrink_to_fit();
|
basic_blocks.shrink_to_fit();
|
||||||
locals.shrink_to_fit();
|
locals.shrink_to_fit();
|
||||||
binding_locals.shrink_to_fit();
|
binding_locals.shrink_to_fit();
|
||||||
|
@ -88,7 +88,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
|
|||||||
Operand::Copy(p) | Operand::Move(p) => {
|
Operand::Copy(p) | Operand::Move(p) => {
|
||||||
let mut ty: Ty = body.locals[p.local].ty.clone();
|
let mut ty: Ty = body.locals[p.local].ty.clone();
|
||||||
let mut is_dereference_of_ref = false;
|
let mut is_dereference_of_ref = false;
|
||||||
for proj in &*p.projection {
|
for proj in p.projection.lookup(&body.projection_store) {
|
||||||
if *proj == ProjectionElem::Deref && ty.as_reference().is_some() {
|
if *proj == ProjectionElem::Deref && ty.as_reference().is_some() {
|
||||||
is_dereference_of_ref = true;
|
is_dereference_of_ref = true;
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ enum ProjectionCase {
|
|||||||
fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> ProjectionCase {
|
fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> ProjectionCase {
|
||||||
let mut is_part_of = false;
|
let mut is_part_of = false;
|
||||||
let mut ty = body.locals[lvalue.local].ty.clone();
|
let mut ty = body.locals[lvalue.local].ty.clone();
|
||||||
for proj in lvalue.projection.iter() {
|
for proj in lvalue.projection.lookup(&body.projection_store).iter() {
|
||||||
match proj {
|
match proj {
|
||||||
ProjectionElem::Deref if ty.as_adt().is_none() => return ProjectionCase::Indirect, // It's indirect in case of reference and raw
|
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>`
|
ProjectionElem::Deref // It's direct in case of `Box<T>`
|
||||||
@ -254,7 +254,7 @@ fn ever_initialized_map(
|
|||||||
for statement in &block.statements {
|
for statement in &block.statements {
|
||||||
match &statement.kind {
|
match &statement.kind {
|
||||||
StatementKind::Assign(p, _) => {
|
StatementKind::Assign(p, _) => {
|
||||||
if p.projection.len() == 0 && p.local == l {
|
if p.projection.lookup(&body.projection_store).len() == 0 && p.local == l {
|
||||||
is_ever_initialized = true;
|
is_ever_initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,7 +289,9 @@ fn ever_initialized_map(
|
|||||||
| TerminatorKind::Return
|
| TerminatorKind::Return
|
||||||
| TerminatorKind::Unreachable => (),
|
| TerminatorKind::Unreachable => (),
|
||||||
TerminatorKind::Call { target, cleanup, destination, .. } => {
|
TerminatorKind::Call { target, cleanup, destination, .. } => {
|
||||||
if destination.projection.len() == 0 && destination.local == l {
|
if destination.projection.lookup(&body.projection_store).len() == 0
|
||||||
|
&& destination.local == l
|
||||||
|
{
|
||||||
is_ever_initialized = true;
|
is_ever_initialized = true;
|
||||||
}
|
}
|
||||||
target
|
target
|
||||||
@ -389,7 +391,7 @@ fn mutability_of_locals(
|
|||||||
| TerminatorKind::Assert { .. }
|
| TerminatorKind::Assert { .. }
|
||||||
| TerminatorKind::Yield { .. } => (),
|
| TerminatorKind::Yield { .. } => (),
|
||||||
TerminatorKind::Call { destination, .. } => {
|
TerminatorKind::Call { destination, .. } => {
|
||||||
if destination.projection.len() == 0 {
|
if destination.projection.lookup(&body.projection_store).len() == 0 {
|
||||||
if ever_init_map.get(destination.local).copied().unwrap_or_default() {
|
if ever_init_map.get(destination.local).copied().unwrap_or_default() {
|
||||||
push_mut_span(destination.local, MirSpan::Unknown);
|
push_mut_span(destination.local, MirSpan::Unknown);
|
||||||
} else {
|
} else {
|
||||||
|
@ -46,8 +46,8 @@ use crate::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
return_slot, AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError,
|
return_slot, AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError,
|
||||||
MirSpan, Operand, Place, PlaceElem, ProjectionElem, Rvalue, StatementKind, TerminatorKind,
|
MirSpan, Operand, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind,
|
||||||
UnOp,
|
TerminatorKind, UnOp,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod shim;
|
mod shim;
|
||||||
@ -485,17 +485,18 @@ struct DropFlags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DropFlags {
|
impl DropFlags {
|
||||||
fn add_place(&mut self, p: Place) {
|
fn add_place(&mut self, p: Place, store: &ProjectionStore) {
|
||||||
if p.iterate_over_parents().any(|it| self.need_drop.contains(&it)) {
|
if p.iterate_over_parents(store).any(|it| self.need_drop.contains(&it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.need_drop.retain(|it| !p.is_parent(it));
|
self.need_drop.retain(|it| !p.is_parent(it, store));
|
||||||
self.need_drop.insert(p);
|
self.need_drop.insert(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_place(&mut self, p: &Place) -> bool {
|
fn remove_place(&mut self, p: &Place, store: &ProjectionStore) -> bool {
|
||||||
// FIXME: replace parents with parts
|
// FIXME: replace parents with parts
|
||||||
if let Some(parent) = p.iterate_over_parents().find(|it| self.need_drop.contains(&it)) {
|
if let Some(parent) = p.iterate_over_parents(store).find(|it| self.need_drop.contains(&it))
|
||||||
|
{
|
||||||
self.need_drop.remove(&parent);
|
self.need_drop.remove(&parent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -656,7 +657,7 @@ impl Evaluator<'_> {
|
|||||||
let mut addr = locals.ptr[p.local].addr;
|
let mut addr = locals.ptr[p.local].addr;
|
||||||
let mut ty: Ty = locals.body.locals[p.local].ty.clone();
|
let mut ty: Ty = locals.body.locals[p.local].ty.clone();
|
||||||
let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized
|
let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized
|
||||||
for proj in &*p.projection {
|
for proj in p.projection.lookup(&locals.body.projection_store) {
|
||||||
let prev_ty = ty.clone();
|
let prev_ty = ty.clone();
|
||||||
ty = self.projected_ty(ty, proj.clone());
|
ty = self.projected_ty(ty, proj.clone());
|
||||||
match proj {
|
match proj {
|
||||||
@ -837,7 +838,9 @@ impl Evaluator<'_> {
|
|||||||
let addr = self.place_addr(l, &locals)?;
|
let addr = self.place_addr(l, &locals)?;
|
||||||
let result = self.eval_rvalue(r, &mut locals)?.to_vec(&self)?;
|
let result = self.eval_rvalue(r, &mut locals)?.to_vec(&self)?;
|
||||||
self.write_memory(addr, &result)?;
|
self.write_memory(addr, &result)?;
|
||||||
locals.drop_flags.add_place(l.clone());
|
locals
|
||||||
|
.drop_flags
|
||||||
|
.add_place(l.clone(), &locals.body.projection_store);
|
||||||
}
|
}
|
||||||
StatementKind::Deinit(_) => not_supported!("de-init statement"),
|
StatementKind::Deinit(_) => not_supported!("de-init statement"),
|
||||||
StatementKind::StorageLive(_)
|
StatementKind::StorageLive(_)
|
||||||
@ -889,7 +892,9 @@ impl Evaluator<'_> {
|
|||||||
)?,
|
)?,
|
||||||
it => not_supported!("unknown function type {it:?}"),
|
it => not_supported!("unknown function type {it:?}"),
|
||||||
};
|
};
|
||||||
locals.drop_flags.add_place(destination.clone());
|
locals
|
||||||
|
.drop_flags
|
||||||
|
.add_place(destination.clone(), &locals.body.projection_store);
|
||||||
if let Some(stack_frame) = stack_frame {
|
if let Some(stack_frame) = stack_frame {
|
||||||
self.code_stack.push(my_stack_frame);
|
self.code_stack.push(my_stack_frame);
|
||||||
current_block_idx = stack_frame.locals.body.start_block;
|
current_block_idx = stack_frame.locals.body.start_block;
|
||||||
@ -970,7 +975,7 @@ impl Evaluator<'_> {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut remain_args = body.param_locals.len();
|
let mut remain_args = body.param_locals.len();
|
||||||
for ((l, interval), value) in locals.ptr.iter().skip(1).zip(args) {
|
for ((l, interval), value) in locals.ptr.iter().skip(1).zip(args) {
|
||||||
locals.drop_flags.add_place(l.into());
|
locals.drop_flags.add_place(l.into(), &locals.body.projection_store);
|
||||||
match value {
|
match value {
|
||||||
IntervalOrOwned::Owned(value) => interval.write_from_bytes(self, &value)?,
|
IntervalOrOwned::Owned(value) => interval.write_from_bytes(self, &value)?,
|
||||||
IntervalOrOwned::Borrowed(value) => interval.write_from_interval(self, value)?,
|
IntervalOrOwned::Borrowed(value) => interval.write_from_interval(self, value)?,
|
||||||
@ -1646,7 +1651,7 @@ impl Evaluator<'_> {
|
|||||||
fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<Interval> {
|
fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<Interval> {
|
||||||
Ok(match it {
|
Ok(match it {
|
||||||
Operand::Copy(p) | Operand::Move(p) => {
|
Operand::Copy(p) | Operand::Move(p) => {
|
||||||
locals.drop_flags.remove_place(p);
|
locals.drop_flags.remove_place(p, &locals.body.projection_store);
|
||||||
self.eval_place(p, locals)?
|
self.eval_place(p, locals)?
|
||||||
}
|
}
|
||||||
Operand::Static(st) => {
|
Operand::Static(st) => {
|
||||||
@ -2468,7 +2473,7 @@ impl Evaluator<'_> {
|
|||||||
|
|
||||||
fn drop_place(&mut self, place: &Place, locals: &mut Locals, span: MirSpan) -> Result<()> {
|
fn drop_place(&mut self, place: &Place, locals: &mut Locals, span: MirSpan) -> Result<()> {
|
||||||
let (addr, ty, metadata) = self.place_addr_and_ty_and_metadata(place, locals)?;
|
let (addr, ty, metadata) = self.place_addr_and_ty_and_metadata(place, locals)?;
|
||||||
if !locals.drop_flags.remove_place(place) {
|
if !locals.drop_flags.remove_place(place, &locals.body.projection_store) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let metadata = match metadata {
|
let metadata = match metadata {
|
||||||
|
@ -244,6 +244,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
let locals = Arena::new();
|
let locals = Arena::new();
|
||||||
let binding_locals: ArenaMap<BindingId, LocalId> = ArenaMap::new();
|
let binding_locals: ArenaMap<BindingId, LocalId> = ArenaMap::new();
|
||||||
let mir = MirBody {
|
let mir = MirBody {
|
||||||
|
projection_store: ProjectionStore::default(),
|
||||||
basic_blocks,
|
basic_blocks,
|
||||||
locals,
|
locals,
|
||||||
start_block,
|
start_block,
|
||||||
@ -809,10 +810,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
current = c;
|
current = c;
|
||||||
operands[u32::from(field_id.into_raw()) as usize] = Some(op);
|
operands[u32::from(field_id.into_raw()) as usize] = Some(op);
|
||||||
}
|
}
|
||||||
self.push_assignment(
|
let rvalue = Rvalue::Aggregate(
|
||||||
current,
|
|
||||||
place,
|
|
||||||
Rvalue::Aggregate(
|
|
||||||
AggregateKind::Adt(variant_id, subst),
|
AggregateKind::Adt(variant_id, subst),
|
||||||
match spread_place {
|
match spread_place {
|
||||||
Some(sp) => operands
|
Some(sp) => operands
|
||||||
@ -821,13 +819,15 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
.map(|(i, it)| match it {
|
.map(|(i, it)| match it {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => {
|
None => {
|
||||||
let p =
|
let p = sp.project(
|
||||||
sp.project(ProjectionElem::Field(FieldId {
|
ProjectionElem::Field(FieldId {
|
||||||
parent: variant_id,
|
parent: variant_id,
|
||||||
local_id: LocalFieldId::from_raw(
|
local_id: LocalFieldId::from_raw(RawIdx::from(
|
||||||
RawIdx::from(i as u32),
|
i as u32,
|
||||||
),
|
)),
|
||||||
}));
|
}),
|
||||||
|
&mut self.result.projection_store,
|
||||||
|
);
|
||||||
Operand::Copy(p)
|
Operand::Copy(p)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -836,9 +836,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
MirLowerError::TypeError("missing field in record literal"),
|
MirLowerError::TypeError("missing field in record literal"),
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
),
|
|
||||||
expr_id.into(),
|
|
||||||
);
|
);
|
||||||
|
self.push_assignment(current, place, rvalue, expr_id.into());
|
||||||
Ok(Some(current))
|
Ok(Some(current))
|
||||||
}
|
}
|
||||||
VariantId::UnionId(union_id) => {
|
VariantId::UnionId(union_id) => {
|
||||||
@ -847,10 +846,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
};
|
};
|
||||||
let local_id =
|
let local_id =
|
||||||
variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?;
|
variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?;
|
||||||
let place = place.project(PlaceElem::Field(FieldId {
|
let place = place.project(
|
||||||
parent: union_id.into(),
|
PlaceElem::Field(FieldId { parent: union_id.into(), local_id }),
|
||||||
local_id,
|
&mut self.result.projection_store,
|
||||||
}));
|
);
|
||||||
self.lower_expr_to_place(*expr, place, current)
|
self.lower_expr_to_place(*expr, place, current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -904,7 +903,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let p = place.project(ProjectionElem::Deref);
|
let p = place.project(ProjectionElem::Deref, &mut self.result.projection_store);
|
||||||
self.push_assignment(current, p, operand.into(), expr_id.into());
|
self.push_assignment(current, p, operand.into(), expr_id.into());
|
||||||
Ok(Some(current))
|
Ok(Some(current))
|
||||||
}
|
}
|
||||||
@ -1126,7 +1125,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
for capture in captures.iter() {
|
for capture in captures.iter() {
|
||||||
let p = Place {
|
let p = Place {
|
||||||
local: self.binding_local(capture.place.local)?,
|
local: self.binding_local(capture.place.local)?,
|
||||||
projection: capture
|
projection: self.result.projection_store.intern(
|
||||||
|
capture
|
||||||
.place
|
.place
|
||||||
.projections
|
.projections
|
||||||
.clone()
|
.clone()
|
||||||
@ -1143,10 +1143,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
ProjectionElem::Subslice { from, to } => {
|
ProjectionElem::Subslice { from, to } => {
|
||||||
ProjectionElem::Subslice { from, to }
|
ProjectionElem::Subslice { from, to }
|
||||||
}
|
}
|
||||||
ProjectionElem::OpaqueCast(it) => ProjectionElem::OpaqueCast(it),
|
ProjectionElem::OpaqueCast(it) => {
|
||||||
|
ProjectionElem::OpaqueCast(it)
|
||||||
|
}
|
||||||
ProjectionElem::Index(it) => match it {},
|
ProjectionElem::Index(it) => match it {},
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
match &capture.kind {
|
match &capture.kind {
|
||||||
CaptureKind::ByRef(bk) => {
|
CaptureKind::ByRef(bk) => {
|
||||||
@ -1261,12 +1264,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
match &self.body.exprs[lhs] {
|
match &self.body.exprs[lhs] {
|
||||||
Expr::Tuple { exprs, is_assignee_expr: _ } => {
|
Expr::Tuple { exprs, is_assignee_expr: _ } => {
|
||||||
for (i, expr) in exprs.iter().enumerate() {
|
for (i, expr) in exprs.iter().enumerate() {
|
||||||
let Some(c) = self.lower_destructing_assignment(
|
let rhs = rhs.project(
|
||||||
current,
|
ProjectionElem::TupleOrClosureField(i),
|
||||||
*expr,
|
&mut self.result.projection_store,
|
||||||
rhs.project(ProjectionElem::TupleOrClosureField(i)),
|
);
|
||||||
span,
|
let Some(c) = self.lower_destructing_assignment(current, *expr, rhs, span)?
|
||||||
)?
|
|
||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
@ -1323,17 +1325,21 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||||||
placeholder_subst
|
placeholder_subst
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_field_projection(&self, place: &mut Place, expr_id: ExprId) -> Result<()> {
|
fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<()> {
|
||||||
if let Expr::Field { expr, name } = &self.body[expr_id] {
|
if let Expr::Field { expr, name } = &self.body[expr_id] {
|
||||||
if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind(Interner) {
|
if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind(Interner) {
|
||||||
let index = name
|
let index = name
|
||||||
.as_tuple_index()
|
.as_tuple_index()
|
||||||
.ok_or(MirLowerError::TypeError("named field on tuple"))?;
|
.ok_or(MirLowerError::TypeError("named field on tuple"))?;
|
||||||
*place = place.project(ProjectionElem::TupleOrClosureField(index))
|
*place = place.project(
|
||||||
|
ProjectionElem::TupleOrClosureField(index),
|
||||||
|
&mut self.result.projection_store,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let field =
|
let field =
|
||||||
self.infer.field_resolution(expr_id).ok_or(MirLowerError::UnresolvedField)?;
|
self.infer.field_resolution(expr_id).ok_or(MirLowerError::UnresolvedField)?;
|
||||||
*place = place.project(ProjectionElem::Field(field));
|
*place =
|
||||||
|
place.project(ProjectionElem::Field(field), &mut self.result.projection_store);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
not_supported!("")
|
not_supported!("")
|
||||||
@ -1995,13 +2001,14 @@ pub fn mir_body_for_closure_query(
|
|||||||
FnTrait::FnOnce => vec![],
|
FnTrait::FnOnce => vec![],
|
||||||
FnTrait::FnMut | FnTrait::Fn => vec![ProjectionElem::Deref],
|
FnTrait::FnMut | FnTrait::Fn => vec![ProjectionElem::Deref],
|
||||||
};
|
};
|
||||||
ctx.result.walk_places(|p| {
|
ctx.result.walk_places(|p, store| {
|
||||||
if let Some(it) = upvar_map.get(&p.local) {
|
if let Some(it) = upvar_map.get(&p.local) {
|
||||||
let r = it.iter().find(|it| {
|
let r = it.iter().find(|it| {
|
||||||
if p.projection.len() < it.0.place.projections.len() {
|
if p.projection.lookup(&store).len() < it.0.place.projections.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (it, y) in p.projection.iter().zip(it.0.place.projections.iter()) {
|
for (it, y) in p.projection.lookup(&store).iter().zip(it.0.place.projections.iter())
|
||||||
|
{
|
||||||
match (it, y) {
|
match (it, y) {
|
||||||
(ProjectionElem::Deref, ProjectionElem::Deref) => (),
|
(ProjectionElem::Deref, ProjectionElem::Deref) => (),
|
||||||
(ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (),
|
(ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (),
|
||||||
@ -2019,13 +2026,18 @@ pub fn mir_body_for_closure_query(
|
|||||||
p.local = closure_local;
|
p.local = closure_local;
|
||||||
let mut next_projs = closure_projection.clone();
|
let mut next_projs = closure_projection.clone();
|
||||||
next_projs.push(PlaceElem::TupleOrClosureField(it.1));
|
next_projs.push(PlaceElem::TupleOrClosureField(it.1));
|
||||||
let prev_projs = mem::take(&mut p.projection);
|
let prev_projs = p.projection;
|
||||||
if it.0.kind != CaptureKind::ByValue {
|
if it.0.kind != CaptureKind::ByValue {
|
||||||
next_projs.push(ProjectionElem::Deref);
|
next_projs.push(ProjectionElem::Deref);
|
||||||
}
|
}
|
||||||
next_projs
|
next_projs.extend(
|
||||||
.extend(prev_projs.iter().cloned().skip(it.0.place.projections.len()));
|
prev_projs
|
||||||
p.projection = next_projs.into();
|
.lookup(&store)
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.skip(it.0.place.projections.len()),
|
||||||
|
);
|
||||||
|
p.projection = store.intern(next_projs.into());
|
||||||
}
|
}
|
||||||
None => err = Some(p.clone()),
|
None => err = Some(p.clone()),
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ impl MirLowerCtx<'_> {
|
|||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
it.0 = it.0.project(ProjectionElem::Deref);
|
it.0 = it.0.project(ProjectionElem::Deref, &mut self.result.projection_store);
|
||||||
Ok(Some(it))
|
Ok(Some(it))
|
||||||
}
|
}
|
||||||
Adjust::Deref(Some(od)) => {
|
Adjust::Deref(Some(od)) => {
|
||||||
@ -152,7 +152,10 @@ impl MirLowerCtx<'_> {
|
|||||||
Operand::Static(s).into(),
|
Operand::Static(s).into(),
|
||||||
expr_id.into(),
|
expr_id.into(),
|
||||||
);
|
);
|
||||||
Ok(Some((temp.project(ProjectionElem::Deref), current)))
|
Ok(Some((
|
||||||
|
temp.project(ProjectionElem::Deref, &mut self.result.projection_store),
|
||||||
|
current,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
_ => try_rvalue(self),
|
_ => try_rvalue(self),
|
||||||
}
|
}
|
||||||
@ -203,7 +206,7 @@ impl MirLowerCtx<'_> {
|
|||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
r = r.project(ProjectionElem::Deref);
|
r = r.project(ProjectionElem::Deref, &mut self.result.projection_store);
|
||||||
Ok(Some((r, current)))
|
Ok(Some((r, current)))
|
||||||
}
|
}
|
||||||
_ => try_rvalue(self),
|
_ => try_rvalue(self),
|
||||||
@ -267,7 +270,8 @@ impl MirLowerCtx<'_> {
|
|||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
p_base = p_base.project(ProjectionElem::Index(l_index));
|
p_base = p_base
|
||||||
|
.project(ProjectionElem::Index(l_index), &mut self.result.projection_store);
|
||||||
Ok(Some((p_base, current)))
|
Ok(Some((p_base, current)))
|
||||||
}
|
}
|
||||||
_ => try_rvalue(self),
|
_ => try_rvalue(self),
|
||||||
@ -308,7 +312,7 @@ impl MirLowerCtx<'_> {
|
|||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
result = result.project(ProjectionElem::Deref);
|
result = result.project(ProjectionElem::Deref, &mut self.result.projection_store);
|
||||||
Ok(Some((result, current)))
|
Ok(Some((result, current)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +367,7 @@ impl MirLowerCtx<'_> {
|
|||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
result = result.project(ProjectionElem::Deref);
|
result = result.project(ProjectionElem::Deref, &mut self.result.projection_store);
|
||||||
Ok(Some((result, current)))
|
Ok(Some((result, current)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,13 +81,16 @@ impl MirLowerCtx<'_> {
|
|||||||
mode: MatchingMode,
|
mode: MatchingMode,
|
||||||
) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
|
) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
|
||||||
let cnt = self.infer.pat_adjustments.get(&pattern).map(|x| x.len()).unwrap_or_default();
|
let cnt = self.infer.pat_adjustments.get(&pattern).map(|x| x.len()).unwrap_or_default();
|
||||||
cond_place.projection = cond_place
|
cond_place.projection = self.result.projection_store.intern(
|
||||||
|
cond_place
|
||||||
.projection
|
.projection
|
||||||
|
.lookup(&self.result.projection_store)
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.chain((0..cnt).map(|_| ProjectionElem::Deref))
|
.chain((0..cnt).map(|_| ProjectionElem::Deref))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into();
|
.into(),
|
||||||
|
);
|
||||||
Ok(match &self.body.pats[pattern] {
|
Ok(match &self.body.pats[pattern] {
|
||||||
Pat::Missing => return Err(MirLowerError::IncompletePattern),
|
Pat::Missing => return Err(MirLowerError::IncompletePattern),
|
||||||
Pat::Wild => (current, current_else),
|
Pat::Wild => (current, current_else),
|
||||||
@ -262,20 +265,23 @@ impl MirLowerCtx<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i, &pat) in prefix.iter().enumerate() {
|
for (i, &pat) in prefix.iter().enumerate() {
|
||||||
let next_place = (&mut cond_place).project(ProjectionElem::ConstantIndex {
|
let next_place = (&mut cond_place).project(
|
||||||
offset: i as u64,
|
ProjectionElem::ConstantIndex { offset: i as u64, from_end: false },
|
||||||
from_end: false,
|
&mut self.result.projection_store,
|
||||||
});
|
);
|
||||||
(current, current_else) =
|
(current, current_else) =
|
||||||
self.pattern_match_inner(current, current_else, next_place, pat, mode)?;
|
self.pattern_match_inner(current, current_else, next_place, pat, mode)?;
|
||||||
}
|
}
|
||||||
if let Some(slice) = slice {
|
if let Some(slice) = slice {
|
||||||
if mode == MatchingMode::Bind {
|
if mode == MatchingMode::Bind {
|
||||||
if let Pat::Bind { id, subpat: _ } = self.body[*slice] {
|
if let Pat::Bind { id, subpat: _ } = self.body[*slice] {
|
||||||
let next_place = (&mut cond_place).project(ProjectionElem::Subslice {
|
let next_place = (&mut cond_place).project(
|
||||||
|
ProjectionElem::Subslice {
|
||||||
from: prefix.len() as u64,
|
from: prefix.len() as u64,
|
||||||
to: suffix.len() as u64,
|
to: suffix.len() as u64,
|
||||||
});
|
},
|
||||||
|
&mut self.result.projection_store,
|
||||||
|
);
|
||||||
(current, current_else) = self.pattern_match_binding(
|
(current, current_else) = self.pattern_match_binding(
|
||||||
id,
|
id,
|
||||||
next_place,
|
next_place,
|
||||||
@ -287,10 +293,10 @@ impl MirLowerCtx<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i, &pat) in suffix.iter().enumerate() {
|
for (i, &pat) in suffix.iter().enumerate() {
|
||||||
let next_place = (&mut cond_place).project(ProjectionElem::ConstantIndex {
|
let next_place = (&mut cond_place).project(
|
||||||
offset: i as u64,
|
ProjectionElem::ConstantIndex { offset: i as u64, from_end: true },
|
||||||
from_end: true,
|
&mut self.result.projection_store,
|
||||||
});
|
);
|
||||||
(current, current_else) =
|
(current, current_else) =
|
||||||
self.pattern_match_inner(current, current_else, next_place, pat, mode)?;
|
self.pattern_match_inner(current, current_else, next_place, pat, mode)?;
|
||||||
}
|
}
|
||||||
@ -412,13 +418,11 @@ impl MirLowerCtx<'_> {
|
|||||||
mode,
|
mode,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
Pat::Ref { pat, mutability: _ } => self.pattern_match_inner(
|
Pat::Ref { pat, mutability: _ } => {
|
||||||
current,
|
let cond_place =
|
||||||
current_else,
|
cond_place.project(ProjectionElem::Deref, &mut self.result.projection_store);
|
||||||
cond_place.project(ProjectionElem::Deref),
|
self.pattern_match_inner(current, current_else, cond_place, *pat, mode)?
|
||||||
*pat,
|
}
|
||||||
mode,
|
|
||||||
)?,
|
|
||||||
Pat::Box { .. } => not_supported!("box pattern"),
|
Pat::Box { .. } => not_supported!("box pattern"),
|
||||||
Pat::ConstBlock(_) => not_supported!("const block pattern"),
|
Pat::ConstBlock(_) => not_supported!("const block pattern"),
|
||||||
})
|
})
|
||||||
@ -594,7 +598,7 @@ impl MirLowerCtx<'_> {
|
|||||||
mode: MatchingMode,
|
mode: MatchingMode,
|
||||||
) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
|
) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
|
||||||
for (proj, arg) in args {
|
for (proj, arg) in args {
|
||||||
let cond_place = cond_place.project(proj);
|
let cond_place = cond_place.project(proj, &mut self.result.projection_store);
|
||||||
(current, current_else) =
|
(current, current_else) =
|
||||||
self.pattern_match_inner(current, current_else, cond_place, arg, mode)?;
|
self.pattern_match_inner(current, current_else, cond_place, arg, mode)?;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ impl<'a> MirPrettyCtx<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f(self, p.local, &p.projection);
|
f(self, p.local, &p.projection.lookup(&self.body.projection_store));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operand(&mut self, r: &Operand) {
|
fn operand(&mut self, r: &Operand) {
|
||||||
|
Loading…
Reference in New Issue
Block a user