about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-01-25 14:43:22 +0100
committerLukas Wirth <lukastw97@gmail.com>2025-01-25 14:43:22 +0100
commit8e7a3381650dd7fc86354649a856163bcbceea52 (patch)
tree345ebb8dbbe74941474ef0b8bd3ed5a158fd7e0f
parentb46775a5f4e48ea740fd34f9d69bc5bce05cb88e (diff)
BodyCollector
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs112
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs49
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir.rs7
3 files changed, 91 insertions, 77 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index 139e1ba896c..334177751e4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -25,8 +25,8 @@ use crate::{
     db::DefDatabase,
     expander::Expander,
     hir::{
-        dummy_expr_id, Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label,
-        LabelId, Pat, PatId, RecordFieldPat, Statement,
+        Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat,
+        PatId, RecordFieldPat, Statement,
     },
     item_tree::AttrOwner,
     nameres::DefMap,
@@ -81,7 +81,7 @@ pub struct Body {
     pub body_expr: ExprId,
     pub types: TypesMap,
     /// Block expressions in this body that may contain inner items.
-    block_scopes: Vec<BlockId>,
+    block_scopes: Box<[BlockId]>,
 
     /// A map from binding to its hygiene ID.
     ///
@@ -98,6 +98,64 @@ pub struct Body {
     ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
 }
 
+/// The body of an item (function, const etc.).
+#[derive(Debug, Eq, PartialEq, Default)]
+pub struct BodyCollector {
+    pub exprs: Arena<Expr>,
+    pub pats: Arena<Pat>,
+    pub bindings: Arena<Binding>,
+    pub labels: Arena<Label>,
+    pub binding_owners: FxHashMap<BindingId, ExprId>,
+    pub types: TypesMap,
+    block_scopes: Vec<BlockId>,
+    binding_hygiene: FxHashMap<BindingId, HygieneId>,
+    ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
+}
+
+impl BodyCollector {
+    fn finish(
+        self,
+        body_expr: ExprId,
+        self_param: Option<BindingId>,
+        params: Box<[PatId]>,
+    ) -> Body {
+        let Self {
+            block_scopes,
+            mut exprs,
+            mut labels,
+            mut pats,
+            mut bindings,
+            mut binding_owners,
+            mut binding_hygiene,
+            mut ident_hygiene,
+            mut types,
+        } = self;
+        exprs.shrink_to_fit();
+        labels.shrink_to_fit();
+        pats.shrink_to_fit();
+        bindings.shrink_to_fit();
+        binding_owners.shrink_to_fit();
+        binding_hygiene.shrink_to_fit();
+        ident_hygiene.shrink_to_fit();
+        types.shrink_to_fit();
+
+        Body {
+            exprs,
+            pats,
+            bindings,
+            labels,
+            binding_owners,
+            params,
+            self_param,
+            body_expr,
+            types,
+            block_scopes: block_scopes.into_boxed_slice(),
+            binding_hygiene,
+            ident_hygiene,
+        }
+    }
+}
+
 pub type ExprPtr = AstPtr<ast::Expr>;
 pub type ExprSource = InFile<ExprPtr>;
 
@@ -242,9 +300,8 @@ impl Body {
         };
         let module = def.module(db);
         let expander = Expander::new(db, file_id, module);
-        let (mut body, mut source_map) =
+        let (body, mut source_map) =
             Body::new(db, def, expander, params, body, module.krate, is_async_fn);
-        body.shrink_to_fit();
         source_map.shrink_to_fit();
 
         (Arc::new(body), Arc::new(source_map))
@@ -304,32 +361,6 @@ impl Body {
         lower::lower(db, owner, expander, params, body, krate, is_async_fn)
     }
 
-    fn shrink_to_fit(&mut self) {
-        let Self {
-            body_expr: _,
-            params: _,
-            self_param: _,
-            block_scopes,
-            exprs,
-            labels,
-            pats,
-            bindings,
-            binding_owners,
-            binding_hygiene,
-            ident_hygiene,
-            types,
-        } = self;
-        block_scopes.shrink_to_fit();
-        exprs.shrink_to_fit();
-        labels.shrink_to_fit();
-        pats.shrink_to_fit();
-        bindings.shrink_to_fit();
-        binding_owners.shrink_to_fit();
-        binding_hygiene.shrink_to_fit();
-        ident_hygiene.shrink_to_fit();
-        types.shrink_to_fit();
-    }
-
     pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
         self.walk_pats(pat_id, &mut |pat| {
             if let Pat::Bind { id, .. } = &self[pat] {
@@ -670,25 +701,6 @@ impl Body {
     }
 }
 
-impl Default for Body {
-    fn default() -> Self {
-        Self {
-            body_expr: dummy_expr_id(),
-            exprs: Default::default(),
-            pats: Default::default(),
-            bindings: Default::default(),
-            labels: Default::default(),
-            params: Default::default(),
-            block_scopes: Default::default(),
-            binding_owners: Default::default(),
-            self_param: Default::default(),
-            binding_hygiene: Default::default(),
-            ident_hygiene: Default::default(),
-            types: Default::default(),
-        }
-    }
-}
-
 impl Index<ExprId> for Body {
     type Output = Expr;
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 583c6ac5e8c..2b25dbdd7f2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -29,7 +29,9 @@ use triomphe::Arc;
 
 use crate::{
     attr::Attrs,
-    body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr},
+    body::{
+        Body, BodyCollector, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr,
+    },
     builtin_type::BuiltinUint,
     data::adt::StructKind,
     db::DefDatabase,
@@ -82,7 +84,7 @@ pub(super) fn lower(
         def_map: expander.module.def_map(db),
         source_map: BodySourceMap::default(),
         ast_id_map: db.ast_id_map(expander.current_file_id()),
-        body: Body::default(),
+        body: BodyCollector::default(),
         expander,
         current_try_block_label: None,
         is_lowering_coroutine: false,
@@ -102,7 +104,7 @@ struct ExprCollector<'a> {
     def_map: Arc<DefMap>,
     ast_id_map: Arc<AstIdMap>,
     krate: CrateId,
-    body: Body,
+    body: BodyCollector,
     source_map: BodySourceMap,
 
     is_lowering_coroutine: bool,
@@ -214,6 +216,9 @@ impl ExprCollector<'_> {
         body: Option<ast::Expr>,
         is_async_fn: bool,
     ) -> (Body, BodySourceMap) {
+        let mut self_param = None;
+        let mut params = vec![];
+
         let skip_body = match self.owner {
             DefWithBodyId::FunctionId(it) => self.db.attrs(it.into()),
             DefWithBodyId::StaticId(it) => self.db.attrs(it.into()),
@@ -226,29 +231,32 @@ impl ExprCollector<'_> {
         // If #[rust_analyzer::skip] annotated, only construct enough information for the signature
         // and skip the body.
         if skip_body {
-            self.body.body_expr = self.missing_expr();
             if let Some((param_list, mut attr_enabled)) = param_list {
-                if let Some(self_param) =
+                if let Some(self_param_syn) =
                     param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
                 {
-                    let is_mutable =
-                        self_param.mut_token().is_some() && self_param.amp_token().is_none();
+                    let is_mutable = self_param_syn.mut_token().is_some()
+                        && self_param_syn.amp_token().is_none();
                     let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
                         Name::new_symbol_root(sym::self_.clone()),
                         BindingAnnotation::new(is_mutable, false),
                     );
-                    self.body.self_param = Some(binding_id);
+                    self_param = Some(binding_id);
                     self.source_map.self_param =
-                        Some(self.expander.in_file(AstPtr::new(&self_param)));
+                        Some(self.expander.in_file(AstPtr::new(&self_param_syn)));
                 }
-                self.body.params = param_list
+                params = param_list
                     .params()
                     .zip(attr_enabled)
                     .filter(|(_, enabled)| *enabled)
                     .map(|_| self.missing_pat())
                     .collect();
             };
-            return (self.body, self.source_map);
+            let body_expr = self.missing_expr();
+            return (
+                self.body.finish(body_expr, self_param, params.into_boxed_slice()),
+                self.source_map,
+            );
         }
 
         self.awaitable_context.replace(if is_async_fn {
@@ -264,25 +272,25 @@ impl ExprCollector<'_> {
             }
         });
         if let Some((param_list, mut attr_enabled)) = param_list {
-            let mut params = vec![];
-            if let Some(self_param) =
+            if let Some(self_param_syn) =
                 param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
             {
                 let is_mutable =
-                    self_param.mut_token().is_some() && self_param.amp_token().is_none();
+                    self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
                 let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
                     Name::new_symbol_root(sym::self_.clone()),
                     BindingAnnotation::new(is_mutable, false),
                 );
-                let hygiene = self_param
+                let hygiene = self_param_syn
                     .name()
                     .map(|name| self.hygiene_id_for(name.syntax().text_range().start()))
                     .unwrap_or(HygieneId::ROOT);
                 if !hygiene.is_root() {
                     self.body.binding_hygiene.insert(binding_id, hygiene);
                 }
-                self.body.self_param = Some(binding_id);
-                self.source_map.self_param = Some(self.expander.in_file(AstPtr::new(&self_param)));
+                self_param = Some(binding_id);
+                self.source_map.self_param =
+                    Some(self.expander.in_file(AstPtr::new(&self_param_syn)));
             }
 
             for (param, _) in param_list.params().zip(attr_enabled).filter(|(_, enabled)| *enabled)
@@ -290,9 +298,8 @@ impl ExprCollector<'_> {
                 let param_pat = self.collect_pat_top(param.pat());
                 params.push(param_pat);
             }
-            self.body.params = params.into_boxed_slice();
         };
-        self.body.body_expr = self.with_label_rib(RibKind::Closure, |this| {
+        let body_expr = self.with_label_rib(RibKind::Closure, |this| {
             if is_async_fn {
                 match body {
                     Some(e) => {
@@ -310,7 +317,7 @@ impl ExprCollector<'_> {
             }
         });
 
-        (self.body, self.source_map)
+        (self.body.finish(body_expr, self_param, params.into_boxed_slice()), self.source_map)
     }
 
     fn ctx(&mut self) -> LowerCtx<'_> {
@@ -1934,7 +1941,7 @@ impl ExprCollector<'_> {
         f: impl FnOnce(&mut Self) -> T,
     ) -> T {
         self.label_ribs.push(LabelRib::new(RibKind::Normal(
-            self.body[label].name.clone(),
+            self.body.labels[label].name.clone(),
             label,
             hygiene,
         )));
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
index 9392e8d12d4..0dcddf162b2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
@@ -19,7 +19,7 @@ use std::fmt;
 
 use hir_expand::{name::Name, MacroDefId};
 use intern::Symbol;
-use la_arena::{Idx, RawIdx};
+use la_arena::Idx;
 use rustc_apfloat::ieee::{Half as f16, Quad as f128};
 use syntax::ast;
 use type_ref::TypeRefId;
@@ -37,11 +37,6 @@ pub type BindingId = Idx<Binding>;
 
 pub type ExprId = Idx<Expr>;
 
-/// FIXME: this is a hacky function which should be removed
-pub(crate) fn dummy_expr_id() -> ExprId {
-    ExprId::from_raw(RawIdx::from(u32::MAX))
-}
-
 pub type PatId = Idx<Pat>;
 
 // FIXME: Encode this as a single u32, we won't ever reach all 32 bits especially given these counts