Skip to content

Commit 044b57f

Browse files
authored
cranelift-isle: Rewrite error reporting (#5318)
There were several issues with ISLE's existing error reporting implementation. - When using Miette for more readable error reports, it would panic if errors were reported from multiple files in the same run. - Miette is pretty heavy-weight for what we're doing, with a lot of dependencies. - The `Error::Errors` enum variant led to normalization steps in many places, to avoid using that variant to represent a single error. This commit: - replaces Miette with codespan-reporting - gets rid of a bunch of cargo-vet exemptions - replaces the `Error::Errors` variant with a new `Errors` type - removes source info from `Error` variants so they're easy to construct - adds source info only when formatting `Errors` - formats `Errors` with a custom `Debug` impl - shares common code between ISLE's callers, islec and cranelift-codegen - includes a source snippet even with fancy-errors disabled I tried to make this a series of smaller commits but I couldn't find any good split points; everything was too entangled with everything else.
1 parent 48ee42e commit 044b57f

File tree

18 files changed

+338
-544
lines changed

18 files changed

+338
-544
lines changed

Cargo.lock

Lines changed: 11 additions & 94 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cranelift/codegen/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ criterion = "0.3"
4040
[build-dependencies]
4141
cranelift-codegen-meta = { path = "meta", version = "0.91.0" }
4242
cranelift-isle = { path = "../isle/isle", version = "=0.91.0" }
43-
miette = { version = "5.1.0", features = ["fancy"], optional = true }
4443

4544
[features]
4645
default = ["std", "unwind"]
@@ -101,7 +100,7 @@ incremental-cache = [
101100
souper-harvest = ["souper-ir", "souper-ir/stringify"]
102101

103102
# Provide fancy Miette-produced errors for ISLE.
104-
isle-errors = ["miette", "cranelift-isle/miette-errors"]
103+
isle-errors = ["cranelift-isle/fancy-errors"]
105104

106105
# Put ISLE generated files in isle_generated_code/, for easier
107106
# inspection, rather than inside of target/.

cranelift/codegen/build.rs

Lines changed: 20 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// current directory is used to find the sources.
1616

1717
use cranelift_codegen_meta as meta;
18+
use cranelift_isle::error::Errors;
1819

1920
use std::env;
2021
use std::io::Read;
@@ -288,13 +289,16 @@ fn build_isle(
288289
}
289290

290291
if let Err(e) = run_compilation(compilation) {
291-
eprintln!("Error building ISLE files: {:?}", e);
292-
let mut source = e.source();
293-
while let Some(e) = source {
294-
eprintln!("{:?}", e);
295-
source = e.source();
296-
}
297292
had_error = true;
293+
eprintln!("Error building ISLE files:");
294+
eprintln!("{:?}", e);
295+
#[cfg(not(feature = "isle-errors"))]
296+
{
297+
eprintln!("To see a more detailed error report, run: ");
298+
eprintln!();
299+
eprintln!(" $ cargo check -p cranelift-codegen --features isle-errors");
300+
eprintln!();
301+
}
298302
}
299303
}
300304

@@ -311,21 +315,16 @@ fn build_isle(
311315
///
312316
/// NB: This must happen *after* the `cranelift-codegen-meta` functions, since
313317
/// it consumes files generated by them.
314-
fn run_compilation(
315-
compilation: &IsleCompilation,
316-
) -> Result<(), Box<dyn std::error::Error + 'static>> {
318+
fn run_compilation(compilation: &IsleCompilation) -> Result<(), Errors> {
317319
use cranelift_isle as isle;
318320

319321
eprintln!("Rebuilding {}", compilation.output.display());
320322

321-
let code = (|| {
322-
let lexer = isle::lexer::Lexer::from_files(
323-
compilation
324-
.inputs
325-
.iter()
326-
.chain(compilation.untracked_inputs.iter()),
327-
)?;
328-
let defs = isle::parser::parse(lexer)?;
323+
let code = {
324+
let file_paths = compilation
325+
.inputs
326+
.iter()
327+
.chain(compilation.untracked_inputs.iter());
329328

330329
let mut options = isle::codegen::CodegenOptions::default();
331330
// Because we include!() the generated ISLE source, we cannot
@@ -335,62 +334,8 @@ fn run_compilation(
335334
// https://github.com/rust-lang/rust/issues/47995.)
336335
options.exclude_global_allow_pragmas = true;
337336

338-
isle::compile::compile(&defs, &options)
339-
})()
340-
.map_err(|e| {
341-
// Make sure to include the source snippets location info along with
342-
// the error messages.
343-
344-
#[cfg(feature = "isle-errors")]
345-
{
346-
let report = miette::Report::new(e);
347-
return DebugReport(report);
348-
349-
struct DebugReport(miette::Report);
350-
351-
impl std::fmt::Display for DebugReport {
352-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
353-
self.0.handler().debug(&*self.0, f)
354-
}
355-
}
356-
357-
impl std::fmt::Debug for DebugReport {
358-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
359-
std::fmt::Display::fmt(self, f)
360-
}
361-
}
362-
363-
impl std::error::Error for DebugReport {}
364-
}
365-
#[cfg(not(feature = "isle-errors"))]
366-
{
367-
return DebugReport(format!("{}", e));
368-
369-
struct DebugReport(String);
370-
371-
impl std::fmt::Display for DebugReport {
372-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
373-
writeln!(f, "ISLE errors:\n\n{}\n", self.0)?;
374-
writeln!(f, "To see a more detailed error report, run: ")?;
375-
writeln!(f, "")?;
376-
writeln!(
377-
f,
378-
" $ cargo check -p cranelift-codegen --features isle-errors"
379-
)?;
380-
writeln!(f, "")?;
381-
Ok(())
382-
}
383-
}
384-
385-
impl std::fmt::Debug for DebugReport {
386-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
387-
std::fmt::Display::fmt(self, f)
388-
}
389-
}
390-
391-
impl std::error::Error for DebugReport {}
392-
}
393-
})?;
337+
isle::compile::from_files(file_paths, &options)?
338+
};
394339

395340
let code = rustfmt(&code).unwrap_or_else(|e| {
396341
println!(
@@ -404,7 +349,8 @@ fn run_compilation(
404349
"Writing ISLE-generated Rust code to {}",
405350
compilation.output.display()
406351
);
407-
std::fs::write(&compilation.output, code)?;
352+
std::fs::write(&compilation.output, code)
353+
.map_err(|e| Errors::from_io(e, "failed writing output"))?;
408354

409355
Ok(())
410356
}

cranelift/isle/isle/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ repository = "https://github.com/bytecodealliance/wasmtime/tree/main/cranelift/i
99
version = "0.91.0"
1010

1111
[dependencies]
12+
codespan-reporting = { version = "0.11.1", optional = true }
1213
log = { workspace = true, optional = true }
13-
miette = { version = "5.1.0", optional = true }
1414

1515
[dev-dependencies]
1616
tempfile = "3"
@@ -19,4 +19,4 @@ tempfile = "3"
1919
default = []
2020

2121
logging = ["log"]
22-
miette-errors = ["miette"]
22+
fancy-errors = ["codespan-reporting"]

cranelift/isle/isle/src/compile.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
//! Compilation process, from AST to Sema to Sequences of Insts.
22
3-
use crate::error::Result;
3+
use std::path::Path;
4+
5+
use crate::error::Errors;
46
use crate::{ast, codegen, sema, trie};
57

68
/// Compile the given AST definitions into Rust source code.
7-
pub fn compile(defs: &ast::Defs, options: &codegen::CodegenOptions) -> Result<String> {
9+
pub fn compile(defs: &ast::Defs, options: &codegen::CodegenOptions) -> Result<String, Errors> {
810
let mut typeenv = sema::TypeEnv::from_ast(defs)?;
911
let termenv = sema::TermEnv::from_ast(&mut typeenv, defs)?;
1012
crate::overlap::check(&mut typeenv, &termenv)?;
1113
let tries = trie::build_tries(&termenv);
1214
Ok(codegen::codegen(&typeenv, &termenv, &tries, options))
1315
}
16+
17+
/// Compile the given files into Rust source code.
18+
pub fn from_files<P: AsRef<Path>>(
19+
inputs: impl IntoIterator<Item = P>,
20+
options: &codegen::CodegenOptions,
21+
) -> Result<String, Errors> {
22+
let lexer = crate::lexer::Lexer::from_files(inputs)?;
23+
let defs = crate::parser::parse(lexer)?;
24+
compile(&defs, options)
25+
}

0 commit comments

Comments
 (0)