aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorDaniel McNab <[email protected]>2021-04-07 12:45:17 +0100
committerDaniel McNab <[email protected]>2021-05-03 14:13:05 +0100
commitebbcf9f458522e76c5a84e6771e0ef434d6d5c5b (patch)
tree05b4684b1b23a5159796d424b511d30e7e651df5 /crates
parenteb741e895f1a73420a401f2495c711afe37d9d19 (diff)
Fix inference with conditionally compiled tails
Fixes #8378
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/body/lower.rs24
-rw-r--r--crates/hir_def/src/body/scope.rs2
-rw-r--r--crates/hir_def/src/expr.rs4
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs2
-rw-r--r--crates/hir_ty/src/infer/expr.rs2
5 files changed, 22 insertions, 12 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 }
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index b4ad984bd..0c3b41080 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -242,7 +242,7 @@ pub struct RecordLitField {
242#[derive(Debug, Clone, Eq, PartialEq)] 242#[derive(Debug, Clone, Eq, PartialEq)]
243pub enum Statement { 243pub enum Statement {
244 Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> }, 244 Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> },
245 Expr(ExprId), 245 Expr { expr: ExprId, has_semi: bool },
246} 246}
247 247
248impl Expr { 248impl Expr {
@@ -265,7 +265,7 @@ impl Expr {
265 f(*expr); 265 f(*expr);
266 } 266 }
267 } 267 }
268 Statement::Expr(e) => f(*e), 268 Statement::Expr { expr: expression, .. } => f(*expression),
269 } 269 }
270 } 270 }
271 if let Some(expr) = tail { 271 if let Some(expr) = tail {
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 79602c3dd..47709c1e8 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -83,7 +83,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
83 if let Expr::Block { statements, tail, .. } = body_expr { 83 if let Expr::Block { statements, tail, .. } = body_expr {
84 if let Some(t) = tail { 84 if let Some(t) = tail {
85 self.validate_results_in_tail_expr(body.body_expr, *t, db); 85 self.validate_results_in_tail_expr(body.body_expr, *t, db);
86 } else if let Some(Statement::Expr(id)) = statements.last() { 86 } else if let Some(Statement::Expr { expr: id, .. }) = statements.last() {
87 self.validate_missing_tail_expr(body.body_expr, *id, db); 87 self.validate_missing_tail_expr(body.body_expr, *id, db);
88 } 88 }
89 } 89 }
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 50497eecb..9476e6297 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -809,7 +809,7 @@ impl<'a> InferenceContext<'a> {
809 let ty = self.resolve_ty_as_possible(ty); 809 let ty = self.resolve_ty_as_possible(ty);
810 self.infer_pat(*pat, &ty, BindingMode::default()); 810 self.infer_pat(*pat, &ty, BindingMode::default());
811 } 811 }
812 Statement::Expr(expr) => { 812 Statement::Expr { expr, .. } => {
813 self.infer_expr(*expr, &Expectation::none()); 813 self.infer_expr(*expr, &Expectation::none());
814 } 814 }
815 } 815 }