-
Notifications
You must be signed in to change notification settings - Fork 705
chore: document and rename InterpreterError
to VmInternalError
#6500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
461ce80
51180de
b285602
0ccff9f
632dd49
5612c96
2172e01
6f7ee36
bbead54
f9a9f6a
4c89461
b20d367
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,8 +33,12 @@ use crate::types::{FunctionIdentifier, Value}; | |
|
||
pub type StackTrace = Vec<FunctionIdentifier>; | ||
|
||
/// Wraps error types that do not implement [`PartialEq`], enabling their | ||
/// use in enums that implement the trait. Any two `IncomparableError` values | ||
/// are always considered unequal. | ||
#[derive(Debug)] | ||
pub struct IncomparableError<T> { | ||
/// The wrapped error value. | ||
pub err: T, | ||
} | ||
|
||
|
@@ -44,28 +48,68 @@ pub enum Error { | |
/// TypeChecker and other check passes. Test executions may | ||
/// trigger these errors. | ||
Unchecked(CheckErrorKind), | ||
Interpreter(InterpreterError), | ||
/// A critical, unrecoverable bug within the VM's internal logic. | ||
/// | ||
/// The presence of this error indicates a violation of one of the VM's | ||
/// invariants or a corrupted state. This is **not** an error in the user's | ||
/// Clarity code, but a bug in the VM's Rust implementation. | ||
/// | ||
/// # Example | ||
/// The VM's evaluation loop attempts to `pop` from an empty internal call stack, | ||
/// indicating a mismatch in function entry/exit logic. | ||
Internal(VmInternalError), | ||
Runtime(RuntimeErrorType, Option<StackTrace>), | ||
EarlyReturn(EarlyReturnError), | ||
} | ||
|
||
/// InterpreterErrors are errors that *should never* occur. | ||
/// Test executions may trigger these errors. | ||
/// Represents an internal, unrecoverable error within the Clarity VM. | ||
/// | ||
/// These errors signify a bug in the VM's logic or a violation of its internal | ||
/// invariants. They are not meant to be caught or handled by Clarity contracts. | ||
#[derive(Debug, PartialEq)] | ||
pub enum InterpreterError { | ||
pub enum VmInternalError { | ||
/// Raised when the VM encounters an invalid or malformed `SymbolicExpression` | ||
/// e.g., bad variable name or missing argument. | ||
/// The `String` provides a message describing the specific issue. | ||
BadSymbolicRepresentation(String), | ||
InterpreterError(String), | ||
/// A generic, unexpected internal error, indicating a logic failure within | ||
/// the VM. | ||
/// The `String` provides a message describing the specific failure. | ||
InvariantViolation(String), // TODO: merge with VmInternalError::Expect | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there an issue for this TODO? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point! I just opened it #6530 |
||
/// The VM failed to produce the final `AssetMap` when finalizing the | ||
/// execution environment for a transaction. | ||
FailedToConstructAssetTable, | ||
/// The VM failed to produce the final `EventBatch` when finalizing the | ||
/// execution environment for a transaction. | ||
FailedToConstructEventBatch, | ||
/// An error occurred during an interaction with the database. | ||
/// The parameter contains the corresponding SQLite error. | ||
#[cfg(feature = "rusqlite")] | ||
SqliteError(IncomparableError<SqliteError>), | ||
/// The file path provided for the MARF database is invalid because it | ||
/// contains non-UTF-8 characters. | ||
BadFileName, | ||
/// The VM failed to create the necessary directory for the MARF persistent | ||
/// storage. Likely due to a file system permissions error or an invalid path | ||
FailedToCreateDataDirectory, | ||
/// A failure occurred within the MARF implementation. | ||
/// The `String` provides a message describing the specific failure. | ||
MarfFailure(String), | ||
/// Failed to construct a tuple value from provided data because it did not | ||
/// match the expected type signature. | ||
FailureConstructingTupleWithType, | ||
/// Failed to construct a list value from provided data because it | ||
/// did not match the expected type signature. | ||
FailureConstructingListWithType, | ||
/// An STX transfer failed due to insufficient balance. | ||
InsufficientBalance, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this truly an unexpected error? Does it imply that the calling code should sanitize inputs first, and that this error should never actually be raised? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This appears to be used as “the last stand.”. Looking at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly -- it's the final check to prevent balance underflows. Balance underflows are checked at several places up the stack, so if this error is needed then Bad Things have already happened in the VM. |
||
/// A generic error occurred during a database operation. | ||
/// The `String` represents a descriptive message detailing the specific issue. | ||
DBError(String), | ||
/// An internal expectation or assertion failed. This is used for conditions | ||
/// that are believed to be unreachable but are handled gracefully to prevent | ||
/// a panic. | ||
/// The `String` provides a message describing the failed expectation. | ||
Expect(String), | ||
} | ||
|
||
|
@@ -130,7 +174,7 @@ impl PartialEq<Error> for Error { | |
(Error::Runtime(x, _), Error::Runtime(y, _)) => x == y, | ||
(Error::Unchecked(x), Error::Unchecked(y)) => x == y, | ||
(Error::EarlyReturn(x), Error::EarlyReturn(y)) => x == y, | ||
(Error::Interpreter(x), Error::Interpreter(y)) => x == y, | ||
(Error::Internal(x), Error::Internal(y)) => x == y, | ||
_ => false, | ||
} | ||
} | ||
|
@@ -175,7 +219,7 @@ impl error::Error for RuntimeErrorType { | |
impl From<ParseError> for Error { | ||
fn from(err: ParseError) -> Self { | ||
match *err.err { | ||
ParseErrors::InterpreterFailure => Error::from(InterpreterError::Expect( | ||
ParseErrors::InterpreterFailure => Error::from(VmInternalError::Expect( | ||
"Unexpected interpreter failure during parsing".into(), | ||
)), | ||
_ => Error::from(RuntimeErrorType::ASTError(Box::new(err))), | ||
|
@@ -186,10 +230,10 @@ impl From<ParseError> for Error { | |
impl From<CostErrors> for Error { | ||
fn from(err: CostErrors) -> Self { | ||
match err { | ||
CostErrors::InterpreterFailure => Error::from(InterpreterError::Expect( | ||
CostErrors::InterpreterFailure => Error::from(VmInternalError::Expect( | ||
"Interpreter failure during cost calculation".into(), | ||
)), | ||
CostErrors::Expect(s) => Error::from(InterpreterError::Expect(format!( | ||
CostErrors::Expect(s) => Error::from(VmInternalError::Expect(format!( | ||
"Interpreter failure during cost calculation: {s}" | ||
))), | ||
other_err => Error::from(CheckErrorKind::from(other_err)), | ||
|
@@ -221,9 +265,9 @@ impl From<EarlyReturnError> for Error { | |
} | ||
} | ||
|
||
impl From<InterpreterError> for Error { | ||
fn from(err: InterpreterError) -> Self { | ||
Error::Interpreter(err) | ||
impl From<VmInternalError> for Error { | ||
fn from(err: VmInternalError) -> Self { | ||
Error::Internal(err) | ||
} | ||
} | ||
|
||
|
@@ -252,12 +296,12 @@ mod test { | |
Error::EarlyReturn(EarlyReturnError::UnwrapFailed(Box::new(Value::Bool(true)))) | ||
); | ||
assert_eq!( | ||
Error::Interpreter(InterpreterError::InterpreterError("".to_string())), | ||
Error::Interpreter(InterpreterError::InterpreterError("".to_string())) | ||
Error::Internal(VmInternalError::InvariantViolation("".to_string())), | ||
Error::Internal(VmInternalError::InvariantViolation("".to_string())) | ||
); | ||
assert!( | ||
Error::EarlyReturn(EarlyReturnError::UnwrapFailed(Box::new(Value::Bool(true)))) | ||
!= Error::Interpreter(InterpreterError::InterpreterError("".to_string())) | ||
!= Error::Internal(VmInternalError::InvariantViolation("".to_string())) | ||
); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.