diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 67952edca3..4a0a5d6fa1 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 005e78c48a..18a6e1410d 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 { support::token(&self.syntax, T![for]) } pub fn pat(&self) -> Option { support::child(&self.syntax) } diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 2e6544f090..98d142da3f 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 { + 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 36fedd2f0b..dcd813bbe0 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();