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>
This commit is contained in:
bors[bot] 2021-10-30 14:42:53 +00:00 committed by GitHub
commit 7765c1a94f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 5 deletions

View file

@ -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
"#]],
);
}

View file

@ -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) }

View file

@ -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 {}

View file

@ -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();