diff --git a/docs/decisions.md b/docs/decisions.md index a5b1d4f..5575527 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -688,8 +688,8 @@ though `hasRead` states the same stop rule. Valid while the two differ in where 2026-09-28, larv-review on systems-architect's finding; awaiting approval. Goals 2 and 11: `pathCheck`, `pathCover`, `pathProbe` and `pathDraw` each loop over `stepInto` and -`table.route` themselves, and `descend` and `tableReadOf` build their probe in place, so -its `drawn` map stays on the stack. One walk calling them through an interface or a type parameter -leaks the walker and the pins it holds, an allocation per reference read. Valid while Go's -escape analysis treats a call through an interface or a type parameter as leaking its -receiver. +`table.route` themselves, and `descend` builds its probe in place, so the probe's +`drawn` map stays on the stack. One walk calling them through an interface or a type +parameter leaks the walker and the pins it holds, an allocation per reference read. +Valid while Go's escape analysis treats a call through an interface or a type parameter +as leaking its receiver. diff --git a/graph.go b/graph.go index 25c40ce..bc7856d 100644 --- a/graph.go +++ b/graph.go @@ -165,7 +165,7 @@ func renderEdges(n node) []renderEdge { // already proved the tail resolves in every variant. func pathLeaves(n node, tail []string) []node { w := &pathCheck{tail: tail} - _, _ = w.walk(n, tail) + _, _ = w.run(n) return w.leaves } diff --git a/path.go b/path.go index 02ab643..ee3d118 100644 --- a/path.go +++ b/path.go @@ -196,6 +196,8 @@ type pathCheck struct { leaves []node } +func (w *pathCheck) run(n node) (node, error) { return w.walk(n, w.tail) } + func (w *pathCheck) walk(n node, tail []string) (node, error) { for descended := false; len(tail) > 0 || descended; { var err error @@ -215,6 +217,9 @@ func (w *pathCheck) walk(n node, tail []string) (node, error) { n, tail, descended = r.next, r.rest, r.descends continue case *template: + if isSelector(tail[0]) { + break + } if err := w.enter(x, tail); err != nil { return nil, err } @@ -452,6 +457,6 @@ func unreachableInChoice(c *choice, want string) error { // checkPath proves a dotted tail as pathCheck does, so a path that validates here // resolves on every render, and a typo is a New-time error. func checkPath(n node, tail []string, level string) error { - _, err := (&pathCheck{level: level, tail: tail}).walk(n, tail) + _, err := (&pathCheck{level: level, tail: tail}).run(n) return err }