Skip to content

fix(go): resolve same-file member calls through receiver types - #4966

Open
xiongjianxu wants to merge 1 commit into
Graphify-Labs:v8from
xiongjianxu:fix/go-receiver
Open

xiongjianxu wants to merge 1 commit into
Graphify-Labs:v8from
xiongjianxu:fix/go-receiver

Conversation

@xiongjianxu

@xiongjianxu xiongjianxu commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

a.apply() could bind to B.apply even when a was declared as *A; method declaration order chose the target. A method could also capture a bare call to a package-level function. Route member calls through receiver-aware resolution and exclude methods from local/global bare-call candidates.

Receiver types follow lexical scope and declaration order. Unknown local bindings block package-variable fallback, fields resolve through their owning struct, and direct calls take priority over method-value references. Generic receiver bindings and explicit T.M(t) / (*T).M(t) expressions use their declared types. Unknown or ambiguous receivers remain unresolved.

Same-file member calls now carry INFERRED confidence, matching cross-file receiver resolution; same-file bare function calls retain EXTRACTED. AST cache schema advances from 36 to 37. The historical schema regression keeps a lower bound without requiring an old issue number in the current assignment's comment.

Scope: this improves extraction within the visible corpus. It does not add complete Go package/import resolution, package-qualified type inference or general return-type inference. global add continues to use existing parked-call hints rather than rerunning receiver inference.

Validation after rebasing onto v8 8e6a6d21, using the existing macOS environment without installing dependencies:

  • New same-file module against the unmodified upstream implementation: 38 failed, 2 passed.
  • Targeted Go, cache and architecture checks across 18 modules: 343 passed, 1 skipped.
  • Ruff and git diff --check: passed; added Python lines are at most 120 Unicode code points.
  • Scoped Pyright reports 148 errors, with no diagnostics on added or modified lines; existing type errors remain.
  • AST-only python -m graphify update . --no-cluster: succeeded. Generated graphs and caches are excluded.

Coordinated full-suite validation on v8 8e6a6d21 used UV_OFFLINE=1 PYTHONHASHSEED=0 python -m pytest tests -q --tb=short --disable-warnings, with PYTHONPATH pointing to each checkout: baseline 9,094 passed / 15 failed, all four changes combined 9,224 passed / 15 failed, with identical failure lists and zero added failures. Both had 357 skipped and 1 xfailed. The 15 baseline failures cover SQL grammar, wheel-build dependency, shell-parser control and Terraform parallel-cache cases. Combined full Pyright had 704 errors / 4 warnings versus baseline 705 / 4, with zero added diagnostics. Combined validation uses cache schema 39 to keep its namespace separate from the individual extraction patches.

Closes #4962

@github-actions github-actions Bot added the contributor Pull request from a returning community contributor label Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown

Thanks for the pull request, @xiongjianxu. A maintainer will review it soon.

Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions.

A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic.

Resolve same-file member calls through declared receiver types, preserve lexical receiver bindings, and keep bare package calls distinct from methods.

Refs Graphify-Labs#4962

@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.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.

Not checked: tests were not run; no formal proof of the changed code.


Graphify review — findings

Reworks Go member-call resolution so x.Method() binds through the receiver's declared type, same-file calls included, and carries INFERRED confidence, while bare package-level function calls stay EXTRACTED. The receiver-type table is now built with lexical scopes, so each call picks up the type in effect at its site, and receivers with unknown or ambiguous types no longer fall back to binding by method name. Bumps the AST cache schema to 37 so Go extractions made under the old binding rules are re-run.

Worth a look

  • Receiver table no longer records locals declared inside function bodies — graphify/extractors/go.py:221 · Escalate · high
    • NOT verified (no proof, no reproducing execution) — needs human review
  • Go call filter reads key 'language' while neighboring code reads 'lang' — graphify/extract.py:11228 · Escalate · medium
    • NOT verified (no proof, no reproducing execution) — needs human review
  • Block-scoped Go declarations leak into the enclosing function's receiver table — graphify/extractors/go.py:992 · Escalate · medium
    • NOT verified (no proof, no reproducing execution) — needs human review

Review partial — this diff was larger than one review pass covers, so later files were not reviewed; some findings may be missing.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 4606 functions depend on the 558 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: extract() — 1117 callers, 66 callees

Verification — 4606 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: 3982 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

502 of 502 test file(s) selected (100%) via static blast radius.

Escalated to a full run for safety — the selection is not trustworthy on its own (see below). CI should run the whole suite.

  • tests/pi.test.ts — full-run-safety
  • tests/test_4874_jvm_resolution.py — impact, full-run-safety
  • tests/test_4909_reference_binding_scale.py — full-run-safety
  • tests/test_affected_cli.py — full-run-safety
  • tests/test_affected_defines.py — full-run-safety
  • tests/test_affected_member_seed.py — full-run-safety
  • tests/test_affected_overrides.py — impact, full-run-safety
  • tests/test_affected_path_file_node.py — full-run-safety
  • tests/test_affected_seed_reference_forms.py — full-run-safety
  • tests/test_agents_platform.py — full-run-safety
  • tests/test_alias_folding.py — impact, full-run-safety
  • tests/test_analyze.py — impact, full-run-safety
  • tests/test_anthropic_custom_endpoint.py — full-run-safety
  • tests/test_antigravity_install.py — full-run-safety
  • tests/test_apm_fallback_version.py — full-run-safety
  • tests/test_architecture_doc.py — full-run-safety
  • tests/test_astro_extraction.py — impact, full-run-safety
  • tests/test_astro_import_ids.py — impact, full-run-safety
  • tests/test_atomic_canvas_export.py — full-run-safety
  • tests/test_atomic_version_stamp.py — full-run-safety
  • tests/test_atomic_writes.py — full-run-safety
  • tests/test_backend_env_isolation.py — full-run-safety
  • tests/test_backend_extras.py — full-run-safety
  • tests/test_backend_opt_in.py — full-run-safety
  • tests/test_benchmark.py — full-run-safety
  • tests/test_benchmark_raw_graph.py — full-run-safety
  • tests/test_benchmark_real_query.py — full-run-safety
  • tests/test_binary_media_words.py — impact, full-run-safety
  • tests/test_blade_extractor.py — impact, full-run-safety
  • tests/test_build.py — impact, full-run-safety
  • tests/test_build_located_semantic_identity.py — impact, full-run-safety
  • tests/test_build_merge_dedup_scope.py — impact, full-run-safety
  • tests/test_build_merge_hyperedges_and_prune.py — impact, full-run-safety
  • tests/test_build_merge_shrink_guard.py — impact, full-run-safety
  • tests/test_builtin_global_type_refs.py — impact, full-run-safety
  • tests/test_c_include_resolution.py — impact, full-run-safety
  • tests/test_cache.py — impact, full-run-safety
  • tests/test_cache_long_paths.py — impact, full-run-safety
  • tests/test_cache_stale_import_target.py — impact, full-run-safety
  • tests/test_cache_windows_case_4925.py — impact, full-run-safety
  • tests/test_callflow_html.py — full-run-safety
  • tests/test_cargo_introspect.py — full-run-safety
  • tests/test_cargo_missing_manifest.py — full-run-safety
  • tests/test_carried_hyperedge_remap.py — impact, full-run-safety
  • tests/test_case_only_decl_ids_4904.py — impact, full-run-safety
  • tests/test_case_sensitive_resolution.py — impact, full-run-safety
  • tests/test_charmap_encoding.py — impact, full-run-safety
  • tests/test_chunking.py — impact, full-run-safety
  • tests/test_cjs_module_extension.py — impact, full-run-safety
  • tests/test_claude_cli_backend.py — full-run-safety
  • … and 452 more

non-code file(s) changed (ARCHITECTURE.md) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (ARCHITECTURE.md) — a coverage gap or a missing link — running the full suite rather than only the selected tests

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

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

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor Pull request from a returning community contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go same-file member calls can resolve to a method on the wrong receiver type

1 participant