Skip to content

Commit 55e6976

Browse files
committed
make invariant checker return potentially multiple errors
1 parent 7ead6ad commit 55e6976

File tree

1 file changed

+67
-14
lines changed

1 file changed

+67
-14
lines changed

crates/wasmi/src/engine/translator/conditions.rs

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,58 @@ use core::{
1919
cmp,
2020
fmt::{self, Display},
2121
};
22+
use std::vec::Vec;
23+
24+
/// A non-empty list of [`Error`]s.
25+
pub struct ErrorList<'ctx> {
26+
ctx: ErrorContext<'ctx>,
27+
errors: Vec<Error>,
28+
}
29+
30+
impl<'ctx> ErrorList<'ctx> {
31+
/// Creates a new [`ErrorList`].
32+
///
33+
/// # Panics
34+
///
35+
/// If `errors` is empty.
36+
fn new(ctx: ErrorContext<'ctx>, errors: Vec<Error>) -> Self {
37+
assert!(!errors.is_empty());
38+
Self { ctx, errors }
39+
}
40+
}
41+
42+
impl ErrorList<'_> {
43+
/// Returns `true` if `self` contains at least one [`Error`].
44+
fn has_errors(&self) -> bool {
45+
!self.errors.is_empty()
46+
}
47+
48+
/// Returns the number of [`Error`]s in `self`.
49+
fn len_errors(&self) -> usize {
50+
self.errors.len()
51+
}
52+
}
53+
54+
impl Display for ErrorList<'_> {
55+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56+
if !self.has_errors() {
57+
return writeln!(f, "all checked Wasmi translation invariants are uphold");
58+
}
59+
writeln!(
60+
f,
61+
"encountered {} broken invariants for Wasmi translation:",
62+
self.len_errors()
63+
)?;
64+
let ctx = self.ctx;
65+
for (n, error) in self.errors.iter().cloned().enumerate() {
66+
write!(f, "error({n}): {}", ErrorWithContext { ctx, error })?;
67+
}
68+
Ok(())
69+
}
70+
}
2271

2372
/// An error describing a broken Wasmi translation invariant.
24-
#[derive(Debug)]
73+
#[derive(Debug, Clone)]
2574
pub struct Error {
2675
/// The erraneous `Instruction` index.
2776
instr: Instr,
@@ -30,7 +79,7 @@ pub struct Error {
3079
}
3180

3281
/// The reason behind a broken Wasmi translation invariant.
33-
#[derive(Debug)]
82+
#[derive(Debug, Clone)]
3483
pub enum Reason {
3584
InvalidRegister {
3685
/// The invalid `Reg`.
@@ -216,6 +265,7 @@ pub struct ErrorWithContext<'ctx> {
216265
}
217266

218267
/// A context to populate an [`Error`] with more information for its [`Display`] implementation.
268+
#[derive(Copy, Clone)]
219269
pub struct ErrorContext<'ctx> {
220270
/// The underlying Wasmi function translator that has already finished its job.
221271
translator: &'ctx FuncTranslator,
@@ -286,15 +336,8 @@ impl ErrorWithContext<'_> {
286336
/// # Errors
287337
///
288338
/// If a Wasmi translation invariant is broken.
289-
pub fn verify_translation_invariants(translator: &FuncTranslator) -> Result<(), ErrorWithContext> {
290-
let checker = TranslationInvariantsChecker { translator };
291-
match checker.verify_translation_invariants() {
292-
Ok(_) => Ok(()),
293-
Err(error) => {
294-
let ctx = ErrorContext { translator };
295-
Err(ErrorWithContext { ctx, error })
296-
}
297-
}
339+
pub fn verify_translation_invariants(translator: &FuncTranslator) -> Result<(), ErrorList> {
340+
TranslationInvariantsChecker { translator }.verify_translation_invariants()
298341
}
299342

300343
/// Encapsulates state required for translation invariants checking.
@@ -303,15 +346,25 @@ struct TranslationInvariantsChecker<'translator> {
303346
translator: &'translator FuncTranslator,
304347
}
305348

306-
impl TranslationInvariantsChecker<'_> {
349+
impl<'translator> TranslationInvariantsChecker<'translator> {
307350
/// Checks if the invariants of Wasmi function translation are uphold.
308351
///
309352
/// Read more here: [`verify_translation_invariants`]
310353
///
311354
/// # Errors
312355
///
313356
/// If a Wasmi translation invariant is broken.
314-
fn verify_translation_invariants(&self) -> Result<(), Error> {
315-
todo!()
357+
fn verify_translation_invariants(&self) -> Result<(), ErrorList<'translator>> {
358+
let errors = Vec::new();
359+
// TODO: perform invariant checking
360+
if errors.is_empty() {
361+
return Ok(());
362+
}
363+
Err(ErrorList::new(
364+
ErrorContext {
365+
translator: self.translator,
366+
},
367+
errors,
368+
))
316369
}
317370
}

0 commit comments

Comments
 (0)