diff options
author | Daniel McNab <[email protected]> | 2021-04-07 12:45:17 +0100 |
---|---|---|
committer | Daniel McNab <[email protected]> | 2021-05-03 14:13:05 +0100 |
commit | ebbcf9f458522e76c5a84e6771e0ef434d6d5c5b (patch) | |
tree | 05b4684b1b23a5159796d424b511d30e7e651df5 /crates/hir_def/src/body | |
parent | eb741e895f1a73420a401f2495c711afe37d9d19 (diff) |
Fix inference with conditionally compiled tails
Fixes #8378
Diffstat (limited to 'crates/hir_def/src/body')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 24 | ||||
-rw-r--r-- | crates/hir_def/src/body/scope.rs | 2 |
2 files changed, 18 insertions, 8 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index c11da30d2..820d5c17e 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -203,7 +203,7 @@ impl ExprCollector<'_> { | |||
203 | self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr()) | 203 | self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr()) |
204 | } | 204 | } |
205 | 205 | ||
206 | /// Returns `None` if the expression is `#[cfg]`d out. | 206 | /// Returns `None` if and only if the expression is `#[cfg]`d out. |
207 | fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> { | 207 | fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> { |
208 | let syntax_ptr = AstPtr::new(&expr); | 208 | let syntax_ptr = AstPtr::new(&expr); |
209 | self.check_cfg(&expr)?; | 209 | self.check_cfg(&expr)?; |
@@ -665,7 +665,7 @@ impl ExprCollector<'_> { | |||
665 | if self.check_cfg(&stmt).is_none() { | 665 | if self.check_cfg(&stmt).is_none() { |
666 | return; | 666 | return; |
667 | } | 667 | } |
668 | 668 | let has_semi = stmt.semicolon_token().is_some(); | |
669 | // Note that macro could be expended to multiple statements | 669 | // Note that macro could be expended to multiple statements |
670 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { | 670 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { |
671 | let macro_ptr = AstPtr::new(&m); | 671 | let macro_ptr = AstPtr::new(&m); |
@@ -682,18 +682,19 @@ impl ExprCollector<'_> { | |||
682 | statements.statements().for_each(|stmt| this.collect_stmt(stmt)); | 682 | statements.statements().for_each(|stmt| this.collect_stmt(stmt)); |
683 | if let Some(expr) = statements.expr() { | 683 | if let Some(expr) = statements.expr() { |
684 | let expr = this.collect_expr(expr); | 684 | let expr = this.collect_expr(expr); |
685 | this.statements_in_scope.push(Statement::Expr(expr)); | 685 | this.statements_in_scope |
686 | .push(Statement::Expr { expr, has_semi }); | ||
686 | } | 687 | } |
687 | } | 688 | } |
688 | None => { | 689 | None => { |
689 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); | 690 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); |
690 | this.statements_in_scope.push(Statement::Expr(expr)); | 691 | this.statements_in_scope.push(Statement::Expr { expr, has_semi }); |
691 | } | 692 | } |
692 | }, | 693 | }, |
693 | ); | 694 | ); |
694 | } else { | 695 | } else { |
695 | let expr = self.collect_expr_opt(stmt.expr()); | 696 | let expr = self.collect_expr_opt(stmt.expr()); |
696 | self.statements_in_scope.push(Statement::Expr(expr)); | 697 | self.statements_in_scope.push(Statement::Expr { expr, has_semi }); |
697 | } | 698 | } |
698 | } | 699 | } |
699 | ast::Stmt::Item(item) => { | 700 | ast::Stmt::Item(item) => { |
@@ -722,8 +723,17 @@ impl ExprCollector<'_> { | |||
722 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | 723 | let prev_statements = std::mem::take(&mut self.statements_in_scope); |
723 | 724 | ||
724 | block.statements().for_each(|s| self.collect_stmt(s)); | 725 | block.statements().for_each(|s| self.collect_stmt(s)); |
725 | 726 | block.tail_expr().and_then(|e| { | |
726 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); | 727 | let expr = self.maybe_collect_expr(e)?; |
728 | Some(self.statements_in_scope.push(Statement::Expr { expr, has_semi: false })) | ||
729 | }); | ||
730 | |||
731 | let mut tail = None; | ||
732 | if let Some(Statement::Expr { expr, has_semi: false }) = self.statements_in_scope.last() { | ||
733 | tail = Some(*expr); | ||
734 | self.statements_in_scope.pop(); | ||
735 | } | ||
736 | let tail = tail; | ||
727 | let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); | 737 | let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); |
728 | let syntax_node_ptr = AstPtr::new(&block.into()); | 738 | let syntax_node_ptr = AstPtr::new(&block.into()); |
729 | let expr_id = self.alloc_expr( | 739 | let expr_id = self.alloc_expr( |
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index bd7005ca6..6764de3a7 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -157,7 +157,7 @@ fn compute_block_scopes( | |||
157 | scope = scopes.new_scope(scope); | 157 | scope = scopes.new_scope(scope); |
158 | scopes.add_bindings(body, scope, *pat); | 158 | scopes.add_bindings(body, scope, *pat); |
159 | } | 159 | } |
160 | Statement::Expr(expr) => { | 160 | Statement::Expr { expr, .. } => { |
161 | scopes.set_scope(*expr, scope); | 161 | scopes.set_scope(*expr, scope); |
162 | compute_expr_scopes(*expr, body, scopes, scope); | 162 | compute_expr_scopes(*expr, body, scopes, scope); |
163 | } | 163 | } |