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.rs272
1 files changed, 122 insertions, 150 deletions
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 16994cdd0c..c4e0640051 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -5,7 +5,7 @@ use std::{fmt::Write, iter, mem};
use base_db::ra_salsa::Cycle;
use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
use hir_def::{
- body::Body,
+ body::{Body, HygieneId},
data::adt::{StructKind, VariantData},
hir::{
ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal,
@@ -13,7 +13,8 @@ use hir_def::{
},
lang_item::{LangItem, LangItemTarget},
path::Path,
- resolver::{resolver_for_expr, HasResolver, ResolveValueResult, ValueNs},
+ resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
+ type_ref::TypesMap,
AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId,
Lookup, TraitId, TupleId, TypeOrConstParamId,
};
@@ -28,7 +29,7 @@ use triomphe::Arc;
use crate::{
consteval::ConstEvalError,
db::{HirDatabase, InternedClosure},
- display::HirDisplay,
+ display::{hir_display_with_types_map, HirDisplay},
error_lifetime,
generics::generics,
infer::{cast::CastTy, unify::InferenceTable, CaptureKind, CapturedItem, TypeMismatch},
@@ -76,6 +77,7 @@ struct MirLowerCtx<'a> {
db: &'a dyn HirDatabase,
body: &'a Body,
infer: &'a InferenceResult,
+ resolver: Resolver,
drop_scopes: Vec<DropScope>,
}
@@ -246,8 +248,15 @@ impl From<LayoutError> for MirLowerError {
}
impl MirLowerError {
- fn unresolved_path(db: &dyn HirDatabase, p: &Path, edition: Edition) -> Self {
- Self::UnresolvedName(p.display(db, edition).to_string())
+ fn unresolved_path(
+ db: &dyn HirDatabase,
+ p: &Path,
+ edition: Edition,
+ types_map: &TypesMap,
+ ) -> Self {
+ Self::UnresolvedName(
+ hir_display_with_types_map(p, types_map).display(db, edition).to_string(),
+ )
}
}
@@ -278,6 +287,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
owner,
closures: vec![],
};
+ let resolver = owner.resolver(db.upcast());
MirLowerCtx {
result: mir,
@@ -285,6 +295,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
infer,
body,
owner,
+ resolver,
current_loop_blocks: None,
labeled_loop_blocks: Default::default(),
discr_temp: None,
@@ -410,43 +421,54 @@ impl<'ctx> MirLowerCtx<'ctx> {
Err(MirLowerError::IncompleteExpr)
}
Expr::Path(p) => {
- let pr =
- if let Some((assoc, subst)) = self.infer.assoc_resolutions_for_expr(expr_id) {
- match assoc {
- hir_def::AssocItemId::ConstId(c) => {
- self.lower_const(
- c.into(),
- current,
- place,
- subst,
- expr_id.into(),
- self.expr_ty_without_adjust(expr_id),
- )?;
- return Ok(Some(current));
- }
- hir_def::AssocItemId::FunctionId(_) => {
- // FnDefs are zero sized, no action is needed.
- return Ok(Some(current));
- }
- hir_def::AssocItemId::TypeAliasId(_) => {
- // FIXME: If it is unreachable, use proper error instead of `not_supported`.
- not_supported!("associated functions and types")
- }
+ let pr = if let Some((assoc, subst)) =
+ self.infer.assoc_resolutions_for_expr(expr_id)
+ {
+ match assoc {
+ hir_def::AssocItemId::ConstId(c) => {
+ self.lower_const(
+ c.into(),
+ current,
+ place,
+ subst,
+ expr_id.into(),
+ self.expr_ty_without_adjust(expr_id),
+ )?;
+ return Ok(Some(current));
}
- } else if let Some(variant) = self.infer.variant_resolution_for_expr(expr_id) {
- match variant {
- VariantId::EnumVariantId(e) => ValueNs::EnumVariantId(e),
- VariantId::StructId(s) => ValueNs::StructId(s),
- VariantId::UnionId(_) => implementation_error!("Union variant as path"),
+ hir_def::AssocItemId::FunctionId(_) => {
+ // FnDefs are zero sized, no action is needed.
+ return Ok(Some(current));
}
- } else {
- let unresolved_name =
- || MirLowerError::unresolved_path(self.db, p, self.edition());
- let resolver = resolver_for_expr(self.db.upcast(), self.owner, expr_id);
- resolver
- .resolve_path_in_value_ns_fully(self.db.upcast(), p)
- .ok_or_else(unresolved_name)?
- };
+ hir_def::AssocItemId::TypeAliasId(_) => {
+ // FIXME: If it is unreachable, use proper error instead of `not_supported`.
+ not_supported!("associated functions and types")
+ }
+ }
+ } else if let Some(variant) = self.infer.variant_resolution_for_expr(expr_id) {
+ match variant {
+ VariantId::EnumVariantId(e) => ValueNs::EnumVariantId(e),
+ VariantId::StructId(s) => ValueNs::StructId(s),
+ VariantId::UnionId(_) => implementation_error!("Union variant as path"),
+ }
+ } else {
+ let resolver_guard =
+ self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr_id);
+ let hygiene = self.body.expr_path_hygiene(expr_id);
+ let result = self
+ .resolver
+ .resolve_path_in_value_ns_fully(self.db.upcast(), p, hygiene)
+ .ok_or_else(|| {
+ MirLowerError::unresolved_path(
+ self.db,
+ p,
+ self.edition(),
+ &self.body.types,
+ )
+ })?;
+ self.resolver.reset_to_guard(resolver_guard);
+ result
+ };
match pr {
ValueNs::LocalBinding(_) | ValueNs::StaticId(_) => {
let Some((temp, current)) =
@@ -553,8 +575,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
return Ok(None);
};
self.push_fake_read(current, cond_place, expr_id.into());
+ let resolver_guard =
+ self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr_id);
let (then_target, else_target) =
self.pattern_match(current, None, cond_place, *pat)?;
+ self.resolver.reset_to_guard(resolver_guard);
self.write_bytes_to_place(
then_target,
place,
@@ -688,6 +713,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
self.push_fake_read(current, cond_place, expr_id.into());
let mut end = None;
+ let resolver_guard =
+ self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr_id);
for MatchArm { pat, guard, expr } in arms.iter() {
let (then, mut otherwise) =
self.pattern_match(current, None, cond_place, *pat)?;
@@ -721,6 +748,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
}
+ self.resolver.reset_to_guard(resolver_guard);
if self.is_unterminated(current) {
self.set_terminator(current, TerminatorKind::Unreachable, expr_id.into());
}
@@ -795,7 +823,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
Expr::Become { .. } => not_supported!("tail-calls"),
Expr::Yield { .. } => not_supported!("yield"),
- Expr::RecordLit { fields, path, spread, ellipsis: _, is_assignee_expr: _ } => {
+ Expr::RecordLit { fields, path, spread } => {
let spread_place = match spread {
&Some(it) => {
let Some((p, c)) = self.lower_expr_as_place(current, it, true)? else {
@@ -809,7 +837,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
let variant_id =
self.infer.variant_resolution_for_expr(expr_id).ok_or_else(|| match path {
Some(p) => MirLowerError::UnresolvedName(
- p.display(self.db, self.edition()).to_string(),
+ hir_display_with_types_map(&**p, &self.body.types)
+ .display(self.db, self.edition())
+ .to_string(),
),
None => MirLowerError::RecordLiteralWithoutPath,
})?;
@@ -1010,35 +1040,28 @@ impl<'ctx> MirLowerCtx<'ctx> {
);
}
}
- if let hir_def::hir::BinaryOp::Assignment { op } = op {
- if let Some(op) = op {
- // last adjustment is `&mut` which we don't want it.
- let adjusts = self
- .infer
- .expr_adjustments
- .get(lhs)
- .and_then(|it| it.split_last())
- .map(|it| it.1)
- .ok_or(MirLowerError::TypeError(
- "adjustment of binary op was missing",
- ))?;
- let Some((lhs_place, current)) =
- self.lower_expr_as_place_with_adjust(current, *lhs, false, adjusts)?
- else {
- return Ok(None);
- };
- let Some((rhs_op, current)) =
- self.lower_expr_to_some_operand(*rhs, current)?
- else {
- return Ok(None);
- };
- let r_value =
- Rvalue::CheckedBinaryOp(op.into(), Operand::Copy(lhs_place), rhs_op);
- self.push_assignment(current, lhs_place, r_value, expr_id.into());
- return Ok(Some(current));
- } else {
- return self.lower_assignment(current, *lhs, *rhs, expr_id.into());
- }
+ if let hir_def::hir::BinaryOp::Assignment { op: Some(op) } = op {
+ // last adjustment is `&mut` which we don't want it.
+ let adjusts = self
+ .infer
+ .expr_adjustments
+ .get(lhs)
+ .and_then(|it| it.split_last())
+ .map(|it| it.1)
+ .ok_or(MirLowerError::TypeError("adjustment of binary op was missing"))?;
+ let Some((lhs_place, current)) =
+ self.lower_expr_as_place_with_adjust(current, *lhs, false, adjusts)?
+ else {
+ return Ok(None);
+ };
+ let Some((rhs_op, current)) = self.lower_expr_to_some_operand(*rhs, current)?
+ else {
+ return Ok(None);
+ };
+ let r_value =
+ Rvalue::CheckedBinaryOp(op.into(), Operand::Copy(lhs_place), rhs_op);
+ self.push_assignment(current, lhs_place, r_value, expr_id.into());
+ return Ok(Some(current));
}
let Some((lhs_op, current)) = self.lower_expr_to_some_operand(*lhs, current)?
else {
@@ -1097,6 +1120,18 @@ impl<'ctx> MirLowerCtx<'ctx> {
);
Ok(Some(current))
}
+ &Expr::Assignment { target, value } => {
+ let Some((value, mut current)) = self.lower_expr_as_place(current, value, true)?
+ else {
+ return Ok(None);
+ };
+ self.push_fake_read(current, value, expr_id.into());
+ let resolver_guard =
+ self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr_id);
+ current = self.pattern_match_assignment(current, value, target)?;
+ self.resolver.reset_to_guard(resolver_guard);
+ Ok(Some(current))
+ }
&Expr::Range { lhs, rhs, range_type: _ } => {
let ty = self.expr_ty_without_adjust(expr_id);
let Some((adt, subst)) = ty.as_adt() else {
@@ -1213,7 +1248,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
);
Ok(Some(current))
}
- Expr::Tuple { exprs, is_assignee_expr: _ } => {
+ Expr::Tuple { exprs } => {
let Some(values) = exprs
.iter()
.map(|it| {
@@ -1291,73 +1326,6 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
- fn lower_destructing_assignment(
- &mut self,
- mut current: BasicBlockId,
- lhs: ExprId,
- rhs: Place,
- span: MirSpan,
- ) -> Result<Option<BasicBlockId>> {
- match &self.body.exprs[lhs] {
- Expr::Tuple { exprs, is_assignee_expr: _ } => {
- for (i, expr) in exprs.iter().enumerate() {
- let rhs = rhs.project(
- ProjectionElem::Field(Either::Right(TupleFieldId {
- tuple: TupleId(!0), // Dummy this as its unused
- index: i as u32,
- })),
- &mut self.result.projection_store,
- );
- let Some(c) = self.lower_destructing_assignment(current, *expr, rhs, span)?
- else {
- return Ok(None);
- };
- current = c;
- }
- Ok(Some(current))
- }
- Expr::Underscore => Ok(Some(current)),
- _ => {
- let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)?
- else {
- return Ok(None);
- };
- self.push_assignment(current, lhs_place, Operand::Copy(rhs).into(), span);
- Ok(Some(current))
- }
- }
- }
-
- fn lower_assignment(
- &mut self,
- current: BasicBlockId,
- lhs: ExprId,
- rhs: ExprId,
- span: MirSpan,
- ) -> Result<Option<BasicBlockId>> {
- 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) {
- self.push_fake_read_for_operand(current, rhs_op, span);
- return Ok(Some(current));
- }
- if matches!(
- &self.body.exprs[lhs],
- Expr::Tuple { .. } | Expr::RecordLit { .. } | Expr::Call { .. }
- ) {
- let temp = self.temp(self.expr_ty_after_adjustments(rhs), current, rhs.into())?;
- let temp = Place::from(temp);
- self.push_assignment(current, temp, 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 {
- return Ok(None);
- };
- self.push_assignment(current, lhs_place, rhs_op.into(), span);
- Ok(Some(current))
- }
-
fn placeholder_subst(&mut self) -> Substitution {
match self.owner.as_generic_def_id(self.db.upcast()) {
Some(it) => TyBuilder::placeholder_subst(self.db, it),
@@ -1406,10 +1374,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
let edition = self.edition();
let unresolved_name =
- || MirLowerError::unresolved_path(self.db, c.as_ref(), edition);
- let resolver = self.owner.resolver(self.db.upcast());
- let pr = resolver
- .resolve_path_in_value_ns(self.db.upcast(), c.as_ref())
+ || MirLowerError::unresolved_path(self.db, c, edition, &self.body.types);
+ let pr = self
+ .resolver
+ .resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT)
.ok_or_else(unresolved_name)?;
match pr {
ResolveValueResult::ValueNs(v, _) => {
@@ -1632,12 +1600,6 @@ impl<'ctx> MirLowerCtx<'ctx> {
self.push_statement(block, StatementKind::FakeRead(p).with_span(span));
}
- fn push_fake_read_for_operand(&mut self, block: BasicBlockId, operand: Operand, span: MirSpan) {
- if let Operand::Move(p) | Operand::Copy(p) = operand {
- self.push_fake_read(block, p, span);
- }
- }
-
fn push_assignment(
&mut self,
block: BasicBlockId,
@@ -1791,8 +1753,16 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
current = c;
self.push_fake_read(current, init_place, span);
+ // Using the initializer for the resolver scope is good enough for us, as it cannot create new declarations
+ // and has all declarations of the `let`.
+ let resolver_guard = self.resolver.update_to_inner_scope(
+ self.db.upcast(),
+ self.owner,
+ *expr_id,
+ );
(current, else_block) =
self.pattern_match(current, None, init_place, *pat)?;
+ self.resolver.reset_to_guard(resolver_guard);
match (else_block, else_branch) {
(None, _) => (),
(Some(else_block), None) => {
@@ -1828,7 +1798,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
self.push_fake_read(c, p, expr.into());
current = scope2.pop_and_drop(self, c, expr.into());
}
- hir_def::hir::Statement::Item => (),
+ hir_def::hir::Statement::Item(_) => (),
}
}
if let Some(tail) = tail {
@@ -2066,11 +2036,13 @@ pub fn mir_body_for_closure_query(
let Some(sig) = ClosureSubst(substs).sig_ty().callable_sig(db) else {
implementation_error!("closure has not callable sig");
};
+ let resolver_guard = ctx.resolver.update_to_inner_scope(db.upcast(), owner, expr);
let current = ctx.lower_params_and_bindings(
args.iter().zip(sig.params().iter()).map(|(it, y)| (*it, y.clone())),
None,
|_| true,
)?;
+ ctx.resolver.reset_to_guard(resolver_guard);
if let Some(current) = ctx.lower_expr_to_place(*root, return_slot().into(), current)? {
let current = ctx.pop_drop_scope_assert_finished(current, root.into())?;
ctx.set_terminator(current, TerminatorKind::Return, (*root).into());