Skip to content

fix(objc): remap the field->type table keys with the ids they hold (#3150) - #3170

Closed
abhay-codes07 wants to merge 1 commit into
Graphify-Labs:v8from
abhay-codes07:fix/objc-field-table-remap
Closed

fix(objc): remap the field->type table keys with the ids they hold (#3150)#3170
abhay-codes07 wants to merge 1 commit into
Graphify-Labs:v8from
abhay-codes07:fix/objc-field-table-remap

Conversation

@abhay-codes07

Copy link
Copy Markdown
Contributor

Closes #3150.

The problem

_resolve_objc_member_calls' field→type table (#2591) is the one extractor bucket keyed by class node id. The #1529 passes rewrite node ids, edge endpoints, raw_calls[].caller_nid and swift_extensions[].nid — but never those keys. The prefix strip fires whenever the input paths share an absolute prefix, i.e. always via graphify update <dir> — so the keys went stale, field_types_by_class.get(cls) missed for every class, and [self.<field> …] receiver typing emitted zero edges through the CLI while working in tests, which hand extract() already-relative paths.

The cached shard has the same split, from the same assumption: _rewrite_strings' docstring says "no extractor bucket is keyed by a node id" — this one is — so the portability round-trip re-anchored every id except the table keys.

The change

  • Both in-process remap passes (the id remap and the symbol-prefix remap) rewrite the table keys through the same mapping (_remap_objc_field_tables), right beside the swift_extensions[].nid rewrites they mirror.
  • The cache portability round-trip rewrites the keys beside each _rewrite_strings call (_rewrite_id_keyed_table_keys), on store and on load, and _rewrite_strings' docstring now names the exception instead of denying it.

A note on verification

The staleness only manifests where the prefix strip actually fires — POSIX path resolution, i.e. the Linux CI and every macOS/Linux user of graphify update — not on this Windows dev machine, where the source_file re-resolution misses and ids keep their absolute form (matching keys, by accident). So: the three end-to-end tests (absolute inputs, relative inputs, warm-cache replay) exercise the fix on the Linux CI, and two platform-independent tests carry the teeth locally — the in-process remap unit test and a cache round-trip built with the real _make_id slug, which fails before the fix (key and node id diverge on store) and passes after.

Tests

tests/test_objc_field_table_remap.py — 5 tests as above, using the issue's own four-file corpus. test_objc*, test_swift*, test_cache and test_stat_index_portability are unchanged (132 passed); the full suite matches the fresh v8 (0.9.51) baseline.

Composes with the #3151 fix (separate PR): its inherits-chain walk reads the same table this PR keeps keyed correctly.

…raphify-Labs#3150)

_resolve_objc_member_calls' field-type table (Graphify-Labs#2591) is the one extractor
bucket keyed BY class node id. The Graphify-Labs#1529 passes rewrote node ids, edge
endpoints, raw_calls[].caller_nid and swift_extensions[].nid - but never
those keys - and the prefix strip fires whenever the inputs share an
absolute prefix, i.e. always via `graphify update <dir>`. So the keys went
stale, field_types_by_class.get(cls) missed for every class, and
[self.<field> ...] receiver typing emitted zero edges through the CLI
while working in tests, which hand extract() already-relative paths.

The cached shard had the same split: _rewrite_strings deliberately never
touches dict keys (its docstring even asserted no bucket is keyed by a
node id - this one is), so a replayed shard kept absolute-derived table
keys while the node ids were re-anchored.

Both in-process remap passes now rewrite the table keys through the same
mapping (_remap_objc_field_tables), and the cache portability round-trip
rewrites them beside every _rewrite_strings call
(_rewrite_id_keyed_table_keys), store and load.
Copilot AI lite review requested due to automatic review settings August 28, 2026 14:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. 1 change(s) tested, no difference found (not proven).


Graphify review — findings

Fixes ObjC receiver typing (#2591) that was silently inert through graphify update <dir>: the objc_field_types["tables"] bucket is keyed by class node id, but the #1529 id-remap and the #2257 cache-portability rewrite both left those keys stale whenever a common absolute prefix was stripped, so every field_types_by_class.get(cls) missed and [self.<field> …] sends resolved to nothing. Adds _remap_objc_field_tables to rewrite the table keys through the same id/prefix mappings in extract, and _rewrite_id_keyed_table_keys to re-anchor them alongside _rewrite_strings on cache store and load, keeping the keys in lockstep with the node ids they reference. Covers the CLI absolute-path shape, warm-cache replay, and the store/load round-trip with tests, so the previously test-only-green path is now exercised end to end.

No blocking issues surfaced. 1 lower-confidence candidate did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2005 functions depend on the 312 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 504 callers, 43 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_semantic_cache() — 58 callers, 9 callees
  • new: load_cached() — 48 callers, 7 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: file_hash() — 50 callers, 6 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • …and 35 more — each is listed as a finding

Verification — 2005 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 1857 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_absolutize\_ids\_in.

The verifier did not have enough to check \_absolutize\_ids\_in, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `path` is annotated `'str | Path'` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_relativize\_ids\_in.

The verifier did not have enough to check \_relativize\_ids\_in, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `path` is annotated `'str | Path'` — outside the synthesizable primitive/collection set

No difference found (not proven): No behavior difference found in \_rewrite\_strings (not a proof).

The verifier ran both versions of \_rewrite\_strings on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

· 43 more finding(s) on lines outside this diff (see the check run).

@safishamsi

Copy link
Copy Markdown
Collaborator

Shipped in v0.9.52 via authorship-preserving cherry-pick so you keep contributor-graph credit. Thanks @abhay-codes07! Release: https://github.com/Graphify-Labs/graphify/releases/tag/v0.9.52

@safishamsi safishamsi closed this Aug 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ObjC: #2591 self.<field> receiver typing emits zero edges via the CLI — objc_field_types keys are skipped by the #1529 id remap

3 participants