{"record":{"id":"318bf2b9ca4096f1","repo":"swc-project/swc","slug":"derive-spanned-span-lo-and-span-hi-is","errorCode":null,"errorMessage":"#[derive(Spanned)]: #[span(lo)] and #[span(hi)] is required","messagePattern":"#\\[derive\\(Spanned\\)\\]: #\\[span\\(lo\\)\\] and #\\[span\\(hi\\)\\] is required","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ast_node/src/spanned.rs","lineNumber":207,"sourceCode":"        return simple_field(span_field);\n    }\n\n    let fields: Vec<_> = bindings\n        .iter()\n        .map(|b| (b, MyField::from_field(b.field())))\n        .collect();\n\n    // TODO: Only one field should be `#[span(lo)]`.\n    let lo = fields.iter().find(|&(_, f)| f.lo);\n    let hi = fields.iter().find(|&(_, f)| f.hi);\n\n    match (lo, hi) {\n        (Some((lo_field, _)), Some((hi_field, _))) => {\n            // Create a new span from lo_field.lo(), hi_field.hi()\n            Box::new(parse_quote!(swc_common::Spanned::span(#lo_field)\n                .with_hi(swc_common::Spanned::span(#hi_field).hi())))\n        }\n        _ => panic!(\"#[derive(Spanned)]: #[span(lo)] and #[span(hi)] is required\"),\n    }\n}\n\n/// Search for `#[span]`\nfn has_empty_span_attr(attrs: &[Attribute]) -> bool {\n    attrs.iter().any(|attr| {\n        if !is_attr_name(attr, \"span\") {\n            return false;\n        }\n\n        match &attr.meta {\n            Meta::Path(..) => true,\n            Meta::List(t) => t.tokens.is_empty(),\n            _ => false,\n        }\n    })\n}\n","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/ast_node/src/spanned.rs#L189-L225","documentation":"Compile-time panic from `#[derive(Spanned)]` (crates/ast_node/src/spanned.rs). Once any field has a `#[span(...)]` list attribute, the macro requires exactly one `#[span(lo)]` field and one `#[span(hi)]` field to compose `lo_field.span().with_hi(hi_field.span().hi())`. If either marker is missing, it panics.","triggerScenarios":"Annotating a field with `#[span(lo)]` but forgetting `#[span(hi)]` on another field (or vice versa) in a Spanned-deriving struct.","commonSituations":"Building wrapper nodes whose span starts at one child's start and ends at another child's end and only marking one end.","solutions":["Add the missing marker: one field `#[span(lo)]` and a different field `#[span(hi)]`","If a single field determines the whole span, drop the list attributes and use bare `#[span]` on that field instead"],"exampleFix":"// before\nstruct Range {\n    #[span(lo)]\n    start: Ident,\n    end: Ident,\n}\n\n// after\nstruct Range {\n    #[span(lo)]\n    start: Ident,\n    #[span(hi)]\n    end: Ident,\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whenever you add `#[span(lo)]`, immediately add `#[span(hi)]` on the closing field","If one field suffices, use bare `#[span]` instead of the lo/hi pair"],"tags":["rust","proc-macro","swc","span","derive","compile-time"],"backgroundTag":"proc-macro-misuse","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"}