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:
2026-09-28 00:36:33 +02:00
committed by Lillem4n
parent d95045f4ac
commit 060fb42fee
3 changed files with 12 additions and 7 deletions
+5 -5
View File
@@ -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.
+1 -1
View File
@@ -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
}
+6 -1
View File
@@ -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
}