about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-06-18 11:41:20 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-06-18 11:44:01 +0200
commit83d7724629c3ea1800f36be28dadead5d604fcd1 (patch)
tree08daa2d5c45081017a84498c51c07974161e54e5
parentfcfc6afe0526123ff43086990356bf175664fdfa (diff)
downloadrust-83d7724629c3ea1800f36be28dadead5d604fcd1.tar.gz
rust-83d7724629c3ea1800f36be28dadead5d604fcd1.zip
fix: Add binding definition for for-expr iterator desugared binding
-rw-r--r--crates/hir-def/src/body/lower.rs46
-rw-r--r--crates/hir/src/lib.rs25
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs6
3 files changed, 42 insertions, 35 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index 71b42f31a24..53b80a17df1 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -188,7 +188,7 @@ impl ExprCollector<'_> {
                 param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
             {
                 let ptr = AstPtr::new(&self_param);
-                let binding_id = self.alloc_binding(
+                let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
                     name![self],
                     BindingAnnotation::new(
                         self_param.mut_token().is_some() && self_param.amp_token().is_none(),
@@ -745,16 +745,14 @@ impl ExprCollector<'_> {
     /// }
     /// ```
     fn collect_for_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::ForExpr) -> ExprId {
-        let (into_iter_fn, iter_next_fn, option_some, option_none) = 'if_chain: {
-            if let Some(into_iter_fn) = LangItem::IntoIterIntoIter.path(self.db, self.krate) {
-                if let Some(iter_next_fn) = LangItem::IteratorNext.path(self.db, self.krate) {
-                    if let Some(option_some) = LangItem::OptionSome.path(self.db, self.krate) {
-                        if let Some(option_none) = LangItem::OptionNone.path(self.db, self.krate) {
-                            break 'if_chain (into_iter_fn, iter_next_fn, option_some, option_none);
-                        }
-                    }
-                }
-            }
+        let Some((into_iter_fn, iter_next_fn, option_some, option_none)) = (|| {
+            Some((
+                LangItem::IntoIterIntoIter.path(self.db, self.krate)?,
+                LangItem::IteratorNext.path(self.db, self.krate)?,
+                LangItem::OptionSome.path(self.db, self.krate)?,
+                LangItem::OptionNone.path(self.db, self.krate)?,
+            ))
+        })() else {
             // Some of the needed lang items are missing, so we can't desugar
             return self.alloc_expr(Expr::Missing, syntax_ptr);
         };
@@ -787,8 +785,8 @@ impl ExprCollector<'_> {
             }),
         };
         let iter_name = Name::generate_new_name();
-        let iter_binding = self.alloc_binding(iter_name.clone(), BindingAnnotation::Mutable);
-        let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name)), syntax_ptr.clone());
+        let iter_expr =
+            self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr.clone());
         let iter_expr_mut = self.alloc_expr(
             Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
             syntax_ptr.clone(),
@@ -808,7 +806,9 @@ impl ExprCollector<'_> {
         );
         let loop_outer =
             self.alloc_expr(Expr::Loop { body: loop_inner, label }, syntax_ptr.clone());
+        let iter_binding = self.alloc_binding(iter_name, BindingAnnotation::Mutable);
         let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None });
+        self.add_definition_to_binding(iter_binding, iter_pat);
         self.alloc_expr(
             Expr::Match {
                 expr: iterator,
@@ -830,18 +830,14 @@ impl ExprCollector<'_> {
     /// }
     /// ```
     fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExpr) -> ExprId {
-        let (try_branch, cf_continue, cf_break, try_from_residual) = 'if_chain: {
-            if let Some(try_branch) = LangItem::TryTraitBranch.path(self.db, self.krate) {
-                if let Some(cf_continue) = LangItem::ControlFlowContinue.path(self.db, self.krate) {
-                    if let Some(cf_break) = LangItem::ControlFlowBreak.path(self.db, self.krate) {
-                        if let Some(try_from_residual) =
-                            LangItem::TryTraitFromResidual.path(self.db, self.krate)
-                        {
-                            break 'if_chain (try_branch, cf_continue, cf_break, try_from_residual);
-                        }
-                    }
-                }
-            }
+        let Some((try_branch, cf_continue, cf_break, try_from_residual)) = (|| {
+            Some((
+                LangItem::TryTraitBranch.path(self.db, self.krate)?,
+                LangItem::ControlFlowContinue.path(self.db, self.krate)?,
+                LangItem::ControlFlowBreak.path(self.db, self.krate)?,
+                LangItem::TryTraitFromResidual.path(self.db, self.krate)?,
+            ))
+        })() else {
             // Some of the needed lang items are missing, so we can't desugar
             return self.alloc_expr(Expr::Missing, syntax_ptr);
         };
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9876503d031..6df625380ff 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2800,6 +2800,22 @@ impl Local {
     /// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = x;`
     pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
         let (body, source_map) = db.body_with_source_map(self.parent);
+        self.sources_(db, &body, &source_map).collect()
+    }
+
+    /// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = x;`
+    pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
+        let (body, source_map) = db.body_with_source_map(self.parent);
+        let src = self.sources_(db, &body, &source_map).next().unwrap();
+        src
+    }
+
+    fn sources_<'a>(
+        self,
+        db: &'a dyn HirDatabase,
+        body: &'a hir_def::body::Body,
+        source_map: &'a hir_def::body::BodySourceMap,
+    ) -> impl Iterator<Item = LocalSource> + 'a {
         body[self.binding_id]
             .definitions
             .iter()
@@ -2812,14 +2828,7 @@ impl Local {
                     Either::Right(it) => Either::Right(it.to_node(&root)),
                 })
             })
-            .map(|source| LocalSource { local: self, source })
-            .collect()
-    }
-
-    /// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = x;`
-    pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
-        let all_sources = self.sources(db);
-        all_sources.into_iter().next().unwrap()
+            .map(move |source| LocalSource { local: self, source })
     }
 }
 
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 01bc0d77dd5..4cb917ce290 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -165,9 +165,11 @@ impl flags::AnalysisStats {
             }
         }
         eprintln!(
-            ", mods: {}, decls: {num_decls}, bodies: {}",
+            ", mods: {}, decls: {num_decls}, bodies: {}, adts: {}, consts: {}",
             visited_modules.len(),
-            bodies.len()
+            bodies.len(),
+            adts.len(),
+            consts.len(),
         );
         eprintln!("{:<20} {}", "Item Collection:", analysis_sw.elapsed());