swc-project/swc · error
rest pattern should handled by array pattern handler: {:?}
Error message
rest pattern should handled by array pattern handler: {:?} What it means
While lowering destructuring declarations, a VarDeclarator whose name pattern is a top-level Rest (`const ...rest = arr`) is invalid — rest patterns only legally occur inside array patterns and are consumed by that handler. Seeing one means an earlier transform or hand-built AST produced a malformed pattern tree.
Source
Thrown at crates/swc_ecma_compat_es2015/src/destructuring.rs:156
},
body => BlockStmt {
stmts: vec![stmt, body.take()],
..Default::default()
},
}));
}
};
}
fn make_ref_ident_for_for_stmt() -> Ident {
private_ident!("ref")
}
impl AssignFolder {
fn visit_mut_var_decl(&mut self, decls: &mut Vec<VarDeclarator>, decl: VarDeclarator) {
match decl.name {
Pat::Ident(..) => decls.push(decl),
Pat::Rest(..) => unreachable!(
"rest pattern should handled by array pattern handler: {:?}",
decl.name
),
Pat::Array(ArrayPat { elems, .. }) => {
assert!(
decl.init.is_some(),
"destructuring pattern binding requires initializer"
);
let init = decl.init.unwrap();
if is_literal(&init) {
match *init {
Expr::Array(arr)
if !elems.is_empty()
&& (elems.len() == arr.elems.len()
|| (elems.len() < arr.elems.len() && has_rest_pat(&elems))) =>
{View on GitHub (pinned to 5176682b65)
Solutions
- Restore the official pass ordering and retest — most hoisting bugs come from reordered transforms
- Validate AST invariants before compat: walk VarDeclarators and assert name is not Pat::Rest
- Reduce the input to the statement that produces the pattern and report upstream with your pass list
Defensive patterns
Strategy: type-guard
Type guard
// Assert no top-level Rest pattern in declarators before compat passes
fn no_top_level_rest(m: &swc_ecma_ast::Module) -> bool {
struct V(bool);
impl Visit for V {
fn visit_var_declarator(&mut self, d: &VarDeclarator) {
if matches!(d.name, Pat::Rest(_)) { self.0 = false; }
d.visit_children_with(self);
}
}
let mut v = V(true);
m.visit_with(&mut v);
v.0
} Try / catch
if let Err(p) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| destructuring(&mut program))) {
if panic_message(&p).contains("rest pattern") {
// an earlier pass produced a malformed pattern; disable that pass or reorder
} else { std::panic::resume_unwind(p); }
} Prevention
- Keep transforms that move Pat nodes from hoisting Rest out of ArrayPat
- Validate AST invariants (no top-level Pat::Rest in VarDeclarator) between passes in debug builds
- Reorder passes back to the official sequence before debugging deeper
When it happens
Trigger: Pipelines where a previous pass rewrites array/object patterns and accidentally hoists a Rest to the declarator level; AST constructed manually with Pat::Rest as a VarDeclarator name; bugs in sibling destructuring-related passes.
Common situations: Custom or out-of-order compat passes (spread, object_rest_spread, destructuring) mutating patterns; plugin authors moving Pat nodes between positions.
Related errors
- assign property in object literal is invalid
- using declaration must be removed by previous pass
- Object rest pattern should be removed by es2018::object_rest
- Invalid attempt to destructure non-iterable instance. In ord
- Cannot destructure ${o}
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/539a7c06f4c81df8.
Report an issue: GitHub.