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.rs153
1 files changed, 76 insertions, 77 deletions
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 8f8f557716..96ddb69814 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -4,8 +4,8 @@ use std::{fmt::Write, iter, mem};
use base_db::Crate;
use hir_def::{
- AdtId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId, GeneralConstId, GenericParamId,
- HasModule, ItemContainerId, LocalFieldId, Lookup, TraitId, TupleId,
+ AdtId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId, GenericParamId, HasModule,
+ ItemContainerId, LocalFieldId, Lookup, TraitId, TupleId,
expr_store::{Body, ExpressionStore, HygieneId, path::Path},
hir::{
ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ClosureKind, ExprId, ExprOrPatId,
@@ -27,9 +27,9 @@ use span::{Edition, FileId};
use syntax::TextRange;
use crate::{
- Adjust, Adjustment, AutoBorrow, CallableDefId, ParamEnvAndCrate,
+ Adjust, Adjustment, AutoBorrow, CallableDefId, InferBodyId, ParamEnvAndCrate,
consteval::ConstEvalError,
- db::{HirDatabase, InternedClosure, InternedClosureId},
+ db::{GeneralConstId, HirDatabase, InternedClosure, InternedClosureId},
display::{DisplayTarget, HirDisplay, hir_display_with_store},
generics::generics,
infer::{
@@ -81,7 +81,8 @@ struct DropScope {
struct MirLowerCtx<'a, 'db> {
result: MirBody,
- owner: DefWithBodyId,
+ owner: InferBodyId,
+ store_owner: ExpressionStoreOwnerId,
current_loop_blocks: Option<LoopBlocks>,
labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks>,
discr_temp: Option<Place>,
@@ -109,7 +110,7 @@ pub enum MirLowerError {
UnresolvedMethod(String),
UnresolvedField,
UnsizedTemporary(StoredTy),
- MissingFunctionDefinition(DefWithBodyId, ExprId),
+ MissingFunctionDefinition(InferBodyId, ExprId),
HasErrors,
/// This should never happen. Type mismatch should catch everything.
TypeError(&'static str),
@@ -188,11 +189,18 @@ impl MirLowerError {
}
}
MirLowerError::MissingFunctionDefinition(owner, it) => {
- let body = Body::of(db, *owner);
+ let owner = owner.expression_store_owner(db);
+ let store = ExpressionStore::of(db, owner);
writeln!(
f,
"Missing function definition for {}",
- body.pretty_print_expr(db, *owner, *it, display_target.edition)
+ hir_def::expr_store::pretty::print_expr_hir(
+ db,
+ store,
+ owner,
+ *it,
+ display_target.edition
+ )
)?;
}
MirLowerError::HasErrors => writeln!(f, "Type inference result contains errors")?,
@@ -281,7 +289,7 @@ type Result<'db, T> = std::result::Result<T, MirLowerError>;
impl<'a, 'db> MirLowerCtx<'a, 'db> {
fn new(
db: &'db dyn HirDatabase,
- owner: DefWithBodyId,
+ owner: InferBodyId,
store: &'a ExpressionStore,
infer: &'a InferenceResult,
) -> Self {
@@ -304,8 +312,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
owner,
closures: vec![],
};
- let resolver = owner.resolver(db);
- let env = db.trait_environment(ExpressionStoreOwnerId::from(owner));
+ let store_owner = owner.expression_store_owner(db);
+ let resolver = store_owner.resolver(db);
+ let env = db.trait_environment(store_owner);
let interner = DbInterner::new_with(db, resolver.krate());
// FIXME(next-solver): Is `non_body_analysis()` correct here? Don't we want to reveal opaque types defined by this body?
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
@@ -317,6 +326,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
store,
types: crate::next_solver::default_types(db),
owner,
+ store_owner,
resolver,
current_loop_blocks: None,
labeled_loop_blocks: Default::default(),
@@ -467,7 +477,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
not_supported!("builtin#asm")
}
Expr::Missing => {
- if let DefWithBodyId::FunctionId(f) = self.owner {
+ if let Some(f) = self.owner.as_function() {
let assoc = f.lookup(self.db);
if let ItemContainerId::TraitId(t) = assoc.container {
let name = &FunctionSignature::of(self.db, f).name;
@@ -497,7 +507,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
}
} else {
let resolver_guard =
- self.resolver.update_to_inner_scope(self.db, self.owner, expr_id);
+ self.resolver.update_to_inner_scope(self.db, self.store_owner, expr_id);
let hygiene = self.store.expr_path_hygiene(expr_id);
let result = self
.resolver
@@ -555,9 +565,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
Ok(Some(current))
}
ValueNs::GenericParam(p) => {
- let Some(def) = self.owner.as_generic_def_id(self.db) else {
- not_supported!("owner without generic def id");
- };
+ let def = self.owner.generic_def(self.db);
let generics = generics(self.db, def);
let index = generics.type_or_const_param_idx(p.into());
self.push_assignment(
@@ -615,7 +623,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
};
self.push_fake_read(current, cond_place, expr_id.into());
let resolver_guard =
- self.resolver.update_to_inner_scope(self.db, self.owner, expr_id);
+ self.resolver.update_to_inner_scope(self.db, self.store_owner, expr_id);
let (then_target, else_target) =
self.pattern_match(current, None, cond_place, *pat)?;
self.resolver.reset_to_guard(resolver_guard);
@@ -753,7 +761,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
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, self.owner, expr_id);
+ self.resolver.update_to_inner_scope(self.db, self.store_owner, expr_id);
for MatchArm { pat, guard, expr } in arms.iter() {
let (then, mut otherwise) =
self.pattern_match(current, None, cond_place, *pat)?;
@@ -1182,7 +1190,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
};
self.push_fake_read(current, value, expr_id.into());
let resolver_guard =
- self.resolver.update_to_inner_scope(self.db, self.owner, expr_id);
+ self.resolver.update_to_inner_scope(self.db, self.store_owner, expr_id);
current = self.pattern_match_assignment(current, value, target)?;
self.resolver.reset_to_guard(resolver_guard);
Ok(Some(current))
@@ -1529,23 +1537,16 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
subst: GenericArgs<'db>,
const_id: GeneralConstId,
) -> Result<'db, Operand> {
- if matches!(const_id, GeneralConstId::AnonConstId(_)) {
- // FIXME:
- not_supported!("anon consts are not supported yet in const eval");
- }
let konst = Const::new_unevaluated(
self.interner(),
UnevaluatedConst { def: const_id.into(), args: subst },
);
- let ty = self
- .db
- .value_ty(match const_id {
- GeneralConstId::ConstId(id) => id.into(),
- GeneralConstId::StaticId(id) => id.into(),
- GeneralConstId::AnonConstId(_) => unreachable!("handled above"),
- })
- .unwrap()
- .instantiate(self.interner(), subst);
+ let ty = match const_id {
+ GeneralConstId::ConstId(id) => self.db.value_ty(id.into()).unwrap(),
+ GeneralConstId::StaticId(id) => self.db.value_ty(id.into()).unwrap(),
+ GeneralConstId::AnonConstId(id) => id.loc(self.db).ty.get(),
+ };
+ let ty = ty.instantiate(self.interner(), subst);
Ok(Operand {
kind: OperandKind::Constant { konst: konst.store(), ty: ty.store() },
span: None,
@@ -1829,8 +1830,11 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
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, self.owner, *expr_id);
+ let resolver_guard = self.resolver.update_to_inner_scope(
+ self.db,
+ self.store_owner,
+ *expr_id,
+ );
(current, else_block) =
self.pattern_match(current, None, init_place, *pat)?;
self.resolver.reset_to_guard(resolver_guard);
@@ -1961,8 +1965,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
match self.result.binding_locals.get(b) {
Some(it) => Ok(*it),
None => {
- // FIXME: It should never happens, but currently it will happen in `const_dependent_on_local` test, which
- // is a hir lowering problem IMO.
+ // FIXME: It should never happens, but currently it will happen in some cases, not sure when exactly.
// never!("Using inaccessible local for binding is always a bug");
Err(MirLowerError::InaccessibleLocal)
}
@@ -2134,12 +2137,10 @@ pub fn mir_body_for_closure_query<'db>(
db: &'db dyn HirDatabase,
closure: InternedClosureId,
) -> Result<'db, MirBody> {
- let InternedClosure { owner, expr, .. } = closure.loc(db);
- let body_owner =
- owner.as_def_with_body().expect("MIR lowering should only happen for body-owned closures");
- let body = Body::of(db, body_owner);
+ let InternedClosure { owner: body_owner, expr, .. } = closure.loc(db);
+ let store = ExpressionStore::of(db, body_owner.expression_store_owner(db));
let infer = InferenceResult::of(db, body_owner);
- let Expr::Closure { args, body: root, .. } = &body[expr] else {
+ let Expr::Closure { args, body: root, .. } = &store[expr] else {
implementation_error!("closure expression is not closure");
};
let crate::next_solver::TyKind::Closure(_, substs) = infer.expr_ty(expr).kind() else {
@@ -2147,7 +2148,7 @@ pub fn mir_body_for_closure_query<'db>(
};
let kind = substs.as_closure().kind();
let captures = infer.closures_data[&expr].min_captures.values().flatten();
- let mut ctx = MirLowerCtx::new(db, body_owner, &body.store, infer);
+ let mut ctx = MirLowerCtx::new(db, body_owner, store, infer);
// 0 is return local
ctx.result.locals.alloc(Local { ty: infer.expr_ty(*root).store() });
@@ -2172,7 +2173,7 @@ pub fn mir_body_for_closure_query<'db>(
ctx.result.param_locals.push(closure_local);
let sig = ctx.interner().signature_unclosure(substs.as_closure().sig(), Safety::Safe);
- let resolver_guard = ctx.resolver.update_to_inner_scope(db, body_owner, expr);
+ let resolver_guard = ctx.resolver.update_to_inner_scope(db, ctx.store_owner, expr);
let current = ctx.lower_params_and_bindings(
args.iter().zip(sig.skip_binder().inputs().iter()).map(|(it, y)| (*it, *y)),
None,
@@ -2290,34 +2291,45 @@ pub fn mir_body_for_closure_query<'db>(
}
#[salsa_macros::tracked(returns(ref), cycle_result = mir_body_cycle_result)]
-pub fn mir_body_query<'db>(db: &'db dyn HirDatabase, def: DefWithBodyId) -> Result<'db, MirBody> {
+pub fn mir_body_query<'db>(db: &'db dyn HirDatabase, def: InferBodyId) -> Result<'db, MirBody> {
let krate = def.krate(db);
let edition = krate.data(db).edition;
let detail = match def {
- DefWithBodyId::FunctionId(it) => {
+ InferBodyId::DefWithBodyId(DefWithBodyId::FunctionId(it)) => {
FunctionSignature::of(db, it).name.display(db, edition).to_string()
}
- DefWithBodyId::StaticId(it) => {
+ InferBodyId::DefWithBodyId(DefWithBodyId::StaticId(it)) => {
StaticSignature::of(db, it).name.display(db, edition).to_string()
}
- DefWithBodyId::ConstId(it) => ConstSignature::of(db, it)
+ InferBodyId::DefWithBodyId(DefWithBodyId::ConstId(it)) => ConstSignature::of(db, it)
.name
.clone()
.unwrap_or_else(Name::missing)
.display(db, edition)
.to_string(),
- DefWithBodyId::VariantId(it) => {
+ InferBodyId::DefWithBodyId(DefWithBodyId::VariantId(it)) => {
let loc = it.lookup(db);
loc.parent.enum_variants(db).variants[loc.index as usize]
.1
.display(db, edition)
.to_string()
}
+ InferBodyId::AnonConstId(_) => "{const}".to_owned(),
};
let _p = tracing::info_span!("mir_body_query", ?detail).entered();
- let body = Body::of(db, def);
+ let (store, root_expr, self_param, params) = match def {
+ InferBodyId::DefWithBodyId(def) => {
+ let body = Body::of(db, def);
+ (&**body, body.root_expr(), body.self_param, &*body.params)
+ }
+ InferBodyId::AnonConstId(def) => {
+ let loc = def.loc(db);
+ let store = ExpressionStore::of(db, loc.owner);
+ (store, loc.expr, None, &[][..])
+ }
+ };
let infer = InferenceResult::of(db, def);
- let mut result = lower_body_to_mir(db, def, body, infer, body.root_expr())?;
+ let mut result = lower_body_to_mir(db, def, store, infer, root_expr, self_param, params)?;
result.shrink_to_fit();
Ok(result)
}
@@ -2325,7 +2337,7 @@ pub fn mir_body_query<'db>(db: &'db dyn HirDatabase, def: DefWithBodyId) -> Resu
fn mir_body_cycle_result<'db>(
_db: &'db dyn HirDatabase,
_: salsa::Id,
- _def: DefWithBodyId,
+ _def: InferBodyId,
) -> Result<'db, MirBody> {
Err(MirLowerError::Loop)
}
@@ -2342,42 +2354,31 @@ fn mir_body_for_closure_cycle_result<'db>(
/// then delegates to [`lower_to_mir_with_store`].
pub fn lower_body_to_mir<'db>(
db: &'db dyn HirDatabase,
- owner: DefWithBodyId,
- body: &Body,
+ owner: InferBodyId,
+ store: &ExpressionStore,
infer: &InferenceResult,
- // FIXME: root_expr should always be the body.body_expr,
- // but this is currently also used for `X` in `[(); X]` which live in the same expression store
root_expr: ExprId,
+ self_param: Option<BindingId>,
+ params: &[PatId],
) -> Result<'db, MirBody> {
- let is_root = root_expr == body.root_expr();
// Extract params and self_param only when lowering the body's root expression for a function.
- if is_root && let DefWithBodyId::FunctionId(fid) = owner {
+ if let Some(fid) = owner.as_function() {
let callable_sig =
db.callable_item_signature(fid.into()).instantiate_identity().skip_binder();
let mut param_tys = callable_sig.inputs().iter().copied();
- let self_param = body.self_param.and_then(|id| Some((id, param_tys.next()?)));
+ let self_param = self_param.and_then(|id| Some((id, param_tys.next()?)));
lower_to_mir_with_store(
db,
owner,
- &body.store,
+ store,
infer,
root_expr,
- body.params.iter().copied().zip(param_tys),
+ params.iter().copied().zip(param_tys),
self_param,
- is_root,
)
} else {
- lower_to_mir_with_store(
- db,
- owner,
- &body.store,
- infer,
- root_expr,
- iter::empty(),
- None,
- is_root,
- )
+ lower_to_mir_with_store(db, owner, store, infer, root_expr, iter::empty(), None)
}
}
@@ -2387,13 +2388,12 @@ pub fn lower_body_to_mir<'db>(
/// const (picks bindings owned by `root_expr`).
pub fn lower_to_mir_with_store<'db>(
db: &'db dyn HirDatabase,
- owner: DefWithBodyId,
+ owner: InferBodyId,
store: &ExpressionStore,
infer: &InferenceResult,
root_expr: ExprId,
params: impl Iterator<Item = (PatId, Ty<'db>)> + Clone,
self_param: Option<(BindingId, Ty<'db>)>,
- is_root: bool,
) -> Result<'db, MirBody> {
if infer.has_type_mismatches() || infer.is_erroneous() {
return Err(MirLowerError::HasErrors);
@@ -2401,10 +2401,9 @@ pub fn lower_to_mir_with_store<'db>(
let mut ctx = MirLowerCtx::new(db, owner, store, infer);
// 0 is return local
ctx.result.locals.alloc(Local { ty: ctx.expr_ty_after_adjustments(root_expr).store() });
- let binding_picker = |b: BindingId| {
- let owner = ctx.store.binding_owner(b);
- if is_root { owner.is_none() } else { owner == Some(root_expr) }
- };
+ let expected_binding_owner =
+ if matches!(owner, InferBodyId::DefWithBodyId(_)) { None } else { Some(root_expr) };
+ let binding_picker = |b: BindingId| ctx.store.binding_owner(b) == expected_binding_owner;
let current = ctx.lower_params_and_bindings(params, self_param, binding_picker)?;
if let Some(current) = ctx.lower_expr_to_place(root_expr, return_slot().into(), current)? {
let current = ctx.pop_drop_scope_assert_finished(current, root_expr.into())?;