Skip to content

Commit da80dfc

Browse files
bors[bot]DJMcNab
andauthored
Merge #8398
8398: Fix inference with conditionally compiled tails r=flodiebold a=DJMcNab Fixes #8378 Co-authored-by: Daniel McNab <[email protected]>
2 parents e290891 + 11c926f commit da80dfc

File tree

6 files changed

+71
-12
lines changed

6 files changed

+71
-12
lines changed

crates/hir_def/src/body/lower.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ impl ExprCollector<'_> {
205205
self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
206206
}
207207

208-
/// Returns `None` if the expression is `#[cfg]`d out.
208+
/// Returns `None` if and only if the expression is `#[cfg]`d out.
209209
fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
210210
let syntax_ptr = AstPtr::new(&expr);
211211
self.check_cfg(&expr)?;
@@ -668,7 +668,7 @@ impl ExprCollector<'_> {
668668
if self.check_cfg(&stmt).is_none() {
669669
return;
670670
}
671-
671+
let has_semi = stmt.semicolon_token().is_some();
672672
// Note that macro could be expended to multiple statements
673673
if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
674674
let macro_ptr = AstPtr::new(&m);
@@ -685,18 +685,19 @@ impl ExprCollector<'_> {
685685
statements.statements().for_each(|stmt| this.collect_stmt(stmt));
686686
if let Some(expr) = statements.expr() {
687687
let expr = this.collect_expr(expr);
688-
this.statements_in_scope.push(Statement::Expr(expr));
688+
this.statements_in_scope
689+
.push(Statement::Expr { expr, has_semi });
689690
}
690691
}
691692
None => {
692693
let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
693-
this.statements_in_scope.push(Statement::Expr(expr));
694+
this.statements_in_scope.push(Statement::Expr { expr, has_semi });
694695
}
695696
},
696697
);
697698
} else {
698699
let expr = self.collect_expr_opt(stmt.expr());
699-
self.statements_in_scope.push(Statement::Expr(expr));
700+
self.statements_in_scope.push(Statement::Expr { expr, has_semi });
700701
}
701702
}
702703
ast::Stmt::Item(item) => {
@@ -725,8 +726,17 @@ impl ExprCollector<'_> {
725726
let prev_statements = std::mem::take(&mut self.statements_in_scope);
726727

727728
block.statements().for_each(|s| self.collect_stmt(s));
728-
729-
let tail = block.tail_expr().map(|e| self.collect_expr(e));
729+
block.tail_expr().and_then(|e| {
730+
let expr = self.maybe_collect_expr(e)?;
731+
Some(self.statements_in_scope.push(Statement::Expr { expr, has_semi: false }))
732+
});
733+
734+
let mut tail = None;
735+
if let Some(Statement::Expr { expr, has_semi: false }) = self.statements_in_scope.last() {
736+
tail = Some(*expr);
737+
self.statements_in_scope.pop();
738+
}
739+
let tail = tail;
730740
let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements);
731741
let syntax_node_ptr = AstPtr::new(&block.into());
732742
let expr_id = self.alloc_expr(

crates/hir_def/src/body/scope.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ fn compute_block_scopes(
157157
scope = scopes.new_scope(scope);
158158
scopes.add_bindings(body, scope, *pat);
159159
}
160-
Statement::Expr(expr) => {
160+
Statement::Expr { expr, .. } => {
161161
scopes.set_scope(*expr, scope);
162162
compute_expr_scopes(*expr, body, scopes, scope);
163163
}

crates/hir_def/src/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ pub struct RecordLitField {
242242
#[derive(Debug, Clone, Eq, PartialEq)]
243243
pub enum Statement {
244244
Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> },
245-
Expr(ExprId),
245+
Expr { expr: ExprId, has_semi: bool },
246246
}
247247

248248
impl Expr {
@@ -265,7 +265,7 @@ impl Expr {
265265
f(*expr);
266266
}
267267
}
268-
Statement::Expr(e) => f(*e),
268+
Statement::Expr { expr: expression, .. } => f(*expression),
269269
}
270270
}
271271
if let Some(expr) = tail {

crates/hir_ty/src/diagnostics/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
8383
if let Expr::Block { statements, tail, .. } = body_expr {
8484
if let Some(t) = tail {
8585
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() {
8787
self.validate_missing_tail_expr(body.body_expr, *id, db);
8888
}
8989
}

crates/hir_ty/src/infer/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ impl<'a> InferenceContext<'a> {
809809
let ty = self.resolve_ty_as_possible(ty);
810810
self.infer_pat(*pat, &ty, BindingMode::default());
811811
}
812-
Statement::Expr(expr) => {
812+
Statement::Expr { expr, .. } => {
813813
self.infer_expr(*expr, &Expectation::none());
814814
}
815815
}

crates/hir_ty/src/tests/regression.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,3 +1050,52 @@ fn test() {
10501050
"#]],
10511051
);
10521052
}
1053+
1054+
#[test]
1055+
fn cfg_tail() {
1056+
// https://github.com/rust-analyzer/rust-analyzer/issues/8378
1057+
check_infer(
1058+
r#"
1059+
fn fake_tail(){
1060+
{ "first" }
1061+
#[cfg(never)] 9
1062+
}
1063+
fn multiple_fake(){
1064+
{ "fake" }
1065+
{ "fake" }
1066+
{ "second" }
1067+
#[cfg(never)] { 11 }
1068+
#[cfg(never)] 12;
1069+
#[cfg(never)] 13
1070+
}
1071+
fn no_normal_tail(){
1072+
{ "third" }
1073+
#[cfg(never)] 14;
1074+
#[cfg(never)] 15;
1075+
}
1076+
fn no_actual_tail(){
1077+
{ "fourth" };
1078+
#[cfg(never)] 14;
1079+
#[cfg(never)] 15
1080+
}
1081+
"#,
1082+
expect![[r#"
1083+
14..53 '{ ...)] 9 }': &str
1084+
20..31 '{ "first" }': &str
1085+
22..29 '"first"': &str
1086+
72..190 '{ ...] 13 }': &str
1087+
78..88 '{ "fake" }': &str
1088+
80..86 '"fake"': &str
1089+
93..103 '{ "fake" }': &str
1090+
95..101 '"fake"': &str
1091+
108..120 '{ "second" }': &str
1092+
110..118 '"second"': &str
1093+
210..273 '{ ... 15; }': &str
1094+
216..227 '{ "third" }': &str
1095+
218..225 '"third"': &str
1096+
293..357 '{ ...] 15 }': ()
1097+
299..311 '{ "fourth" }': &str
1098+
301..309 '"fourth"': &str
1099+
"#]],
1100+
)
1101+
}

0 commit comments

Comments
 (0)