about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2022-02-26 16:45:06 +0200
committerLaurențiu Nicola <lnicola@dend.ro>2022-02-26 16:45:06 +0200
commit87c4a4104da2acc662f777324f4ae3c6702bb5cc (patch)
tree66a38b9f43426914a84a2c6f023f3a53e066523d
parenta2cc1d6b7b499d6b03436db7fc8053aea72f75ac (diff)
downloadrust-87c4a4104da2acc662f777324f4ae3c6702bb5cc.tar.gz
rust-87c4a4104da2acc662f777324f4ae3c6702bb5cc.zip
Fix body selection in while loops
-rw-r--r--crates/hir_ty/src/tests/regression.rs22
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs1
-rw-r--r--crates/syntax/src/ast/node_ext.rs9
-rw-r--r--crates/syntax/src/tests/sourcegen_ast.rs5
4 files changed, 34 insertions, 3 deletions
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index 4a0a5d6fa1f..812f12acede 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -1245,3 +1245,25 @@ fn test() {
         "#]],
     );
 }
+
+#[test]
+fn while_loop_block_expr_iterable() {
+    check_infer(
+        r#"
+fn test() {
+    while { true } {
+        let y = 0;
+    }
+}
+        "#,
+        expect![[r#"
+            10..59 '{     ...   } }': ()
+            16..57 'while ...     }': ()
+            22..30 '{ true }': bool
+            24..28 'true': bool
+            31..57 '{     ...     }': ()
+            45..46 'y': i32
+            49..50 '0': i32
+        "#]],
+    );
+}
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 6c4729ef365..11247fbf1c9 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1035,7 +1035,6 @@ pub struct WhileExpr {
     pub(crate) syntax: SyntaxNode,
 }
 impl ast::HasAttrs for WhileExpr {}
-impl ast::HasLoopBody for WhileExpr {}
 impl WhileExpr {
     pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
     pub fn condition(&self) -> Option<Expr> { support::child(&self.syntax) }
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 1b916e91bfd..97455abd809 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -769,6 +769,15 @@ impl ast::HasLoopBody for ast::ForExpr {
     }
 }
 
+impl ast::HasLoopBody for ast::WhileExpr {
+    fn loop_body(&self) -> Option<ast::BlockExpr> {
+        let mut exprs = support::children(self.syntax());
+        let first = exprs.next();
+        let second = exprs.next();
+        second.or(first)
+    }
+}
+
 impl ast::HasAttrs for ast::AnyHasDocComments {}
 
 impl From<ast::Adt> for ast::Item {
diff --git a/crates/syntax/src/tests/sourcegen_ast.rs b/crates/syntax/src/tests/sourcegen_ast.rs
index 4a608da9ff4..5ed56a81c49 100644
--- a/crates/syntax/src/tests/sourcegen_ast.rs
+++ b/crates/syntax/src/tests/sourcegen_ast.rs
@@ -85,8 +85,9 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
                 .traits
                 .iter()
                 .filter(|trait_name| {
-                    // For loops have two expressions so this might collide, therefor manual impl it
-                    node.name != "ForExpr" || trait_name.as_str() != "HasLoopBody"
+                    // Loops have two expressions so this might collide, therefor manual impl it
+                    node.name != "ForExpr" && node.name != "WhileExpr"
+                        || trait_name.as_str() != "HasLoopBody"
                 })
                 .map(|trait_name| {
                     let trait_name = format_ident!("{}", trait_name);