Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions crates/hir_def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ExprId> {
let syntax_ptr = AstPtr::new(&expr);
self.check_cfg(&expr)?;
Expand Down Expand Up @@ -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);
Expand All @@ -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) => {
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion crates/hir_def/src/body/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions crates/hir_def/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ pub struct RecordLitField {
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Statement {
Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> },
Expr(ExprId),
Expr { expr: ExprId, has_semi: bool },
}

impl Expr {
Expand All @@ -265,7 +265,7 @@ impl Expr {
f(*expr);
}
}
Statement::Expr(e) => f(*e),
Statement::Expr { expr: expression, .. } => f(*expression),
}
}
if let Some(expr) = tail {
Expand Down
2 changes: 1 addition & 1 deletion crates/hir_ty/src/diagnostics/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
if let Expr::Block { statements, tail, .. } = body_expr {
if let Some(t) = tail {
self.validate_results_in_tail_expr(body.body_expr, *t, db);
} else if let Some(Statement::Expr(id)) = statements.last() {
} else if let Some(Statement::Expr { expr: id, .. }) = statements.last() {
self.validate_missing_tail_expr(body.body_expr, *id, db);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/hir_ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ impl<'a> InferenceContext<'a> {
let ty = self.resolve_ty_as_possible(ty);
self.infer_pat(*pat, &ty, BindingMode::default());
}
Statement::Expr(expr) => {
Statement::Expr { expr, .. } => {
self.infer_expr(*expr, &Expectation::none());
}
}
Expand Down
49 changes: 49 additions & 0 deletions crates/hir_ty/src/tests/regression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1050,3 +1050,52 @@ fn test() {
"#]],
);
}

#[test]
fn cfg_tail() {
// https://github.com/rust-analyzer/rust-analyzer/issues/8378
check_infer(
r#"
fn fake_tail(){
{ "first" }
#[cfg(never)] 9
}
fn multiple_fake(){
{ "fake" }
{ "fake" }
{ "second" }
#[cfg(never)] { 11 }
#[cfg(never)] 12;
#[cfg(never)] 13
}
fn no_normal_tail(){
{ "third" }
#[cfg(never)] 14;
#[cfg(never)] 15;
}
fn no_actual_tail(){
{ "fourth" };
#[cfg(never)] 14;
#[cfg(never)] 15
}
"#,
expect![[r#"
14..53 '{ ...)] 9 }': &str
20..31 '{ "first" }': &str
22..29 '"first"': &str
72..190 '{ ...] 13 }': &str
78..88 '{ "fake" }': &str
80..86 '"fake"': &str
93..103 '{ "fake" }': &str
95..101 '"fake"': &str
108..120 '{ "second" }': &str
110..118 '"second"': &str
210..273 '{ ... 15; }': &str
216..227 '{ "third" }': &str
218..225 '"third"': &str
293..357 '{ ...] 15 }': ()
299..311 '{ "fourth" }': &str
301..309 '"fourth"': &str
"#]],
)
}