Unnamed repository; edit this file 'description' to name the repository.
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 <[email protected]>
bors[bot] 2021-10-30
parent 3ad83cc · parent c93983e · commit 7765c1a
-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 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<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 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<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 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();