From 575b0e301e6d9cfeea8b47b724aeb5ab583591e1 Mon Sep 17 00:00:00 2001 From: Hong Jiarong Date: Sat, 15 Nov 2025 23:41:04 +0800 Subject: [PATCH] fix: destructuring pattern handling in ExprWorker (#2244) This PR corrects destructuring handling in `ExprWorker` by switching `DestructuringItem::Named` to use `named.pattern()` rather than `named.expr()`. According to ast definition (see `Named::pattern` in https://github.com/typst/typst/blob/0da0165954e027ba48f7ba4a03e3b7b5b35ea8f6/crates/typst-syntax/src/ast.rs#L1418-L1433 , the rhs of a `Named` pair must be interpreted as a pattern when it appears inside a destructuring context, not as an expression. This change ensures nested destructuring patterns are analyzed correctly. Also, spread items (`..rest`) are normalized into pattern form and registered as proper declarations. So that now complex patterns like `#let (x: (used_a, unused_x), y: (c1, c2, c3)) = (...)` and array spreads like `#let (first, ..rest) = (1, 2, 3)` are allowed to resolve and lint as intended. --- crates/tinymist-query/src/syntax/expr.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/tinymist-query/src/syntax/expr.rs b/crates/tinymist-query/src/syntax/expr.rs index 76762c97..781c7d85 100644 --- a/crates/tinymist-query/src/syntax/expr.rs +++ b/crates/tinymist-query/src/syntax/expr.rs @@ -516,7 +516,7 @@ impl ExprWorker<'_> { } ast::DestructuringItem::Named(named) => { let key = Decl::var(named.name()).into(); - let val = self.check_pattern_expr(named.expr()); + let val = self.check_pattern(named.pattern()); names.push((key, val)); } ast::DestructuringItem::Spread(spreading) => { @@ -525,14 +525,17 @@ impl ExprWorker<'_> { } else { Decl::spread(spreading.span()).into() }; + let pattern = Pattern::Expr(Expr::Star).into(); if inputs.is_empty() { - spread_left = - Some((decl, self.check_pattern_expr(spreading.expr()))); + spread_left = Some((decl.clone(), pattern)); } else { - spread_right = - Some((decl, self.check_pattern_expr(spreading.expr()))); + spread_right = Some((decl.clone(), pattern)); } + + self.resolve_as(Decl::as_def(&decl, None)); + self.scope_mut() + .insert_mut(decl.name().clone(), decl.into()); } } }