Repository: rinja-rs/askama (language: rust)

Issue:
if let chain has a weird behaviour
I expected this code:

```jinja
{%- if let Some(query) = search_query && !query.is_empty() %}
```

To either emit an error about the `&&` after `if let Some` or to work, instead it generated:

```rust
if let Some(query,) = &(search_query && !self.query.is_empty()) {
```

Which is a very unexpected in-between.

I think it should generate `if let Some(query) = search_query && !self.query.is_empty()`. What do you think?


Discussion / hints:
> I think it should generate `if let Some(query) = search_query && !self.query.is_empty()`. What do you think?

That certainly looks more sensible!
Another interesting bug coming from `if let`: the binding var (`query` in this case) is not recognized as such.

Fix patch:
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index 58da7f72..1bb419ad 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -364,12 +364,24 @@ impl<'a> Generator<'a> {
 
                 if let Some(target) = target {
                     let mut expr_buf = Buffer::new(0);
-                    self.visit_expr(&mut expr_buf, expr)?;
                     buf.write("let ");
-                    self.visit_target(buf, true, true, target);
-                    buf.write(" = &(");
+                    // If this is a chain condition, then we need to declare the variable after the
+                    // left expression has been handled but before the right expression is handled
+                    // but this one should have access to the let-bound variable.
+                    match expr {
+                        Expr::BinOp(op, ref left, ref right) if *op == "||" || *op == "&&" => {
+                            self.visit_expr(&mut expr_buf, left)?;
+                            self.visit_target(buf, true, true, target);
+                            expr_buf.write(&format!(" {op} "));
+                            self.visit_expr(&mut expr_buf, right)?;
+                        }
+                        _ => {
+                            self.visit_expr(&mut expr_buf, expr)?;
+                            self.visit_target(buf, true, true, target);
+                        }
+                    }
+                    buf.write(" = &");
                     buf.write(&expr_buf.buf);
-                    buf.write(")");
                 } else {
                     // The following syntax `*(&(...) as &bool)` is used to
                     // trigger Rust's automatic dereferencing, to coerce


Test patch: