{"record":{"id":"d69041f64c278f0a","repo":"swc-project/swc","slug":"pattern","errorCode":null,"errorMessage":"Pattern {:?}","messagePattern":"Pattern (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_compat_es2015/src/destructuring.rs","lineNumber":470,"sourceCode":"                    // tmp === void 0 ? def_value : tmp\n                    Some(Box::new(make_cond_expr(tmp_ident, def_value)))\n                } else {\n                    Some(def_value)\n                };\n\n                let var_decl = VarDeclarator {\n                    span,\n                    name: *left,\n                    init,\n                    definite: false,\n                };\n\n                let mut var_decls = vec![var_decl];\n                var_decls.visit_mut_with(self);\n                decls.extend(var_decls);\n            }\n\n            _ => unimplemented!(\"Pattern {:?}\", decl),\n        }\n    }\n}\n\n#[fast_path(DestructuringVisitor)]\nimpl VisitMut for Destructuring {\n    noop_visit_mut_type!(fail);\n\n    impl_for_for_stmt!(visit_mut_for_in_stmt, ForInStmt);\n\n    impl_for_for_stmt!(visit_mut_for_of_stmt, ForOfStmt);\n\n    impl_visit_mut_fn!();\n\n    fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {\n        self.visit_mut_stmt_like(n);\n    }\n","sourceCodeStart":452,"sourceCodeEnd":488,"githubUrl":"https://github.com/swc-project/swc/blob/d7d74346665e36e692aa07e13d4ee3ee692ee35c/crates/swc_ecma_compat_es2015/src/destructuring.rs#L452-L488","documentation":"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)`.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Treat parser errors as fatal — do not run compat transforms on an AST recovered from a failed parse","Validate that every VarDeclarator name is Ident/Array/Object/Assign before running the pass","Reduce to a minimal input and report the offending pattern kind upstream"],"exampleFix":"// before: transforming an error-recovered AST\nlet module = parser.parse_module().ok().unwrap_or_else(|| build_partial_module());\nmodule.visit_mut_with(&mut destructuring(c));\n\n// after: abort on parse errors\nlet module = parser.parse_module()?;\nmodule.visit_mut_with(&mut destructuring(c));","handlingStrategy":"validation","validationCode":"// Rust: validate declarator patterns before the destructuring pass\nfn patterns_are_supported(m: &Module) -> bool {\n    fn ok(p: &Pat) -> bool { matches!(p, Pat::Ident(..) | Pat::Array(..) | Pat::Object(..) | Pat::Assign(..)) }\n    m.body.iter().all(|i| match i {\n        ModuleItem::Stmt(Stmt::Decl(Decl::Var(v))) => v.decls.iter().all(|d| ok(&d.name)),\n        _ => true,\n    })\n}","typeGuard":"fn is_valid_destructuring_pat(p: &Pat) -> bool {\n    matches!(p, Pat::Ident(..) | Pat::Array(..) | Pat::Object(..) | Pat::Assign(..))\n}","tryCatchPattern":null,"preventionTips":["Abort on parse errors instead of transforming recovered ASTs","When building AST programmatically, assert every declarator name is one of the four supported patterns"],"tags":["ecmascript","es2015","destructuring","ast-validation"],"backgroundTag":null,"analyzedSha":"d7d74346665e36e692aa07e13d4ee3ee692ee35c","analyzedAt":"2026-08-16T12:41:13.160Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}