An escaped diagnostic says which file and which line, not (_)
Three suite runs left "Fatal error: exception Flan.Loc.Error(_)" on stderr: OCaml's default handler knows nothing about the diag record, so a process that does not catch prints a constructor name and none of the message. The trigger was a corpus file the test binaries check directly and nothing there wraps. Registering a Printexc printer changes no control flow and costs the drivers that do catch nothing; it only makes the corpse legible.
This commit is contained in:
parent
ac7ee912e7
commit
223e282e44
25
lib/loc.ml
25
lib/loc.ml
@ -359,8 +359,8 @@ let report (d : diag) =
|
||||
it found. *)
|
||||
let report_all (ds : diag list) =
|
||||
(* Source order, with the placeless ones last. A diagnostic the checker
|
||||
raised against [unknown] — a wrong [main] signature is the one that
|
||||
happens — has line 0, and sorting on the number alone would put it at the
|
||||
raised against [unknown] — a rule about a declaration that is not in this
|
||||
file to point at — has line 0, and sorting on the number alone would put it at the
|
||||
top of the list, above every error that can actually be clicked. It is a
|
||||
real error and it is not anywhere, so it goes after the ones that are. *)
|
||||
let placed (d : diag) = d.dloc.line > 0 in
|
||||
@ -376,3 +376,24 @@ let report_all (ds : diag list) =
|
||||
let n = List.length ds in
|
||||
String.concat "\n" (List.map report ds)
|
||||
^ Printf.sprintf "\n%d error%s" n (if n = 1 then "" else "s")
|
||||
|
||||
(* The last line of defence, and the one nobody plans to reach. Every driver in
|
||||
this tree catches [Error] and [Errors] and prints [report]; a process that
|
||||
does not — a test binary walking the corpus, a tool written in an afternoon —
|
||||
dies through OCaml's default handler, and the default handler knows nothing
|
||||
about this record. What it prints is [Fatal error: exception
|
||||
Flan.Loc.Error(_)]: the name of a constructor, an underscore, and not one
|
||||
word of the diagnostic that was carefully built to say what was wrong and
|
||||
where. That is how three suite runs came to leave a message-less fatal on
|
||||
stderr while reporting that they had passed.
|
||||
|
||||
Registering a printer costs nothing and cannot change control flow — the
|
||||
exception still propagates and still kills whatever did not catch it. All it
|
||||
changes is that the corpse says which file and which line, which is the
|
||||
whole of what the diagnostic was for. Drivers that do catch are unaffected:
|
||||
they never ask [Printexc] anything. *)
|
||||
let () =
|
||||
Printexc.register_printer (function
|
||||
| Error d -> Some (report d)
|
||||
| Errors ds -> Some (report_all ds)
|
||||
| _ -> None)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user