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

  1. Restore the official pass ordering and retest — most hoisting bugs come from reordered transforms
  2. Validate AST invariants before compat: walk VarDeclarators and assert name is not Pat::Rest
  3. 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

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


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/539a7c06f4c81df8. Report an issue: GitHub.