Repository navigation
Conversation
wire.Bind(new(I), new(T)) records that a provider set or injector binds
interface I to concrete T. That fact lives only in the injector source,
so the graph could not say which provider set selects which
implementation.
For Go files that import github.com/google/wire (aliases honored, dot and
blank imports skipped), each <local>.Bind call whose two args are
new([*]Ident) or new([*]pkg.Ident) emits a BINDS edge:
- source: the innermost package-level Variable containing the call
(var Set = wire.NewSet(...)), else the enclosing Function (injector)
- target: T, resolved exactly to a type-like node via the file's
package or import map; no edge when T is not in the graph
- props: {"strategy":"wire_bind","interfaces":[QN...],
"unresolved_interfaces":[raw...]}, sorted and deduplicated
All interfaces bound to the same (source, target) share one edge,
because edges dedupe on (source, target, type).
Emitted next to the env CONFIGURES helper at the sequential, parallel
and incremental sites.
Refs DeusData#2444
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Tony Thayer-Osborne <962968+tthayer@users.noreply.github.com>
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
|
Thank you for the detailed coverage measurements, explicit unresolved cases, and for keeping this draft pending the decision in #2444. We need more time to review the proposed BINDS graph contract and its indexing semantics. There is no design approval or merge commitment yet. The separate Go extraction fix #2453 can be reviewed independently. The queue is quite full, and we appreciate your patience while we give community contributions the review they deserve. |
Part (1) of #2444. Draft pending design sign-off on the issue (new edge type).
Problem
wire.Bind(new(I), new(T))is the only place a Wire codebase records which concrete type satisfies an interface for a given provider set or injector. The graph has no edge for it:IMPLEMENTS/OVERRIDEsay T can satisfy I.CALLSintowire_gen.goconstructors say what a binary constructs.Neither says which provider set selects T for I. That is what separates
*localWriterfrom*s3Writerin the issue's example.Change
In Go files that import
github.com/google/wire(aliases honored; dot/blank imports skipped), each<local>.Bind(new(I), new(T))emits:Variablewhose span contains the call (var Set = wire.NewSet(...), multi-line OK), else the enclosingFunction(wire.Buildin an injector).new(*T)ornew(T), bare orpkg.T) resolved exactly through the file's package or import map to a type-like node. There is no fallback: if T is not in the graph, no edge is emitted and a debug skip is logged.new([*]Ident)ornew([*]pkg.Ident). Anything else (generics, parenthesized, non-new) is skipped and logged.unresolved_interfacesas written.CONFIGUREShelper at the sequential, parallel and incremental sites. No new pass, no schema change.cbm_alloc-backedyyjson_alc, solint-memory-core.pybaselines are unchanged.Tests
In
tests/test_pipeline.c:pipeline_wire_bind_edges_sequential_parallel_incremental: same-packageLocalSet, cross-packagenew(store.ObjectWriter), new(*store.S3Writer), and an injectorwire.Build(wire.Bind(...)). Asserts identical edges forCBM_INDEX_SINGLE_THREAD=1,CBM_WORKERS=4(padded past the parallel threshold) and incremental reindex.pipeline_wire_bind_multi_interface_single_edge: one set binds*Tto an in-repo interface twice plusio.Writer. Expects 1 edge, the QN ininterfaces, andio.Writerinunresolved_interfaces.pipeline_wire_bind_negative_controls: each of the following yields 0 edges:wirevaluedi "github.com/google/wire"called aswire.Bind(whiledi.Bindyields 1)newargumentsBINDSis added to the edge-type lists intest_edge_structural.c,test_lang_contract.candtest_convergence_probe.c.Results (darwin arm64):
scripts/test.sh --suites pipeline,edge_structural,lang_contract,convergence_probe,incremental: 586 passed, 0 failed.--suites): 8254 passed, 0 failed, 10 skipped. Defaultscripts/test.shstops at step 0x on the scoop manifest pin (pkg/scoop/codebase-memory-mcp.jsonat 0.11.0), a static check this diff does not touch (nopkg/changes).lint-memory-core.py, clang-format,lint-tidy-diffand cppcheck on the changed files: clean.Measured on google/wire's own testdata
internal/wire/testdatais skipped by discovery (testdata), so the 14 cases that callwire.Bindwere copied out and indexed one by one, withmain(80eb92a) and this branch as a paired control.Nodes and other edge types: identical, 229 nodes on both. Edges went from 478 to 483, and that +5 is entirely
BINDS.Edges emitted (5):
InterfaceBinding,ImportedInterfaceBinding,InterfaceBindingReuse(injector source),ReturnArgumentAsInterface(fmt.Stringer, reported as unresolved) andExampleWithMocks.Correctly no edge (5): the concrete type is external or builtin in
BindInterfaceWithValue(*os.File),MultipleBindings(*strings.Reader) andInterfaceBindingDoesntImplement(string);InterfaceBindingInvalidArg0passes non-newargs;InterfaceBindingNotEnoughArgspasses one arg.Missed (4), both pre-existing Go extraction bugs that this PR does not fix:
BindInjectorArg,BindInjectorArgPointer,UnusedProviders: Go method QNs carry no receiver (Go: method QNs ignore the receiver — every same-name method in a package collapses onto one node #1909; fix in fix(extract): receiver-qualify Go method QNs #1913), sofunc (f Foo) Foo()shares the QN oftype Foo. The node ends up labeledMethodand fails the type-like check.ProviderSetBindingMissingConcreteType:var ( ... )groups nestvar_specundervar_spec_list, andextract_vars_mainstreamonly reads direct children. So grouped package-level vars get noVariablenode, and the bind has no source.The grouped-
varfix is fix(go): extract Variables from grouped var ( ... ) declarations #2453. Both fixes change Go extraction beyond Wire.On a private Go monorepo (368
wire.Bindcalls, all shapednew(pkg.I), new(*pkg.T)), this branch emits 340BINDSedges: 292 from provider-set variables and 48 from injector functions.What this does not do
new(*mux.Router)) get no edge. The target must exist in the graph.wire.InterfaceValue,wire.Struct,wire.Value,wire.FieldsOfare not handled.mainlinking and binding-awaretrace_pathare separate follow-ups.new(...)are skipped.Size
+579/−4. 236 lines are the test in
test_pipeline.c, and 329 arepass_definitions.c. The source side is one cohesive feature, so I did not split it further.Written with Claude Code (Anthropic). I reviewed the change and am accountable for it.