{"record":{"id":"7b5f4fb9ba54e7d5","repo":"swc-project/swc","slug":"failed-to-parse-assigntarget","errorCode":null,"errorMessage":"failed to parse AssignTarget","messagePattern":"failed to parse AssignTarget","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_quote_macros/src/ret_type.rs","lineNumber":45,"sourceCode":"    if let Some(ty) = extract_generic(\"Option\", ty) {\n        if input_str.is_empty() {\n            return Ok(BoxWrapper(Box::new(None::<swc_ecma_ast::Expr>)));\n        }\n\n        let node = parse_input_type(input_str, ty).context(\"failed to parse `T` in Option<T>\")?;\n        return Ok(BoxWrapper(Box::new(Some(node))));\n    }\n\n    if let Type::Path(p) = ty {\n        if let Some(ident) = p.path.get_ident() {\n            match &*ident.to_string() {\n                \"Expr\" => return parse(input_str, &mut |p| p.parse_expr().map(|v| *v)),\n                \"Pat\" => return parse(input_str, &mut |p| p.parse_pat()),\n                \"Stmt\" => return parse(input_str, &mut |p| p.parse_stmt_list_item()),\n                \"AssignTarget\" => {\n                    return parse(input_str, &mut |p| {\n                        Ok(AssignTarget::try_from(p.parse_pat()?)\n                            .expect(\"failed to parse AssignTarget\"))\n                    })\n                }\n                \"ModuleItem\" => return parse(input_str, &mut |p| p.parse_module_item()),\n                _ => {}\n            }\n        }\n    }\n\n    bail!(\"Unknown quote type: {ty:?}\");\n}\n\nfn parse<T>(\n    input_str: &str,\n    op: &mut dyn FnMut(&mut Parser<Lexer>) -> PResult<T>,\n) -> Result<BoxWrapper, Error>\nwhere\n    T: ToCode,\n{","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_quote_macros/src/ret_type.rs#L27-L63","documentation":"Inside `parse_input_type` (crates/swc_ecma_quote_macros/src/ret_type.rs), when the `quote!` output type is `AssignTarget`, the macro parses the quoted string as a `Pat` and converts it with `AssignTarget::try_from(p)`. That `TryFrom` (crates/swc_ecma_ast/src/expr.rs:1519) only accepts `Pat::Ident`, `Pat::Array`, `Pat::Object`, `Pat::Invalid`, and `Pat::Expr` variants that are themselves valid `SimpleAssignTarget`s. Any other pattern returns Err and this `expect` panics during macro expansion.","triggerScenarios":"`quote!(AssignTarget as \"a = 1\")` (Pat::Assign, a pattern with default), `quote!(AssignTarget as \"...rest\")` (Pat::Rest), or an expression pattern that is not a simple assignment target such as `quote!(AssignTarget as \"foo()\")`, `\"123\"`, or `\"a + b\"` (SimpleAssignTarget::try_from rejects call/literal/binary expressions).","commonSituations":"Transform authors templating the left-hand side of an assignment expression (`AssignExpr { left: quote!(AssignTarget as \"...\"), .. }`) and pasting a full assignment, a rest element, or a non-reference expression into the quoted string. The panic happens at compile time of the transform crate.","solutions":["Quote only a valid assignment target: a plain identifier (`\"a\"`), a member expression (`\"a.b\"`, `\"a[b]\"`), or a destructuring pattern (`\"[a, b]\"`, `\"({ a })\").","Remove default values and rest elements from the quoted string (`\"a = 1\"` and \"...rest\" are not assignable targets in the Pat form this macro accepts).","For call results or literals on the left-hand side, that code is invalid JavaScript anyway; fix the template to match real assignment syntax.","If you need an arbitrary pattern, use `quote!(Pat as \"...\")` and convert to AssignTarget yourself where you can handle the Err."],"exampleFix":"// before\nlet target = quote!(AssignTarget as \"a = 1\"); // Pat::Assign rejected by TryFrom<Pat>\n\n// after\nlet target = quote!(AssignTarget as \"a\");","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// A quoted string is safe for `quote!(AssignTarget as \"...\")` only if it is\n// an identifier, member access, or destructuring pattern.\nfn is_assign_target_snippet(src: &str) -> bool {\n    let s = src.trim();\n    // reject defaults (\"a = 1\") and top-level rest (\"...r\")\n    if s.contains(\"= \") || s.starts_with(\"...\") {\n        return false;\n    }\n    matches!(\n        s,\n        _ if s.chars().next().map_or(false, |c| c.is_alphabetic() || c == '_' || c == '[' || s.starts_with(\"({\"))\n    )\n}","tryCatchPattern":null,"preventionTips":["Only quote identifiers, member expressions, or array/object destructuring patterns as AssignTarget.","Never put defaults (`=`) or rest elements (`...`) in an AssignTarget template.","Prefer quote!(Pat as \"...\") when the pattern shape is not guaranteed, and convert with TryFrom where the Err can be handled."],"tags":["proc-macro","quote-macro","assignment-target","compile-time","swc"],"backgroundTag":"invalid-assignment-target","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"}