fix(c,cpp): a pointer, array or function member is not a supertype (#2394)

extractInheritance carried Go's struct-embedding check (a field_declaration
with no direct field_identifier names an embedded type) into every grammar
with a field_declaration_list. tree-sitter-c/cpp, and Objective-C's C
structs, nest a member's field_identifier inside its pointer/array/
function/reference declarator, so `SharedState* shared;`, `jv elements[];`
and `virtual Status Put(...) = 0;` all became `extends` edges to the
member's type: false supertypes in the type hierarchy, blast radius and
codegraph_explore, and false cpp-override call edges built on them
(google/leveldb: 246 of 302 extends edges).

Gate the branch to Go in the TS extractor, drop the mirrored arm from the
C/C++ kernel port (and the "kept for parity" quirk note), and drop the
inert copy from the Rust-language port. C++ base_class_clause, Objective-C
superclasses and Go embedding are unchanged.

Validated on leveldb, jq, llm.c and redis: every removed extends edge is a
member site, no base-clause edge is lost; gin, SDWebImage and ripgrep
dumps are byte-identical; kernel/wasm parity sweeps show 0 diffs.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-10-06 23:27:58 +00:00
committed by GitHub
parent 0a670dc8cc
commit ac1f430d3e
7 changed files with 292 additions and 45 deletions
+4 -21
View File
@@ -33,11 +33,6 @@
//! (loses uninit scalars by design); cpp declarations instead take the TS
//! GENERIC fallback (direct identifier children only → `int x;` extracts,
//! `int x = 5;` does not — bug-for-bug).
//! - inheritance quirk: extractInheritance recurses into
//! field_declaration_list, where a field_declaration with no DIRECT
//! field_identifier child (pointer/array/method members) but a direct
//! type_identifier emits an `extends` ref to that type (the Go-embedding
//! branch matching c/cpp shapes). Kept: the parity gate pins today's graph.
//! - static-member/value-read pass (cpp only): `field_expression` is in
//! MEMBER_ACCESS_TYPES (listed for Scala, same node kind in cpp), so
//! `Capitalized.member` / `Capitalized->member` VALUE reads emit
@@ -1866,8 +1861,10 @@ impl<'t> Walker<'t> {
// --- inheritance ---------------------------------------------------------
/// extractInheritance — the branches whose node kinds occur in the c/cpp
/// grammars: base_class_clause (#1043), the field_declaration Go-embedding
/// shape, and the field_declaration_list recursion that reaches it.
/// grammars: base_class_clause (#1043) and the field_declaration_list
/// recursion. A member `field_declaration` is never a supertype: the TS
/// Go-embedding check is gated to Go, since c/cpp members nest their
/// field_identifier inside a pointer/array/function declarator.
fn extract_inheritance(&mut self, node: Node<'t>, class_row: u32) {
stack_guard!();
let extends_kind = edge_kind_index("extends").unwrap();
@@ -1886,20 +1883,6 @@ impl<'t> Walker<'t> {
}
}
}
"field_declaration" => {
let has_field_identifier = (0..child.named_child_count())
.filter_map(|j| child.named_child(j))
.any(|c| c.kind() == "field_identifier");
if !has_field_identifier {
let type_id = (0..child.named_child_count())
.filter_map(|j| child.named_child(j))
.find(|c| c.kind() == "type_identifier");
if let Some(type_id) = type_id {
let name = self.text(type_id).to_string();
self.push_ref_at(class_row, &name, extends_kind, type_id);
}
}
}
"field_declaration_list" | "class_heritage" => {
self.extract_inheritance(child, class_row);
}
+3 -17
View File
@@ -1061,9 +1061,9 @@ impl<'t> Walker<'t> {
/// extractInheritance — the rust-reachable cases: trait_bounds
/// (supertraits; a scoped `fmt::Debug` bound matches NO case and is
/// dropped), the Go embedding check on field_declaration (inert in rust —
/// every field has a field_identifier), and the field_declaration_list
/// recursion that reaches it.
/// dropped) and the field_declaration_list recursion. The TS Go-embedding
/// check on field_declaration is gated to Go (and was inert here anyway —
/// every rust field has a field_identifier).
fn extract_inheritance(&mut self, node: Node<'t>, class_row: u32) {
stack_guard!();
let extends_kind = edge_kind_index("extends").unwrap();
@@ -1102,20 +1102,6 @@ impl<'t> Walker<'t> {
}
}
}
"field_declaration" => {
let has_field_identifier = (0..child.named_child_count())
.filter_map(|j| child.named_child(j))
.any(|c| c.kind() == "field_identifier");
if !has_field_identifier {
let type_id = (0..child.named_child_count())
.filter_map(|j| child.named_child(j))
.find(|c| c.kind() == "type_identifier");
if let Some(type_id) = type_id {
let name = self.text(type_id).to_string();
self.push_ref_at(class_row, &name, extends_kind, type_id);
}
}
}
"field_declaration_list" | "class_heritage" => {
self.extract_inheritance(child, class_row);
}