Change how diagnostics are ordered (#4778)

This change deliberately breaks away from the line/column ordering, and
instead focuses on a last byte offset corresponding to the final token
processed as part of producing the message. Where that's equal, this
maintains stable ordering in order to reflect the order that diagnostics
were produced.

The intent of this approach is that lex, parse, and check diagnostics
are interleaved based on where they are produced, but that
subexpressions still have diagnostics emitted prior to containing
expressions. In particular, the prior line/column sort essentially
sorted on the _start_ of where a diagnostic was associated, and this is
closer to sorting based on the _end_. As a consequence, something like
`F(1 2)` will have the error for `1 2` emitted _before_ a diagnostic for
`F(1 2)` not matching parameters, instead of _after_.

In check, we track the last handled node. This provides a
last_byte_offset _separate_ from where a diagnostic is associated. The
intent is that this creates an ordering of diagnostics which may be
associated with earlier code, to cause the diagnostics to be emitted
later. An example consequence of this is the change in ordering of
modifier diagnostics: we are diagnosing those from the same place, but
they have the same last_byte_offset, so we print them out in the order
produced.

I've added similar tracking to parse, but cannot identify any test which
is affected by it (note the separate commit, I thought about this late).
I'm not sure whether we have good out-of-order errors we could produce
for this.

A significant number of tests have reordered diagnostics as a
consequence of this change, so this change does not add further testing.
This commit is contained in:
Jon Ross-Perkins
2025-01-10 18:36:24 +00:00
committed by GitHub
parent be85a5092d
commit 8f685b6953
39 changed files with 436 additions and 319 deletions
+2 -2
View File
@@ -13,8 +13,8 @@ namespace Carbon {
namespace {
struct FilenameConverter : DiagnosticConverter<llvm::StringRef> {
auto ConvertLoc(llvm::StringRef filename, ContextFnT /*context_fn*/) const
-> DiagnosticLoc override {
return {.filename = filename};
-> ConvertedDiagnosticLoc override {
return {.loc = {.filename = filename}, .last_byte_offset = -1};
}
};
} // namespace