Skip to content

fix(pipeline): a Go import can resolve to a function or method — 89 false IMPORTS edges, including os/exec → a test helper method #1934

Closed

Description

@ilyabrykau-orca

fix(pipeline): a Go import can resolve to a function or method — the name-guess fallbacks are language-blind

Status: fix open — PR #1938 (both name-guess fallbacks — Strategy 3 symbol-name and Strategy 1b sibling-file — gated on the importing file's language via cbm_import_symbol_fallback_allowed, false for Go). Measured: Go IMPORTS targets Method 85 → 0, Function 4 → 0, Folder 2206 unchanged. Generalises #1926/#1931 (import "C" was the special case).

What happens

A Go import path names a package — never a function, method, field, or a Makefile target. Strategy 1 in cbm_pipeline_resolve_import_node() resolves every correct Go import (module path → package Folder). When it misses — the normal case for stdlib/third-party — the correct result is no edge, but two fallbacks fire instead:

  • Strategy 3 (pass_pkgmap.c): takes the last path segment, cbm_gbuf_find_by_names it project-wide, filters by the permissive import_targetable_label() (admits Function/Method/…, right for Python/Java where imports can name members), returns the lexicographically smallest survivor. import "os/exec" → any project symbol named exec.
  • Strategy 1b (sibling-file resolution) admits symbol labels through the same filter, re-creating the bug one directory closer (found by field census after gating Strategy 3 alone: one surviving os/exec → a same-package exec() method).

Damage measured (~1150-file Go repo)

Go IMPORTS resolved to count
Folder (correct) 2206
Method/Function (false) 89 (3.9%)

Breakdown: os/exec → a test harness's exec method (52); "C" → a test helper's C (27, = #1926); .../wait → a rate limiter's method (6); two imports → a Function extracted from a Makefile (4). Blast radius is confined to the IMPORTS relation (calls in those files resolve via LSP first; only 1 knock-on call edge) — but IMPORTS is what get_architecture and dependency views are built from, where a Go file "depends on" a test harness or a Makefile.

Minimal reproduction

// app/run.go
package app

import "os/exec"

func Run() error { return exec.Command("true").Run() }
// helper/harness.go
package helper

type harness struct{ n int }

func (h *harness) exec(cmd string) error { return nil }
  • go.mod. Expected: os/exec is external → no IMPORTS edge. Actual: edge to helper.harness.exec.

Detection recipe

SELECT t.label, count(*) FROM edges e
JOIN nodes s ON s.id = e.source_id JOIN nodes t ON t.id = e.target_id
WHERE e.type = 'IMPORTS' AND s.file_path LIKE '%.go'
GROUP BY 1 ORDER BY 2 DESC;

For Go, any row that is not Folder/Module/File is false.

Fix (as landed)

The issue's "cheaper first cut": skip both name-guess fallbacks when the importing file is Go — the measurement found no correct Go import that needed either. Member-importing languages (Python from m import f, Java, Kotlin, Rust use crate::ops::helper) keep Strategy 3; build/markup grammars (SCSS partials, Meson subdir, Pony use) keep Strategy 1b. Reproduce-first exact-count probe (ei_edge_count_is — a floor can't catch a fabricated extra edge) with cross-package and same-package decoys.

Related: #1926/#1931, #725, #787; tracked in #1932.

Activity

  1. added a commit that references this issue on Aug 30, 2026
    7d76b88
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    parsing/qualityGraph extraction bugs, false positives, missing edges

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions