{"record":{"id":"e560a78dee020c5e","repo":"swc-project/swc","slug":"object-rest-pattern-should-be-removed-by-es2018-o","errorCode":null,"errorMessage":"Object rest pattern should be removed by es2018::object_rest_spread pass","messagePattern":"Object rest pattern should be removed by es2018::object_rest_spread pass","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_compat_es2015/src/destructuring.rs","lineNumber":420,"sourceCode":"                                }\n                                None => {\n                                    let var_decl = VarDeclarator {\n                                        span: prop_span,\n                                        name: key.clone().into(),\n                                        init: Some(Box::new(make_ref_prop_expr(\n                                            &ref_ident,\n                                            key.clone().into(),\n                                            computed,\n                                        ))),\n                                        definite: false,\n                                    };\n                                    let mut var_decls = vec![var_decl];\n                                    var_decls.visit_mut_with(self);\n                                    decls.extend(var_decls);\n                                }\n                            }\n                        }\n                        ObjectPatProp::Rest(..) => unreachable!(\n                            \"Object rest pattern should be removed by es2018::object_rest_spread \\\n                             pass\"\n                        ),\n                        #[cfg(swc_ast_unknown)]\n                        _ => panic!(\"unable to access unknown nodes\"),\n                    }\n                }\n            }\n            Pat::Assign(AssignPat {\n                span,\n                left,\n                right: def_value,\n                ..\n            }) => {\n                let init = if let Some(init) = decl.init {\n                    let tmp_ident = match &*init {\n                        Expr::Ident(ref i) if i.ctxt != SyntaxContext::empty() => i.clone(),\n","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_compat_es2015/src/destructuring.rs#L402-L438","documentation":"The es2015 destructuring pass lowers object patterns property by property; object rest (`const { a, ...rest } = obj`) belongs to es2018::object_rest_spread, which must run earlier and eliminate ObjectPatProp::Rest. If a rest element is still present when destructuring runs, it panics because it cannot express 'all remaining properties'.","triggerScenarios":"Running swc_ecma_compat_es2015::destructuring standalone — without es2018::object_rest_spread ahead of it — on code using object rest patterns in declarations, assignments, or function parameters.","commonSituations":"Hand-assembled transform chains instead of the preset; migrating old pipelines after object rest syntax was added; tools applying only a subset of es2015 passes to reduce build time.","solutions":["Use the standard compat chain (swc core build/targets) which orders object_rest_spread before destructuring","In a custom chain, prepend swc_ecma_compat_es2018::object_rest_spread() before es2015 destructuring","Avoid object rest syntax in inputs when you must run destructuring alone"],"exampleFix":"// before (custom chain, wrong order)\nlet passes = vec![destructuring()];\n\n// after\nlet passes = vec![\n  Box::new(swc_ecma_compat_es2018::object_rest_spread()),\n  destructuring(),\n];","handlingStrategy":"validation","validationCode":"// Detect object rest patterns before running destructuring standalone\nlet object_rest = regex::Regex::new(r\"\\{\\s*[^}]*\\.\\.\\.[A-Za-z_$][\\w$]*\\s*\\}\").unwrap();\nif object_rest.is_match(&source) {\n    return Err(\"object rest requires es2018::object_rest_spread before destructuring\".into());\n}","typeGuard":"// Guard AST before destructuring: no ObjectPatProp::Rest may remain\nfn object_rest_removed(m: &swc_ecma_ast::Module) -> bool {\n    struct V(bool);\n    impl Visit for V {\n        fn visit_object_pat_prop(&mut self, p: &ObjectPatProp) {\n            if matches!(p, ObjectPatProp::Rest(_)) { self.0 = false; }\n            p.visit_children_with(self);\n        }\n    }\n    let mut v = V(true);\n    m.visit_with(&mut v);\n    v.0\n}","tryCatchPattern":"if let Err(p) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| destructuring(&mut program))) {\n    if panic_message(&p).contains(\"object_rest_spread\") {\n        // prepend swc_ecma_compat_es2018::object_rest_spread() and retry\n    } else { std::panic::resume_unwind(p); }\n}","preventionTips":["Use swc's preset chain so object_rest_spread always precedes destructuring","In custom chains, order passes newest-syntax-first (es2018+ before es2015)","Add pipeline smoke tests covering object rest, spread, and class properties"],"tags":["swc","compat","es2015","es2018","object-rest","pass-order"],"backgroundTag":"object-rest-spread-lowering","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}