Refuse a selector on a template before its level fence, give pathCheck one entry over its own tail, and scope the probe decision to descend
This commit is contained in:
+5
-5
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user