pub enum CompilationError {
Manifest(Vec<ManifestError>),
Resolution(Vec<Error>),
LoadingFiles(Vec<SourceFileError>),
Source(Error, SourceFileId),
Canonical(Vec<Error>, Name),
Type(Vec<Error>, Name),
Exhaustiveness(Vec<Error>, Name),
Program(Vec<Error>, Name),
DependenciesError(Error),
InFile(Box<CompilationError>, SourceFileId),
Many(Vec<CompilationError>),
}Expand description
Every way checking a package can fail, tagged with the phase that failed.
What can go wrong once a package has checked — emitting it, writing it, running it —
is zelkova::BuildError’s, which wraps this.
Each phase-carrying variant holds all the errors that phase produced for one
module rather than only the first, plus the module’s Name, which is what
as_diagnostic puts in front of the message. Rendering goes through
PhaseError; see that trait for why no variant here carries a span.
Variants§
Manifest(Vec<ManifestError>)
The package’s zelkova.toml is missing, malformed, or fails one of its own
field-level rules (an illegal name, a dependency entry naming no source, …).
Raised before LoadingFiles even runs — a
package’s source root is derived from its manifest, so there is nothing to walk
until the manifest is known good — with one exception:
PrivateModuleNotFound needs the
package’s parsed modules and is pushed after them, and
MainModuleNotFound needs its checked
ones and is pushed after those.
It carries no SourceFileId either way. A manifest error’s location is a byte
range in zelkova.toml, and that file is never read into the database, so each
error names its manifest in its own message instead.
Resolution(Vec<Error>)
The build could not be resolved: a dependency that could not be obtained or read, a circular package graph, or two modules answering to one name in one package.
Like Manifest it carries no
SourceFileId: what each of these errors is about is a zelkova.toml, which
is not a file the database holds, so each names its manifest in its own message.
The graph half is raised before any source is loaded and goes back to the caller
unrendered; the name-collision half is pushed onto check_package’s
accumulator once the packages’ modules are known, and stops that package being
compiled.
LoadingFiles(Vec<SourceFileError>)
Source(Error, SourceFileId)
Canonical(Vec<Error>, Name)
Type(Vec<Error>, Name)
Type checking failed for the named module.
Exhaustiveness(Vec<Error>, Name)
Exhaustiveness checking failed for the named module. Unreachable while
exhaustiveness::check is a stub, but rendered like any other phase.
Program(Vec<Error>, Name)
The named module is its package’s main, checked, and is not fit to be a
program’s entry point (program).
DependenciesError(Error)
InFile(Box<CompilationError>, SourceFileId)
An error together with the file the module it belongs to was read from.
A phase never knows its SourceFileId, so the labels its errors produce are
byte ranges with no file attached. This is where the two halves are put
together, and it has exactly one constructor: check_package, which is
the only place that knows which file a module was parsed from. Nothing else
should build it — an id guessed anywhere else would underline the wrong file.
Many(Vec<CompilationError>)
Several errors, rendered as one summary.
Nothing in the compiler builds it: check_package hands its accumulated errors
back as PackageCheck::errors, and the driver’s own accumulation is
zelkova::BuildError::Many, which holds each of them on its own.
Implementations§
Source§impl CompilationError
impl CompilationError
Sourcepub fn as_diagnostic(&self) -> Diagnostic<SourceFileId>
pub fn as_diagnostic(&self) -> Diagnostic<SourceFileId>
Turn this error into the diagnostic the user reads.
This is the compiler’s single rendering point — nothing else builds a Diagnostic
from a phase error, and zelkova::BuildError::as_diagnostic calls it for
every error of the check. It is public so
that a test can assert on what the user is actually shown, rather than on
is_err(): what a failure says is the behaviour this method exists for.