swc-project/swc · error

Pattern {:?}

Error message

Pattern {:?}

What it means

The ES2015 destructuring transform lowers destructuring declarations for Ident, Array, Object and Assign patterns. Any other `Pat` variant used as the name of a `VarDeclarator` — in practice `Pat::Invalid` produced by error-recovery parsing, or programmatically built AST — falls into `_ => unimplemented!("Pattern {:?}", decl)`.

Source

Thrown at crates/swc_ecma_compat_es2015/src/destructuring.rs:470

                    // tmp === void 0 ? def_value : tmp
                    Some(Box::new(make_cond_expr(tmp_ident, def_value)))
                } else {
                    Some(def_value)
                };

                let var_decl = VarDeclarator {
                    span,
                    name: *left,
                    init,
                    definite: false,
                };

                let mut var_decls = vec![var_decl];
                var_decls.visit_mut_with(self);
                decls.extend(var_decls);
            }

            _ => unimplemented!("Pattern {:?}", decl),
        }
    }
}

#[fast_path(DestructuringVisitor)]
impl VisitMut for Destructuring {
    noop_visit_mut_type!(fail);

    impl_for_for_stmt!(visit_mut_for_in_stmt, ForInStmt);

    impl_for_for_stmt!(visit_mut_for_of_stmt, ForOfStmt);

    impl_visit_mut_fn!();

    fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
        self.visit_mut_stmt_like(n);
    }

View on GitHub (pinned to d7d7434666)

Solutions

  1. Treat parser errors as fatal — do not run compat transforms on an AST recovered from a failed parse
  2. Validate that every VarDeclarator name is Ident/Array/Object/Assign before running the pass
  3. Reduce to a minimal input and report the offending pattern kind upstream

Example fix

// before: transforming an error-recovered AST
let module = parser.parse_module().ok().unwrap_or_else(|| build_partial_module());
module.visit_mut_with(&mut destructuring(c));

// after: abort on parse errors
let module = parser.parse_module()?;
module.visit_mut_with(&mut destructuring(c));
Defensive patterns

Strategy: validation

Validate before calling

// Rust: validate declarator patterns before the destructuring pass
fn patterns_are_supported(m: &Module) -> bool {
    fn ok(p: &Pat) -> bool { matches!(p, Pat::Ident(..) | Pat::Array(..) | Pat::Object(..) | Pat::Assign(..)) }
    m.body.iter().all(|i| match i {
        ModuleItem::Stmt(Stmt::Decl(Decl::Var(v))) => v.decls.iter().all(|d| ok(&d.name)),
        _ => true,
    })
}

Type guard

fn is_valid_destructuring_pat(p: &Pat) -> bool {
    matches!(p, Pat::Ident(..) | Pat::Array(..) | Pat::Object(..) | Pat::Assign(..))
}

Prevention

When it happens

Trigger: Feed the destructuring pass a `VarDeclarator` whose name is `Pat::Invalid` or `Pat::Rest`: typically a module parsed in error-recovery mode (errors collected but an AST still returned) or an AST constructed/mutated by a plugin.

Common situations: Custom tooling and plugins that build or mutate AST without validating patterns; pipelines that ignore parser errors and keep transforming; inputs from codegen that emit invalid patterns.

Related errors


AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16). Data as JSON: /api/errors/d69041f64c278f0a. Report an issue: GitHub.