about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-10-30 14:42:53 +0000
committerGitHub <noreply@github.com>2021-10-30 14:42:53 +0000
commit7765c1a94f4e93e76f0977a52b434f673aa97831 (patch)
treeb11cec330f779f14cf96429e113bd52edf62386a
parent3ad83cc08db5123401fd6786a10319f540879a8e (diff)
parentc93983e76f0617d495053913d96e557d72f66c81 (diff)
downloadrust-7765c1a94f4e93e76f0977a52b434f673aa97831.tar.gz
rust-7765c1a94f4e93e76f0977a52b434f673aa97831.zip
Merge #10668
10668: fix: Fix for-loop expressions breaking with BlockExpr iterable r=Veykril a=Veykril

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/10665
bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-rw-r--r--crates/hir_ty/src/tests/regression.rs24
-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.rs15
4 files changed, 44 insertions, 5 deletions
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index 67952edca38..4a0a5d6fa1f 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -1221,3 +1221,27 @@ fn mamba(a: U32!(), p: u32) -> u32 {
     "#,
     )
 }
+
+#[test]
+fn for_loop_block_expr_iterable() {
+    check_infer(
+        r#"
+fn test() {
+    for _ in { let x = 0; } {
+        let y = 0;
+    }
+}
+        "#,
+        expect![[r#"
+            10..68 '{     ...   } }': ()
+            16..66 'for _ ...     }': ()
+            20..21 '_': {unknown}
+            25..39 '{ let x = 0; }': ()
+            31..32 'x': i32
+            35..36 '0': i32
+            40..66 '{     ...     }': ()
+            54..55 'y': i32
+            58..59 '0': i32
+        "#]],
+    );
+}
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 005e78c48a1..18a6e1410dd 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -850,7 +850,6 @@ pub struct ForExpr {
     pub(crate) syntax: SyntaxNode,
 }
 impl ast::HasAttrs for ForExpr {}
-impl ast::HasLoopBody for ForExpr {}
 impl ForExpr {
     pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 2e6544f090e..98d142da3f7 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -754,6 +754,15 @@ impl ast::GenericParamList {
     }
 }
 
+impl ast::HasLoopBody for ast::ForExpr {
+    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::HasDocComments for ast::SourceFile {}
 impl ast::HasDocComments for ast::Fn {}
 impl ast::HasDocComments for ast::Struct {}
diff --git a/crates/syntax/src/tests/sourcegen_ast.rs b/crates/syntax/src/tests/sourcegen_ast.rs
index 36fedd2f0bc..dcd813bbe03 100644
--- a/crates/syntax/src/tests/sourcegen_ast.rs
+++ b/crates/syntax/src/tests/sourcegen_ast.rs
@@ -81,10 +81,17 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
         .map(|node| {
             let name = format_ident!("{}", node.name);
             let kind = format_ident!("{}", to_upper_snake_case(&node.name));
-            let traits = node.traits.iter().map(|trait_name| {
-                let trait_name = format_ident!("{}", trait_name);
-                quote!(impl ast::#trait_name for #name {})
-            });
+            let traits = node
+                .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"
+                })
+                .map(|trait_name| {
+                    let trait_name = format_ident!("{}", trait_name);
+                    quote!(impl ast::#trait_name for #name {})
+                });
 
             let methods = node.fields.iter().map(|field| {
                 let method_name = field.method_name();