swc-project/swc · error
add_effects for class expression
Error message
add_effects for class expression
What it means
ExprExt::extract_side_effects_to in swc_ecma_utils recursively splits an expression into its side-effecting subexpressions (used by transforms that reorder or eliminate expressions). It handles most expression kinds but class expressions (Expr::Class, i.e. an anonymous `class {}` used as a value) hit `unimplemented!("add_effects for class expression")` because nobody contributed that arm.
Solutions
- Guard the call site: skip or specially handle `matches!(expr, Expr::Class(_))` before calling extract_side_effects_to
- Rewrite the input so the class expression is hoisted into a variable (`const C = class {};`) before the transform runs
- Upgrade swc_ecma_utils, or if you own the fork, implement the Expr::Class arm (push the class expr itself or its computed keys/superclass)
Example fix
// before
let mut effects = Vec::new();
expr.extract_side_effects_to(&mut effects);
// after
let mut effects = Vec::new();
if matches!(&*expr, Expr::Class(_)) {
effects.push(expr); // preserve the whole class expression
} else {
expr.extract_side_effects_to(&mut effects);
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: pre-walk the expression and bail out early
fn contains_class_expr(e: &swc_ecma_ast::Expr) -> bool {
if matches!(e, swc_ecma_ast::Expr::Class(_)) { return true; }
// also check immediate children relevant to your pass
false
} Type guard
fn is_class_expr(e: &swc_ecma_ast::Expr) -> bool {
matches!(e, swc_ecma_ast::Expr::Class(_))
} Try / catch
// Wrap library calls in catch_unwind when feeding third-party code through
// transform pipelines that use extract_side_effects_to
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
run_transform(program)
}));
if result.is_err() { /* log node span, skip this module, fail loudly */ } Prevention
- Hoist class expressions to named consts in input code before running effect-extraction passes
- Guard every call to extract_side_effects_to with a matches!(expr, Expr::Class(_)) check
- Use catch_unwind at the module boundary of batch compilers so one bad module does not kill the whole run
When it happens
Trigger: A transform or utility that calls extract_side_effects_to on an expression tree containing an anonymous class expression in value position, e.g. `x = (class { ... }, y)` or an inlined IIFE result where a class expression remains.
Common situations: Custom passes built on ExprExt that feed arbitrary user code through extract_side_effects_to; optimization/inlining scenarios where a class expression survives to the extraction step.
Related errors
- A class descriptor's .kind property must be "class", but a…
- An element descriptor's .kind property must be either…
- An element descriptor's .placement property must be one of…
- #[ast_serde] on enum does not accept any argument
- Cannot convert to Param
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/6697c936ed19b24c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/swc_ecma_utils/src/lib.rs:2021
self.extract_side_effects_to(v, *e.expr);
v
});
}
Expr::TaggedTpl(TaggedTpl { tag, tpl, .. }) => {
self.extract_side_effects_to(to, *tag);
tpl.exprs
.into_iter()
.for_each(|e| self.extract_side_effects_to(to, *e));
}
Expr::Tpl(Tpl { exprs, .. }) => {
exprs
.into_iter()
.for_each(|e| self.extract_side_effects_to(to, *e));
}
Expr::Class(ClassExpr { .. }) => unimplemented!("add_effects for class expression"),
Expr::JSXMember(..)
| Expr::JSXNamespacedName(..)
| Expr::JSXEmpty(..)
| Expr::JSXElement(..)
| Expr::JSXFragment(..) => to.push(Box::new(expr)),
Expr::TsTypeAssertion(TsTypeAssertion { expr, .. })
| Expr::TsNonNull(TsNonNullExpr { expr, .. })
| Expr::TsAs(TsAsExpr { expr, .. })
| Expr::TsConstAssertion(TsConstAssertion { expr, .. })
| Expr::TsInstantiation(TsInstantiation { expr, .. })
| Expr::TsSatisfies(TsSatisfiesExpr { expr, .. }) => {
self.extract_side_effects_to(to, *expr)
}
Expr::OptChain(..) => to.push(Box::new(expr)),
Expr::Invalid(..) => unreachable!(),View on GitHub (pinned to 5176682b65)