A sink collects what a pass found so the pass can go on to the next thing. It is switched on by the caller, not by the code that raises, which is what leaves the interactive path untouched: the daemon checks one form, asks for a sink that is off, and still gets one exception. Two resync points, and both are places the work already had a boundary. In the parser it is a top-level form — the reader found where each declaration ends, so skipping a bad one cannot lose its place, while inside a declaration there is no such landmark and one bad defn stays one error. In the checker it is the two passes: pass one, which builds every name and signature, still stops at the first refusal, because a signature it could not make sense of leaves a hole that pass two would report once per mention. Thirty unknown-name lines under one wrong signature are not thirty errors. Pass two is where the volume is and where collecting pays, and by then every signature is sound, so a body that fails cannot make the next body fail. That is what makes a declaration a resync point needing no resynchronising.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%