diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 24 | ||||
-rw-r--r-- | crates/hir_def/src/body/scope.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/expr.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 49 |
6 files changed, 71 insertions, 12 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 75dc19c11..9f278d35b 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -205,7 +205,7 @@ impl ExprCollector<'_> { | |||
205 | self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr()) | 205 | self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr()) |
206 | } | 206 | } |
207 | 207 | ||
208 | /// Returns `None` if the expression is `#[cfg]`d out. | 208 | /// Returns `None` if and only if the expression is `#[cfg]`d out. |
209 | fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> { | 209 | fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> { |
210 | let syntax_ptr = AstPtr::new(&expr); | 210 | let syntax_ptr = AstPtr::new(&expr); |
211 | self.check_cfg(&expr)?; | 211 | self.check_cfg(&expr)?; |
@@ -668,7 +668,7 @@ impl ExprCollector<'_> { | |||
668 | if self.check_cfg(&stmt).is_none() { | 668 | if self.check_cfg(&stmt).is_none() { |
669 | return; | 669 | return; |
670 | } | 670 | } |
671 | 671 | let has_semi = stmt.semicolon_token().is_some(); | |
672 | // Note that macro could be expended to multiple statements | 672 | // Note that macro could be expended to multiple statements |
673 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { | 673 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { |
674 | let macro_ptr = AstPtr::new(&m); | 674 | let macro_ptr = AstPtr::new(&m); |
@@ -685,18 +685,19 @@ impl ExprCollector<'_> { | |||
685 | statements.statements().for_each(|stmt| this.collect_stmt(stmt)); | 685 | statements.statements().for_each(|stmt| this.collect_stmt(stmt)); |
686 | if let Some(expr) = statements.expr() { | 686 | if let Some(expr) = statements.expr() { |
687 | let expr = this.collect_expr(expr); | 687 | 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 }); | ||
689 | } | 690 | } |
690 | } | 691 | } |
691 | None => { | 692 | None => { |
692 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); | 693 | 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 }); |
694 | } | 695 | } |
695 | }, | 696 | }, |
696 | ); | 697 | ); |
697 | } else { | 698 | } else { |
698 | let expr = self.collect_expr_opt(stmt.expr()); | 699 | 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 }); |
700 | } | 701 | } |
701 | } | 702 | } |
702 | ast::Stmt::Item(item) => { | 703 | ast::Stmt::Item(item) => { |
@@ -725,8 +726,17 @@ impl ExprCollector<'_> { | |||
725 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | 726 | let prev_statements = std::mem::take(&mut self.statements_in_scope); |
726 | 727 | ||
727 | block.statements().for_each(|s| self.collect_stmt(s)); | 728 | block.statements().for_each(|s| self.collect_stmt(s)); |
728 | 729 | block.tail_expr().and_then(|e| { | |
729 | let tail = block.tail_expr().map(|e| self.collect_expr(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; | ||
730 | let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); | 740 | let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); |
731 | let syntax_node_ptr = AstPtr::new(&block.into()); | 741 | let syntax_node_ptr = AstPtr::new(&block.into()); |
732 | let expr_id = self.alloc_expr( | 742 | 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)] |
243 | pub enum Statement { | 243 | pub 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 | ||
248 | impl Expr { | 248 | impl 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 | } |
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index d14f5c9bb..e23bd4da9 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -1050,3 +1050,52 @@ fn test() { | |||
1050 | "#]], | 1050 | "#]], |
1051 | ); | 1051 | ); |
1052 | } | 1052 | } |
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 | } | ||