{"record":{"id":"4c5f5f3b6b0343e0","repo":"swc-project/swc","slug":"object-rest-pattern-should-be-removed-by-es2018-o-4c5f5f","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":1028,"sourceCode":"                                    }\n                                    None => {\n                                        exprs.push(\n                                            AssignExpr {\n                                                span,\n                                                left: key.clone().into(),\n                                                op: op!(\"=\"),\n                                                right: Box::new(make_ref_prop_expr(\n                                                    &ref_ident,\n                                                    key.clone().into(),\n                                                    computed,\n                                                )),\n                                            }\n                                            .into(),\n                                        );\n                                    }\n                                }\n                            }\n                            ObjectPatProp::Rest(_) => unreachable!(\n                                \"object rest pattern should be removed by \\\n                                 es2018::object_rest_spread pass\"\n                            ),\n                            #[cfg(swc_ast_unknown)]\n                            _ => panic!(\"unable to access unknown nodes\"),\n                        }\n                    }\n\n                    // Last one should be object itself.\n                    exprs.push(ref_ident.into());\n\n                    *expr = SeqExpr {\n                        span: DUMMY_SP,\n                        exprs,\n                    }\n                    .into();\n                }\n","sourceCodeStart":1010,"sourceCodeEnd":1046,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_compat_es2015/src/destructuring.rs#L1010-L1046","documentation":"The es2015 destructuring pass (swc_ecma_compat_es2015::destructure) rewrites object binding patterns into a sequence of assignments. While expanding the properties of an object pattern it explicitly asserts that ObjectPatProp::Rest never appears, because rest elements (e.g. `const {a, ...rest} = obj`) are supposed to be lowered earlier by the es2018::object_rest_spread pass. Hitting this unreachable! means the compat pass chain ran in the wrong order or was hand-assembled without the es2018 pass.","triggerScenarios":"Compiling source containing an object destructuring rest element while invoking swc_ecma_compat_es2015::destructure directly (or in a custom swc_core Pass chain) without running swc_ecma_compat_es2018::object_rest_spread first. Also triggered by swc_core version skew where the preset-env/compat pass ordering changed.","commonSituations":"Codemod or bundler authors building custom `Chain`s of compat passes instead of using preset_env/CompatEnv; projects mixing swc_core versions across crates (e.g. swc_ecma_compat_es2015 from a different version than the driver); downgrading swc after a pass-list refactor.","solutions":["If you build a manual pass chain, insert swc_ecma_compat_es2018::object_rest_spread(Default::default()) BEFORE swc_ecma_compat_es2015::destructure (and before es2015::generator).","Prefer the standard pipelines (swc_ecma_preset_env / CompatEnv / full `es` compat chain) which order passes correctly, instead of hand-picking passes.","Align all swc crates on one swc_core version so pass wiring is consistent.","If ordering is already correct in your version, file an swc issue with a minimal repro of the rest-element input."],"exampleFix":"// before: rest element panics because es2018 pass never ran\nlet pass = Chain::new(swc_ecma_compat_es2015::destructure());\n\n// after: lower object rest/spread first, then destructure\nlet pass = Chain::new(\n    swc_ecma_compat_es2018::object_rest_spread(Default::default()),\n    swc_ecma_compat_es2015::destructure(),\n);","handlingStrategy":"validation","validationCode":"// Before applying es2015::destructure, assert no object-rest remains\nuse swc_ecma_ast::*; use swc_ecma_visit::{Visit, VisitWith};\nstruct RestChecker; impl Visit for RestChecker {\n    fn visit_object_pat_prop(&mut self, p: &ObjectPatProp) {\n        if let ObjectPatProp::Rest(_) = p { panic!(\"run object_rest_spread before destructure\"); }\n        p.visit_children_with(self);\n    }\n}\n// program.visit_with(&mut RestChecker);","typeGuard":null,"tryCatchPattern":"// Rust panics cross FFI/thread boundaries; contain them at your driver edge\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    program.apply_mut(chain)\n}));\nif result.is_err() { /* extract payload, surface 'pass ordering' error to user */ }","preventionTips":["Prefer preset_env/CompatEnv over hand-assembled compat chains.","Never place es2015 passes before es2018 object_rest_spread in a chain.","Keep every swc crate on the same swc_core release (cargo tree -i swc_core)."],"tags":["swc","compat-es2015","destructuring","object-rest","pass-ordering","panic"],"backgroundTag":"compiler-pass-ordering","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}