about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/body/lower.rs18
-rw-r--r--crates/hir-ty/src/tests/macros.rs27
-rw-r--r--crates/hir-ty/src/tests/regression.rs6
3 files changed, 46 insertions, 5 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index e188d80eb81..049afa82279 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -690,12 +690,26 @@ impl ExprCollector<'_> {
         let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
         let prev_local_module = mem::replace(&mut self.expander.module, module);
 
-        let statements = block.statements().filter_map(|s| self.collect_stmt(s)).collect();
+        let mut statements: Vec<_> =
+            block.statements().filter_map(|s| self.collect_stmt(s)).collect();
         let tail = block.tail_expr().and_then(|e| self.maybe_collect_expr(e));
+        let tail = tail.or_else(|| {
+            let stmt = statements.pop()?;
+            if let Statement::Expr { expr, has_semi: false } = stmt {
+                return Some(expr);
+            }
+            statements.push(stmt);
+            None
+        });
 
         let syntax_node_ptr = AstPtr::new(&block.into());
         let expr_id = self.alloc_expr(
-            Expr::Block { id: block_id, statements, tail, label: None },
+            Expr::Block {
+                id: block_id,
+                statements: statements.into_boxed_slice(),
+                tail,
+                label: None,
+            },
             syntax_node_ptr,
         );
 
diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs
index 81268f37fd3..a4299d9f050 100644
--- a/crates/hir-ty/src/tests/macros.rs
+++ b/crates/hir-ty/src/tests/macros.rs
@@ -1,6 +1,8 @@
 use expect_test::expect;
 use test_utils::{bench, bench_fixture, skip_slow_tests};
 
+use crate::tests::check_infer_with_mismatches;
+
 use super::{check_infer, check_types};
 
 #[test]
@@ -1247,3 +1249,28 @@ fn infinitely_recursive_macro_type() {
         "#]],
     );
 }
+
+#[test]
+fn cfg_tails() {
+    check_infer_with_mismatches(
+        r#"
+//- /lib.rs crate:foo cfg:feature=foo
+struct S {}
+
+impl S {
+    fn new2(bar: u32) -> Self {
+        #[cfg(feature = "foo")]
+        { Self { } }
+        #[cfg(not(feature = "foo"))]
+        { Self { } }
+    }
+}
+"#,
+        expect![[r#"
+            34..37 'bar': u32
+            52..170 '{     ...     }': S
+            62..106 '#[cfg(... { } }': S
+            96..104 'Self { }': S
+        "#]],
+    );
+}
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index d41470d29f7..ee0a631a1bc 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1013,17 +1013,17 @@ fn cfg_tail() {
         "#,
         expect![[r#"
             14..53 '{     ...)] 9 }': ()
-            20..31 '{ "first" }': &str
+            20..31 '{ "first" }': ()
             22..29 '"first"': &str
             72..190 '{     ...] 13 }': ()
             78..88 '{ "fake" }': &str
             80..86 '"fake"': &str
             93..103 '{ "fake" }': &str
             95..101 '"fake"': &str
-            108..120 '{ "second" }': &str
+            108..120 '{ "second" }': ()
             110..118 '"second"': &str
             210..273 '{     ... 15; }': ()
-            216..227 '{ "third" }': &str
+            216..227 '{ "third" }': ()
             218..225 '"third"': &str
             293..357 '{     ...] 15 }': ()
             299..311 '{ "fourth" }': &str