Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/expr_store/lower.rs')
-rw-r--r--crates/hir-def/src/expr_store/lower.rs128
1 files changed, 68 insertions, 60 deletions
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index f4842700f7..7862cda69f 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -19,7 +19,7 @@ use hir_expand::{
};
use intern::{Symbol, sym};
use rustc_hash::FxHashMap;
-use smallvec::smallvec;
+use smallvec::SmallVec;
use stdx::never;
use syntax::{
AstNode, AstPtr, SyntaxNodePtr,
@@ -38,9 +38,9 @@ use crate::{
attrs::AttrFlags,
db::DefDatabase,
expr_store::{
- Body, BodySourceMap, ExprPtr, ExpressionStore, ExpressionStoreBuilder,
+ Body, BodySourceMap, ExprPtr, ExprRoot, ExpressionStore, ExpressionStoreBuilder,
ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, LifetimePtr,
- PatPtr, RootExprOrigin, TypePtr,
+ PatPtr, TypePtr,
expander::Expander,
lower::generics::ImplTraitLowerFn,
path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path},
@@ -83,7 +83,7 @@ pub(super) fn lower_body(
let mut self_param = None;
let mut source_map_self_param = None;
let mut params = vec![];
- let mut collector = ExprCollector::body(db, module, current_file_id);
+ let mut collector = ExprCollector::new(db, module, current_file_id);
let skip_body = AttrFlags::query(
db,
@@ -120,8 +120,7 @@ pub(super) fn lower_body(
let count = param_list.params().filter(|it| collector.check_cfg(it)).count();
params = (0..count).map(|_| collector.missing_pat()).collect();
};
- let body_expr = collector.missing_expr();
- collector.store.inference_roots = Some(smallvec![(body_expr, RootExprOrigin::BodyRoot)]);
+ collector.with_expr_root(|collector| collector.missing_expr());
let (store, source_map) = collector.store.finish();
return (
Body { store, params: params.into_boxed_slice(), self_param },
@@ -164,24 +163,25 @@ pub(super) fn lower_body(
}
};
- let body_expr = collector.collect(
- self_param,
- &mut params,
- body,
- if is_async_fn {
- Awaitable::Yes
- } else {
- match owner {
- DefWithBodyId::FunctionId(..) => Awaitable::No("non-async function"),
- DefWithBodyId::StaticId(..) => Awaitable::No("static"),
- DefWithBodyId::ConstId(..) => Awaitable::No("constant"),
- DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
- }
- },
- is_async_fn,
- is_gen_fn,
- );
- collector.store.inference_roots = Some(smallvec![(body_expr, RootExprOrigin::BodyRoot)]);
+ collector.with_expr_root(|collector| {
+ collector.collect(
+ self_param,
+ &mut params,
+ body,
+ if is_async_fn {
+ Awaitable::Yes
+ } else {
+ match owner {
+ DefWithBodyId::FunctionId(..) => Awaitable::No("non-async function"),
+ DefWithBodyId::StaticId(..) => Awaitable::No("static"),
+ DefWithBodyId::ConstId(..) => Awaitable::No("constant"),
+ DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
+ }
+ },
+ is_async_fn,
+ is_gen_fn,
+ )
+ });
let (store, source_map) = collector.store.finish();
(
@@ -195,7 +195,7 @@ pub(crate) fn lower_type_ref(
module: ModuleId,
type_ref: InFile<Option<ast::Type>>,
) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) {
- let mut expr_collector = ExprCollector::signature(db, module, type_ref.file_id);
+ let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id);
let type_ref =
expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator);
let (store, source_map) = expr_collector.store.finish();
@@ -210,7 +210,7 @@ pub(crate) fn lower_generic_params(
param_list: Option<ast::GenericParamList>,
where_clause: Option<ast::WhereClause>,
) -> (ExpressionStore, GenericParams, ExpressionStoreSourceMap) {
- let mut expr_collector = ExprCollector::signature(db, module, file_id);
+ let mut expr_collector = ExprCollector::new(db, module, file_id);
let mut collector = generics::GenericParamsCollector::new(def);
collector.lower(&mut expr_collector, param_list, where_clause);
let params = collector.finish();
@@ -224,7 +224,7 @@ pub(crate) fn lower_impl(
impl_syntax: InFile<ast::Impl>,
impl_id: ImplId,
) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId, Option<TraitRef>, GenericParams) {
- let mut expr_collector = ExprCollector::signature(db, module, impl_syntax.file_id);
+ let mut expr_collector = ExprCollector::new(db, module, impl_syntax.file_id);
let self_ty =
expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty());
let trait_ = impl_syntax.value.trait_().and_then(|it| match &it {
@@ -252,7 +252,7 @@ pub(crate) fn lower_trait(
trait_syntax: InFile<ast::Trait>,
trait_id: TraitId,
) -> (ExpressionStore, ExpressionStoreSourceMap, GenericParams) {
- let mut expr_collector = ExprCollector::signature(db, module, trait_syntax.file_id);
+ let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
let mut collector = generics::GenericParamsCollector::with_self_param(
&mut expr_collector,
trait_id.into(),
@@ -275,7 +275,7 @@ pub(crate) fn lower_type_alias(
type_alias_id: TypeAliasId,
) -> (ExpressionStore, ExpressionStoreSourceMap, GenericParams, Box<[TypeBound]>, Option<TypeRefId>)
{
- let mut expr_collector = ExprCollector::signature(db, module, alias.file_id);
+ let mut expr_collector = ExprCollector::new(db, module, alias.file_id);
let bounds = alias
.value
.type_bound_list()
@@ -317,7 +317,7 @@ pub(crate) fn lower_function(
bool,
bool,
) {
- let mut expr_collector = ExprCollector::signature(db, module, fn_.file_id);
+ let mut expr_collector = ExprCollector::new(db, module, fn_.file_id);
let mut collector = generics::GenericParamsCollector::new(function_id.into());
collector.lower(&mut expr_collector, fn_.value.generic_param_list(), fn_.value.where_clause());
let mut params = vec![];
@@ -544,20 +544,7 @@ impl BindingList {
}
impl<'db> ExprCollector<'db> {
- /// Creates a collector for a signature store, this will populate `const_expr_origins` to any
- /// top level const arg roots.
- pub fn signature(
- db: &dyn DefDatabase,
- module: ModuleId,
- current_file_id: HirFileId,
- ) -> ExprCollector<'_> {
- let mut this = Self::body(db, module, current_file_id);
- this.store.inference_roots = Some(Default::default());
- this
- }
-
- /// Creates a collector for a bidy store.
- pub fn body(
+ pub fn new(
db: &dyn DefDatabase,
module: ModuleId,
current_file_id: HirFileId,
@@ -565,7 +552,7 @@ impl<'db> ExprCollector<'db> {
let (def_map, local_def_map) = module.local_def_map(db);
let expander = Expander::new(db, current_file_id, def_map);
let krate = module.krate(db);
- ExprCollector {
+ let mut result = ExprCollector {
db,
cfg_options: krate.cfg_options(db),
module,
@@ -583,7 +570,9 @@ impl<'db> ExprCollector<'db> {
outer_impl_trait: false,
krate,
name_generator_index: 0,
- }
+ };
+ result.store.inference_roots = Some(SmallVec::new());
+ result
}
fn generate_new_name(&mut self) -> Name {
@@ -652,9 +641,6 @@ impl<'db> ExprCollector<'db> {
}
ast::Type::ArrayType(inner) => {
let len = self.lower_const_arg_opt(inner.const_arg());
- if let Some(const_expr_origins) = &mut self.store.inference_roots {
- const_expr_origins.push((len.expr, RootExprOrigin::ArrayLength));
- }
TypeRef::Array(ArrayType {
ty: self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn),
len,
@@ -939,9 +925,6 @@ impl<'db> ExprCollector<'db> {
}
ast::GenericArg::ConstArg(arg) => {
let arg = self.lower_const_arg(arg);
- if let Some(const_expr_origins) = &mut self.store.inference_roots {
- const_expr_origins.push((arg.expr, RootExprOrigin::GenericArgsPath));
- }
args.push(GenericArg::Const(arg))
}
}
@@ -1216,17 +1199,17 @@ impl<'db> ExprCollector<'db> {
}
fn lower_const_arg_opt(&mut self, arg: Option<ast::ConstArg>) -> ConstRef {
- let const_expr_origins = self.store.inference_roots.take();
- let r = ConstRef { expr: self.collect_expr_opt(arg.and_then(|it| it.expr())) };
- self.store.inference_roots = const_expr_origins;
- r
+ ConstRef {
+ expr: self.with_fresh_binding_expr_root(|this| {
+ this.collect_expr_opt(arg.and_then(|arg| arg.expr()))
+ }),
+ }
}
pub fn lower_const_arg(&mut self, arg: ast::ConstArg) -> ConstRef {
- let const_expr_origins = self.store.inference_roots.take();
- let r = ConstRef { expr: self.collect_expr_opt(arg.expr()) };
- self.store.inference_roots = const_expr_origins;
- r
+ ConstRef {
+ expr: self.with_fresh_binding_expr_root(|this| this.collect_expr_opt(arg.expr())),
+ }
}
fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
@@ -3110,6 +3093,31 @@ fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)>
}
impl ExprCollector<'_> {
+ fn with_fresh_binding_expr_root(&mut self, f: impl FnOnce(&mut Self) -> ExprId) -> ExprId {
+ self.with_expr_root(|this| this.with_binding_owner(f))
+ }
+
+ fn with_expr_root(&mut self, f: impl FnOnce(&mut Self) -> ExprId) -> ExprId {
+ let inference_roots = self.store.inference_roots.take();
+ let root = f(self);
+ self.store.inference_roots = inference_roots;
+
+ if let Some(inference_roots) = &mut self.store.inference_roots {
+ inference_roots.push(ExprRoot {
+ root,
+ exprs_end: end(&self.store.exprs),
+ pats_end: end(&self.store.pats),
+ bindings_end: end(&self.store.bindings),
+ });
+ }
+
+ return root;
+
+ fn end<T>(arena: &la_arena::Arena<T>) -> la_arena::Idx<T> {
+ la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(arena.len() as u32))
+ }
+ }
+
fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
let src = self.expander.in_file(ptr);
let id = self.store.exprs.alloc(expr);