From 83d7724629c3ea1800f36be28dadead5d604fcd1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 18 Jun 2023 11:41:20 +0200 Subject: [PATCH] fix: Add binding definition for for-expr iterator desugared binding --- crates/hir-def/src/body/lower.rs | 46 +++++++++---------- crates/hir/src/lib.rs | 25 ++++++---- .../rust-analyzer/src/cli/analysis_stats.rs | 6 ++- 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 71b42f31a2..53b80a17df 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 = 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, 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, 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 9876503d03..6df625380f 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 { 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 + '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 01bc0d77dd..4cb917ce29 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());