{"record":{"id":"9ef58a31be816998","repo":"swc-project/swc","slug":"illegal-conversion-cannot-convert-to-logical","errorCode":null,"errorMessage":"illegal conversion: Cannot convert {:?} to LogicalExprOp","messagePattern":"illegal conversion: Cannot convert (.+?) to LogicalExprOp","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_estree_compat/src/babelify/operators.rs","lineNumber":29,"sourceCode":"}\n\nimpl From<BinaryOpOutput> for BinaryExprOp {\n    fn from(o: BinaryOpOutput) -> Self {\n        match o {\n            BinaryOpOutput::BinOp(op) => op,\n            BinaryOpOutput::LogicOp(_) => panic!(\n                \"illegal conversion: Cannot convert {:?} to BinaryExprOp\",\n                &o\n            ),\n        }\n    }\n}\n\nimpl From<BinaryOpOutput> for LogicalExprOp {\n    fn from(o: BinaryOpOutput) -> Self {\n        match o {\n            BinaryOpOutput::LogicOp(op) => op,\n            BinaryOpOutput::BinOp(_) => panic!(\n                \"illegal conversion: Cannot convert {:?} to LogicalExprOp\",\n                &o\n            ),\n        }\n    }\n}\n\nimpl Babelify for BinaryOp {\n    type Output = BinaryOpOutput;\n\n    fn babelify(self, _ctx: &Context) -> Self::Output {\n        match self {\n            BinaryOp::EqEq => BinaryOpOutput::BinOp(BinaryExprOp::Equal),\n            BinaryOp::NotEq => BinaryOpOutput::BinOp(BinaryExprOp::NotEqual),\n            BinaryOp::EqEqEq => BinaryOpOutput::BinOp(BinaryExprOp::StrictEqual),\n            BinaryOp::NotEqEq => BinaryOpOutput::BinOp(BinaryExprOp::StrictNotEqual),\n            BinaryOp::Lt => BinaryOpOutput::BinOp(BinaryExprOp::LessThan),\n            BinaryOp::LtEq => BinaryOpOutput::BinOp(BinaryExprOp::LessThanOrEqual),","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_estree_compat/src/babelify/operators.rs#L11-L47","documentation":"The mirror of the BinaryExprOp conversion: this From impl converts a BinaryOpOutput into LogicalExprOp and panics when the value holds the BinOp kind. Babel represents `a && b` as LogicalExpression and arithmetic/comparison operations as BinaryExpression, so babelifying a LogicalExpr whose operator is non-logical (e.g. `+`) is an inconsistent AST that cannot be converted. The SWC parser never emits this mismatch; it comes from AST construction or transforms that pair the wrong node type with an operator.","triggerScenarios":"Constructing a swc_ecma_ast LogicalExpr with op set to a non-logical operator such as Add or Eq (or rewriting a LogicalExpr's op in place) and then babelifying the expression.","commonSituations":"Operator-rewriting codemods that keep the node type fixed; AST builder utilities defaulting to LogicalExpr; hand-written test fixtures with inconsistent node/op pairings.","solutions":["Pair the node type with the operator class: LogicalExpr only for &&/||/??, BinExpr for everything else","Fix transforms to change the node type when they change the operator class","Validate the AST before babelify with a check that BinExpr/LogicalExpr ops are in the right class","Wrap the conversion in catch_unwind as a last-resort guard"],"exampleFix":"// before\nLogicalExpr {\n    op: BinaryOp::Add,\n    left,\n    right,\n}\n\n// after\nBinExpr {\n    op: BinaryOp::Add,\n    left,\n    right,\n}","handlingStrategy":"type-guard","validationCode":"fn logical_exprs_consistent(program: &Program) -> Result<(), String> {\n    for e in exprs(program) {\n        if let Expr::Logical(l) = e {\n            if !matches!(l.op, BinaryOp::LogicalAnd | BinaryOp::LogicalOr | BinaryOp::NullishCoalescing) {\n                return Err(format!(\"LogicalExpr with non-logical op {:?} at {:?}\", l.op, l.span));\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":"fn op_is_logical(o: BinaryOp) -> bool {\n    matches!(o, BinaryOp::LogicalAnd | BinaryOp::LogicalOr | BinaryOp::NullishCoalescing)\n}","tryCatchPattern":"let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| program.babelify(&ctx)))\n    .map_err(|_| anyhow::anyhow!(\"illegal conversion: non-logical operator used in LogicalExpression\"))?;","preventionTips":["Reserve LogicalExpr for &&, ||, ?? only","Make operator-rewriting transforms also fix the node type","Validate AST shape before babelify in codemod pipelines","Cover both node types in fixture tests for expression builders"],"tags":["swc","babelify","panic","logical-expression","operator-mismatch","illegal-conversion"],"backgroundTag":"operator-kind-mismatch","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"}