From ebbcf9f458522e76c5a84e6771e0ef434d6d5c5b Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Wed, 7 Apr 2021 12:45:17 +0100 Subject: Fix inference with conditionally compiled tails Fixes #8378 --- crates/hir_def/src/body/lower.rs | 24 +++++++++++++++++------- crates/hir_def/src/body/scope.rs | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'crates/hir_def/src/body') 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<'_> { self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr()) } - /// Returns `None` if the expression is `#[cfg]`d out. + /// Returns `None` if and only if the expression is `#[cfg]`d out. fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option { let syntax_ptr = AstPtr::new(&expr); self.check_cfg(&expr)?; @@ -665,7 +665,7 @@ impl ExprCollector<'_> { if self.check_cfg(&stmt).is_none() { return; } - + let has_semi = stmt.semicolon_token().is_some(); // Note that macro could be expended to multiple statements if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { let macro_ptr = AstPtr::new(&m); @@ -682,18 +682,19 @@ impl ExprCollector<'_> { statements.statements().for_each(|stmt| this.collect_stmt(stmt)); if let Some(expr) = statements.expr() { let expr = this.collect_expr(expr); - this.statements_in_scope.push(Statement::Expr(expr)); + this.statements_in_scope + .push(Statement::Expr { expr, has_semi }); } } None => { let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); - this.statements_in_scope.push(Statement::Expr(expr)); + this.statements_in_scope.push(Statement::Expr { expr, has_semi }); } }, ); } else { let expr = self.collect_expr_opt(stmt.expr()); - self.statements_in_scope.push(Statement::Expr(expr)); + self.statements_in_scope.push(Statement::Expr { expr, has_semi }); } } ast::Stmt::Item(item) => { @@ -722,8 +723,17 @@ impl ExprCollector<'_> { let prev_statements = std::mem::take(&mut self.statements_in_scope); block.statements().for_each(|s| self.collect_stmt(s)); - - let tail = block.tail_expr().map(|e| self.collect_expr(e)); + block.tail_expr().and_then(|e| { + let expr = self.maybe_collect_expr(e)?; + Some(self.statements_in_scope.push(Statement::Expr { expr, has_semi: false })) + }); + + let mut tail = None; + if let Some(Statement::Expr { expr, has_semi: false }) = self.statements_in_scope.last() { + tail = Some(*expr); + self.statements_in_scope.pop(); + } + let tail = tail; let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); let syntax_node_ptr = AstPtr::new(&block.into()); 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( scope = scopes.new_scope(scope); scopes.add_bindings(body, scope, *pat); } - Statement::Expr(expr) => { + Statement::Expr { expr, .. } => { scopes.set_scope(*expr, scope); compute_expr_scopes(*expr, body, scopes, scope); } -- cgit v1.2.3