{"record":{"id":"adb1b4df340330ad","repo":"denoland/deno","slug":"cppgc-inherits-from-specified-more-than-once","errorCode":null,"errorMessage":"cppgc_inherits_from specified more than once","messagePattern":"cppgc_inherits_from specified more than once","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"libs/ops/cppgc.rs","lineNumber":174,"sourceCode":"      {\n        return Ok(());\n      }\n    }\n  }\n  Err(Error::new(\n    span,\n    \"cppgc inheritance requires #[repr(C)] on the type\",\n  ))\n}\n\nfn parse_base_attr(attrs: &[Attribute]) -> Result<Type> {\n  let mut found = None;\n  for attr in attrs {\n    if !attr.path().is_ident(\"cppgc_inherits_from\") {\n      continue;\n    }\n    if found.is_some() {\n      return Err(Error::new(\n        attr.span(),\n        \"cppgc_inherits_from specified more than once\",\n      ));\n    }\n    let base = attr.parse_args::<Type>()?;\n    found = Some(base);\n  }\n  found.ok_or_else(|| {\n    Error::new(\n      proc_macro2::Span::call_site(),\n      \"derive(CppgcInherits) requires #[cppgc_inherits_from(BaseType)]\",\n    )\n  })\n}\n\n#[derive(Clone)]\nenum FieldRef {\n  Named(Ident, proc_macro2::Span),","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/libs/ops/cppgc.rs#L156-L192","documentation":"Thrown by the `CppgcInherits` derive macro (deno_core's cppgc garbage-collector bridge). `parse_base_attr` in libs/ops/cppgc.rs scans the type's attributes for `#[cppgc_inherits_from(Base)]`, stores the first match, and raises this compile error on the span of any second occurrence because a cppgc-managed type can declare exactly one C++ base class.","triggerScenarios":"Annotating one type with two `#[cppgc_inherits_from(...)]` helper attributes: `#[derive(CppgcInherits)] #[cppgc_inherits_from(A)] #[cppgc_inherits_from(B)] struct X;` — the error span points at the duplicate attribute.","commonSituations":"Copy-pasting an existing cppgc type (e.g. the DOMPoint example in ext/web/geometry.rs) and adding a new base without removing the old attribute; merge conflicts that leave both versions of the attribute; attempting multiple inheritance, which cppgc does not support.","solutions":["Delete all but one `#[cppgc_inherits_from(...)]` attribute on the type, keeping the direct base you actually wrap.","If the type genuinely needs two bases, introduce an intermediate Rust/C++ base type that itself derives `CppgcInherits` from the grandparent, and inherit from that single intermediate.","After a merge conflict, grep the file for `cppgc_inherits_from` and make sure only one attribute survives."],"exampleFix":"// before\n#[derive(CppgcInherits, CppgcBase)]\n#[cppgc_inherits_from(DOMPointReadOnly)]\n#[cppgc_inherits_from(CSSStyleValue)]\nstruct DOMPoint { /* ... */ }\n\n// after\n#[derive(CppgcInherits, CppgcBase)]\n#[cppgc_inherits_from(DOMPointReadOnly)]\nstruct DOMPoint { /* ... */ }","handlingStrategy":"validation","validationCode":"# In CI or a pre-commit check, flag types with more than one cppgc_inherits_from:\n# (grep-based guard; the real enforcement is the compile error itself)\n! grep -rn --include='*.rs' -E '^[[:space:]]*#\\[cppgc_inherits_from' path/to/file | awk -F: '{print $1}' | uniq -c | awk '$1 > 1 { exit 1 }'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat `#[cppgc_inherits_from(...)]` as appearing exactly once per type; make that an explicit convention in your code review checklist.","After merge conflicts in cppgc types, grep for `cppgc_inherits_from` and keep only one attribute."],"tags":["cppgc","proc-macro","derive-macro","duplicate-attribute","compile-time"],"backgroundTag":"duplicate-macro-attribute","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}