Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/lower.rs')
-rw-r--r--crates/hir-ty/src/mir/lower.rs183
1 files changed, 99 insertions, 84 deletions
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 51cf882d05..dd2dba717f 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -71,7 +71,7 @@ struct MirLowerCtx<'a> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MirLowerError {
- ConstEvalError(String, Box<ConstEvalError>),
+ ConstEvalError(Box<str>, Box<ConstEvalError>),
LayoutError(LayoutError),
IncompleteExpr,
IncompletePattern,
@@ -84,7 +84,7 @@ pub enum MirLowerError {
UnsizedTemporary(Ty),
MissingFunctionDefinition(DefWithBodyId, ExprId),
TypeMismatch(TypeMismatch),
- /// This should be never happen. Type mismatch should catch everything.
+ /// This should never happen. Type mismatch should catch everything.
TypeError(&'static str),
NotSupported(String),
ContinueWithoutLoop,
@@ -244,6 +244,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
let locals = Arena::new();
let binding_locals: ArenaMap<BindingId, LocalId> = ArenaMap::new();
let mir = MirBody {
+ projection_store: ProjectionStore::default(),
basic_blocks,
locals,
start_block,
@@ -370,6 +371,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
mut current: BasicBlockId,
) -> Result<Option<BasicBlockId>> {
match &self.body.exprs[expr_id] {
+ Expr::OffsetOf(_) => {
+ not_supported!("builtin#offset_of")
+ }
+ Expr::InlineAsm(_) => {
+ not_supported!("builtin#asm")
+ }
Expr::Missing => {
if let DefWithBodyId::FunctionId(f) = self.owner {
let assoc = f.lookup(self.db.upcast());
@@ -803,36 +810,34 @@ impl<'ctx> MirLowerCtx<'ctx> {
current = c;
operands[u32::from(field_id.into_raw()) as usize] = Some(op);
}
- self.push_assignment(
- current,
- place,
- Rvalue::Aggregate(
- AggregateKind::Adt(variant_id, subst),
- match spread_place {
- Some(sp) => operands
- .into_iter()
- .enumerate()
- .map(|(i, it)| match it {
- Some(it) => it,
- None => {
- let p =
- sp.project(ProjectionElem::Field(FieldId {
- parent: variant_id,
- local_id: LocalFieldId::from_raw(
- RawIdx::from(i as u32),
- ),
- }));
- Operand::Copy(p)
- }
- })
- .collect(),
- None => operands.into_iter().collect::<Option<_>>().ok_or(
- MirLowerError::TypeError("missing field in record literal"),
- )?,
- },
- ),
- expr_id.into(),
+ let rvalue = Rvalue::Aggregate(
+ AggregateKind::Adt(variant_id, subst),
+ match spread_place {
+ Some(sp) => operands
+ .into_iter()
+ .enumerate()
+ .map(|(i, it)| match it {
+ Some(it) => it,
+ None => {
+ let p = sp.project(
+ ProjectionElem::Field(FieldId {
+ parent: variant_id,
+ local_id: LocalFieldId::from_raw(RawIdx::from(
+ i as u32,
+ )),
+ }),
+ &mut self.result.projection_store,
+ );
+ Operand::Copy(p)
+ }
+ })
+ .collect(),
+ None => operands.into_iter().collect::<Option<_>>().ok_or(
+ MirLowerError::TypeError("missing field in record literal"),
+ )?,
+ },
);
+ self.push_assignment(current, place, rvalue, expr_id.into());
Ok(Some(current))
}
VariantId::UnionId(union_id) => {
@@ -841,10 +846,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
let local_id =
variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?;
- let place = place.project(PlaceElem::Field(FieldId {
- parent: union_id.into(),
- local_id,
- }));
+ let place = place.project(
+ PlaceElem::Field(FieldId { parent: union_id.into(), local_id }),
+ &mut self.result.projection_store,
+ );
self.lower_expr_to_place(*expr, place, current)
}
}
@@ -898,7 +903,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
else {
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());
Ok(Some(current))
}
@@ -1120,27 +1125,31 @@ impl<'ctx> MirLowerCtx<'ctx> {
for capture in captures.iter() {
let p = Place {
local: self.binding_local(capture.place.local)?,
- projection: capture
- .place
- .projections
- .clone()
- .into_iter()
- .map(|it| match it {
- ProjectionElem::Deref => ProjectionElem::Deref,
- ProjectionElem::Field(it) => ProjectionElem::Field(it),
- ProjectionElem::TupleOrClosureField(it) => {
- ProjectionElem::TupleOrClosureField(it)
- }
- ProjectionElem::ConstantIndex { offset, from_end } => {
- ProjectionElem::ConstantIndex { offset, from_end }
- }
- ProjectionElem::Subslice { from, to } => {
- ProjectionElem::Subslice { from, to }
- }
- ProjectionElem::OpaqueCast(it) => ProjectionElem::OpaqueCast(it),
- ProjectionElem::Index(it) => match it {},
- })
- .collect(),
+ projection: self.result.projection_store.intern(
+ capture
+ .place
+ .projections
+ .clone()
+ .into_iter()
+ .map(|it| match it {
+ ProjectionElem::Deref => ProjectionElem::Deref,
+ ProjectionElem::Field(it) => ProjectionElem::Field(it),
+ ProjectionElem::TupleOrClosureField(it) => {
+ ProjectionElem::TupleOrClosureField(it)
+ }
+ ProjectionElem::ConstantIndex { offset, from_end } => {
+ ProjectionElem::ConstantIndex { offset, from_end }
+ }
+ ProjectionElem::Subslice { from, to } => {
+ ProjectionElem::Subslice { from, to }
+ }
+ ProjectionElem::OpaqueCast(it) => {
+ ProjectionElem::OpaqueCast(it)
+ }
+ ProjectionElem::Index(it) => match it {},
+ })
+ .collect(),
+ ),
};
match &capture.kind {
CaptureKind::ByRef(bk) => {
@@ -1201,7 +1210,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
let Some(values) = elements
.iter()
.map(|it| {
- let Some((o, c)) = self.lower_expr_to_some_operand(*it, current)? else {
+ let Some((o, c)) = self.lower_expr_to_some_operand(*it, current)?
+ else {
return Ok(None);
};
current = c;
@@ -1254,12 +1264,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
match &self.body.exprs[lhs] {
Expr::Tuple { exprs, is_assignee_expr: _ } => {
for (i, expr) in exprs.iter().enumerate() {
- let Some(c) = self.lower_destructing_assignment(
- current,
- *expr,
- rhs.project(ProjectionElem::TupleOrClosureField(i)),
- span,
- )? else {
+ let rhs = rhs.project(
+ ProjectionElem::TupleOrClosureField(i),
+ &mut self.result.projection_store,
+ );
+ let Some(c) = self.lower_destructing_assignment(current, *expr, rhs, span)?
+ else {
return Ok(None);
};
current = c;
@@ -1268,8 +1278,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
Expr::Underscore => Ok(Some(current)),
_ => {
- let Some((lhs_place, current)) =
- self.lower_expr_as_place(current, lhs, false)?
+ let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)?
else {
return Ok(None);
};
@@ -1286,9 +1295,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
rhs: ExprId,
span: MirSpan,
) -> Result<Option<BasicBlockId>> {
- let Some((rhs_op, current)) =
- self.lower_expr_to_some_operand(rhs, current)?
- else {
+ let Some((rhs_op, current)) = self.lower_expr_to_some_operand(rhs, current)? else {
return Ok(None);
};
if matches!(&self.body.exprs[lhs], Expr::Underscore) {
@@ -1303,9 +1310,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
self.push_assignment(current, temp.clone(), rhs_op.into(), span);
return self.lower_destructing_assignment(current, lhs, temp, span);
}
- let Some((lhs_place, current)) =
- self.lower_expr_as_place(current, lhs, false)?
- else {
+ let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)? else {
return Ok(None);
};
self.push_assignment(current, lhs_place, rhs_op.into(), span);
@@ -1320,17 +1325,21 @@ impl<'ctx> MirLowerCtx<'ctx> {
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 TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind(Interner) {
let index = name
.as_tuple_index()
.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 {
let field =
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 {
not_supported!("")
@@ -1447,7 +1456,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
let name = const_id.name(self.db.upcast());
self.db
.const_eval(const_id.into(), subst, None)
- .map_err(|e| MirLowerError::ConstEvalError(name, Box::new(e)))?
+ .map_err(|e| MirLowerError::ConstEvalError(name.into(), Box::new(e)))?
};
Ok(Operand::Constant(c))
}
@@ -1844,7 +1853,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
data.name.display(self.db.upcast()),
data.variants[variant.local_id].name.display(self.db.upcast())
);
- Err(MirLowerError::ConstEvalError(name, Box::new(e)))
+ Err(MirLowerError::ConstEvalError(name.into(), Box::new(e)))
}
}
}
@@ -1992,13 +2001,14 @@ pub fn mir_body_for_closure_query(
FnTrait::FnOnce => vec![],
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) {
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;
}
- 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) {
(ProjectionElem::Deref, ProjectionElem::Deref) => (),
(ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (),
@@ -2016,13 +2026,18 @@ pub fn mir_body_for_closure_query(
p.local = closure_local;
let mut next_projs = closure_projection.clone();
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 {
next_projs.push(ProjectionElem::Deref);
}
- next_projs
- .extend(prev_projs.iter().cloned().skip(it.0.place.projections.len()));
- p.projection = next_projs.into();
+ next_projs.extend(
+ prev_projs
+ .lookup(&store)
+ .iter()
+ .cloned()
+ .skip(it.0.place.projections.len()),
+ );
+ p.projection = store.intern(next_projs.into());
}
None => err = Some(p.clone()),
}