Skip to content

Discretise compiler diagnostics

Currently, compiler diagnostics are built using the Diagnostic struct from within the compiler's core. The message is allocated inside the compiler and provided directly as a String. That makes it simple to create new diagnostics but has a few issues:

  • It's hard to refer to a unique diagnostic "type" (mismatched type, syntax error, missing argument, ...), as the only identity of an error is the line its diagnostic is created at
    • Having a numeric error code is much easier to Google or seek help on an online index (e.g. Rust's error code index)
  • It's near-impossible to localize errors for different languages if we ever had to do that
  • It bloats the core of the compiler with user-facing, almost UI-related, code
    • We're using Diagnostic as an abstraction over ariadne but over time we might tend to just reimplement ariadne's API
    • This also requires allocating more memory from within the compiler
  • It makes it super hard for compiler drivers to understand the diagnostics as they're directly emitted in human form
    • It also makes it hard for external tool to be one day able to receive diagnostics in stdout but as a machine format (e.g. Rust's JSON output)
    • Same remark for language servers
    • Same remark for "quick fix" features of language servers. Generating quick-fixes from inside the compiler would be ridiculous
  • It's hard to categorize errors/warnings, notably to be able to granularly disable the latter

Ideally, our diagnostics would be represented as a big enum, or a boxed dyn trait, and all presentation-related stuff would be the problem of user-facing drivers (incl. quick fixes).

Doing this today would be a bad idea as we don't really have enough hindsight on all errors we may emit.

Possibly interesting reads (yeah I like Rust how would you guess?):

Edited by Edgar Onghena