From b3cc37be261493a6bd3a8ccc595dea3204c0bab7 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Tue, 29 Sep 2026 13:44:08 +0200 Subject: [PATCH] Report a pin clash in readSurvey.edge as a load error, not a panic --- readsurvey.go | 23 +++++++++++++++-------- todo.md | 4 ---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/readsurvey.go b/readsurvey.go index 634ca83..a40e81b 100644 --- a/readsurvey.go +++ b/readsurvey.go @@ -11,6 +11,7 @@ type readSurvey struct { reads []pathRead read map[readKey]bool seen map[nodeVisit]bool + clash error } // surveyAt is where a survey stands: the draw group its reads draw in, how the render's root reached it, the @@ -122,12 +123,14 @@ func (s *readSurvey) edge(from node, e renderEdge, at surveyAt) { s.reads = append(s.reads, pathRead{at, a, tr}) } if tr != nil { - tr.pins.each(func(t *table, r int) { - if c := at.pins.clash(t, r); c != nil { - panic(internalError("%s reads %s past a pinned row of %s, which checkOwnFamily refuses", e.reached(), t.selectorSpelling(r), c.path)) + pins := at.pins.clone() + if err := tr.replay(&pins); err != nil { + if s.clash == nil { + s.clash = conflict(pathRead{at, a, tr}, err) } - at.pins = at.pins.entered(t, r) - }) + return + } + at.pins = pins } } s.walk(e.to, at) @@ -209,10 +212,14 @@ func (r *tableRead) replay(d *pinSet) error { return err } -// check refuses what one draw per reference path cannot answer for: a read of a level beside a path -// another read takes into it, and two reads of one table family that select different rows. Reads -// are compared in path order, so which pair is reported does not vary. +// check refuses what one draw per reference path cannot answer for: a read selecting a row its route +// pinned another of, a read of a level beside a path another read takes into it, and two reads of one +// table family that select different rows. Reads are compared in path order, so which pair is +// reported does not vary. func (s *readSurvey) check() error { + if s.clash != nil { + return s.clash + } sort.SliceStable(s.reads, func(i, j int) bool { if s.reads[i].at.group != s.reads[j].at.group { return s.reads[i].at.group < s.reads[j].at.group diff --git a/todo.md b/todo.md index 1811fdc..3033c48 100644 --- a/todo.md +++ b/todo.md @@ -34,10 +34,6 @@ ranking `readSurvey.walk` and `edge` hardest and the unit they would least modif This round, in order: -- Make `readSurvey.edge` sound whatever order `checkNodeFences` runs its fences in: - report the pin clash as a load error, or have `checkDraws` run `checkOwnFamily` over - the scope before its survey, and delete the panic naming `checkOwnFamily`. All nine - seats found the survey sound only by a call order stated in that panic's text. - Test that `render` and `renderEdges` agree on every node kind, and each of the switches `node`'s comment lists, so a kind one of them misses fails a test: five seats, both architects among them, found the mirror held by comments alone.