diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index ded23c7c6e3..44d60b4d330 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -13,6 +13,7 @@ on: pull_request: branches: - develop + - aac-client-breaking # temp branch for aac work types: - opened - reopened diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 613e8c973ee..4c346bdf781 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -498,10 +498,10 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { /// /// # Errors /// - /// - Returns CheckErrors::WriteAttemptedInReadOnly if there is a read-only + /// - Returns CheckErrorKind::WriteAttemptedInReadOnly if there is a read-only /// violation, i.e. if some function marked read-only attempts to modify /// the chainstate. - pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), CheckError> + pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), StaticCheckError> ``` This comment is considered positive because it explains the contract of the function in pseudo-code. Someone who understands the constructs mentioned could, e.g., write a test for this method from this description. diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index 09e4e5f056d..5efb0843f45 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -136,201 +136,382 @@ impl SyntaxBindingError { } } -impl From for CheckErrors { +impl From for CheckErrorKind { fn from(e: SyntaxBindingError) -> Self { Self::BadSyntaxBinding(e) } } +/// Errors encountered during type-checking and analysis of Clarity contract code, ensuring +/// type safety, correct function signatures, and adherence to resource constraints. +/// These errors prevent invalid contracts from being deployed or executed, +/// halting analysis and failing the transaction or contract deployment. #[derive(Debug, PartialEq)] -pub enum CheckErrors { - // cost checker errors +pub enum CheckErrorKind { + // Cost checker errors + /// Arithmetic overflow in cost computation during type-checking, exceeding the maximum threshold. CostOverflow, + /// Cumulative type-checking cost exceeds the allocated budget, indicating budget depletion. + /// The first `ExecutionCost` represents the total consumed cost, and the second represents the budget limit. CostBalanceExceeded(ExecutionCost, ExecutionCost), + /// Memory usage during type-checking exceeds the allocated budget. + /// The first `u64` represents the total consumed memory, and the second represents the memory limit. MemoryBalanceExceeded(u64, u64), + /// Failure in cost-tracking due to an unexpected condition or invalid state. + /// The `String` wraps the specific reason for the failure. CostComputationFailed(String), + // Time checker errors + /// Type-checking time exceeds the allowed budget, halting analysis to ensure responsiveness. + ExecutionTimeExpired, + /// Value exceeds the maximum allowed size for type-checking or serialization. ValueTooLarge, + /// Value is outside the acceptable range for its type (e.g., integer bounds). ValueOutOfBounds, + /// Type signature nesting depth exceeds the allowed limit during analysis. TypeSignatureTooDeep, + /// Expected a name (e.g., variable, function) but found an invalid or missing token. ExpectedName, + /// Supertype (e.g., trait or union) exceeds the maximum allowed size or complexity. + /// This error indicates a transaction would invalidate a block if included. SupertypeTooLarge, - // unexpected interpreter behavior + // Unexpected interpreter behavior + /// Unexpected condition or failure in the type-checker, indicating a bug or invalid state. + /// This error indicates a transaction would invalidate a block if included. Expects(String), - // match errors - BadMatchOptionSyntax(Box), - BadMatchResponseSyntax(Box), + // Match expression errors + /// Invalid syntax in an `option` match expression. + /// The `Box` wraps the underlying error causing the syntax issue. + BadMatchOptionSyntax(Box), + /// Invalid syntax in a `response` match expression. + /// The `Box` wraps the underlying error causing the syntax issue. + BadMatchResponseSyntax(Box), + /// Input to a `match` expression does not conform to the expected type (e.g., `Option` or `Response`). + /// The `Box` wraps the actual type of the provided input. BadMatchInput(Box), - // list typing errors + // List typing errors + /// List elements have mismatched types, violating type consistency. ListTypesMustMatch, + /// Constructed list exceeds the maximum allowed length during type-checking. ConstructedListTooLarge, - // simple type expectation mismatch + // Type mismatch errors + /// Expected type does not match the actual type during analysis. + /// The first `Box` wraps the expected type, and the second wraps the actual type. TypeError(Box, Box), + /// Value does not match the expected type during type-checking. + /// The `Box` wraps the expected type, and the `Box` wraps the invalid value. TypeValueError(Box, Box), + /// Type description is invalid or malformed, preventing proper type-checking. InvalidTypeDescription, + /// Referenced type name does not exist or is undefined. + /// The `String` wraps the non-existent type name. UnknownTypeName(String), - // union type mismatch + // Union type mismatch + /// Type does not belong to the expected union of types during analysis. + /// The `Vec` represents the expected types, and the `Box` wraps the actual type. UnionTypeError(Vec, Box), + /// Value does not belong to the expected union of types during type-checking. + /// The `Vec` represents the expected types, and the `Box` wraps the invalid value. UnionTypeValueError(Vec, Box), + /// Expected an optional type but found a different type. + /// The `Box` wraps the actual type provided. ExpectedOptionalType(Box), + /// Expected a response type but found a different type. + /// The `Box` wraps the actual type provided. ExpectedResponseType(Box), + /// Expected an optional or response type but found a different type. + /// The `Box` wraps the actual type provided. ExpectedOptionalOrResponseType(Box), + /// Expected an optional value but found a different value. + /// The `Box` wraps the actual value provided. ExpectedOptionalValue(Box), + /// Expected a response value but found a different value. + /// The `Box` wraps the actual value provided. ExpectedResponseValue(Box), + /// Expected an optional or response value but found a different value. + /// The `Box` wraps the actual value provided. ExpectedOptionalOrResponseValue(Box), + /// Could not determine the type of the `ok` branch in a response type. CouldNotDetermineResponseOkType, + /// Could not determine the type of the `err` branch in a response type. CouldNotDetermineResponseErrType, + /// Could not determine the serialization type for a value during analysis. CouldNotDetermineSerializationType, + /// Intermediary response types were not properly checked, risking type safety. UncheckedIntermediaryResponses, + /// Expected a contract principal value but found a different value. + /// The `Box` wraps the actual value provided. ExpectedContractPrincipalValue(Box), + // Match type errors + /// Could not determine the types for a match expression’s branches. CouldNotDetermineMatchTypes, + /// Could not determine the type of an expression during analysis. CouldNotDetermineType, // Checker runtime failures + /// Attempt to re-annotate a type that was already annotated, indicating a bug. TypeAlreadyAnnotatedFailure, + /// Unexpected failure in the type-checker implementation, indicating a bug. CheckerImplementationFailure, // Assets + /// Expected a token name as an argument but found an invalid token. BadTokenName, + /// Invalid or malformed signature in a `(define-non-fungible-token ...)` expression. DefineNFTBadSignature, + /// Referenced non-fungible token (NFT) does not exist. + /// The `String` wraps the non-existent token name. NoSuchNFT(String), + /// Referenced fungible token (FT) does not exist. + /// The `String` wraps the non-existent token name. NoSuchFT(String), + // Transfer and asset operation errors + /// Invalid arguments provided to a `stx-transfer?` function. BadTransferSTXArguments, + /// Invalid arguments provided to a fungible token transfer function. BadTransferFTArguments, + /// Invalid arguments provided to a non-fungible token transfer function. BadTransferNFTArguments, + /// Invalid arguments provided to a fungible token mint function. BadMintFTArguments, + /// Invalid arguments provided to a fungible token burn function. BadBurnFTArguments, - // tuples + // Tuples + /// Tuple field name is invalid or violates naming rules. BadTupleFieldName, + /// Expected a tuple type but found a different type. + /// The `Box` wraps the actual type provided. ExpectedTuple(Box), + /// Referenced tuple field does not exist in the tuple type. + /// The `String` wraps the requested field name, and the `TupleTypeSignature` wraps the tuple’s type. NoSuchTupleField(String, TupleTypeSignature), + /// Empty tuple is not allowed in Clarity. EmptyTuplesNotAllowed, + /// Invalid tuple construction due to malformed syntax or type mismatch. + /// The `String` wraps the specific error description. BadTupleConstruction(String), - // variables + // Variables + /// Referenced data variable does not exist in scope. + /// The `String` wraps the non-existent variable name. NoSuchDataVariable(String), - // data map + // Data map + /// Map name is invalid or violates naming rules. BadMapName, + /// Referenced data map does not exist in scope. + /// The `String` wraps the non-existent map name. NoSuchMap(String), - // defines + // Defines + /// Invalid or malformed signature in a function definition. DefineFunctionBadSignature, + /// Function name is invalid or violates naming rules. BadFunctionName, + /// Invalid or malformed map type definition in a `(define-map ...)` expression. BadMapTypeDefinition, + /// Public function must return a response type, but found a different type. + /// The `Box` wraps the actual return type. PublicFunctionMustReturnResponse(Box), + /// Invalid or malformed variable definition in a `(define-data-var ...)` expression. DefineVariableBadSignature, + /// Return types of function branches do not match the expected type. + /// The first `Box` wraps the expected type, and the second wraps the actual type. ReturnTypesMustMatch(Box, Box), + /// Circular reference detected in interdependent function definitions. + /// The `Vec` represents the list of referenced names forming the cycle. CircularReference(Vec), - // contract-call errors + // Contract-call errors + /// Referenced contract does not exist. + /// The `String` wraps the non-existent contract name. NoSuchContract(String), + /// Referenced public function does not exist in the specified contract. + /// The first `String` wraps the contract name, and the second wraps the function name. NoSuchPublicFunction(String, String), + /// Public function is not read-only when expected to be. + /// The first `String` wraps the contract name, and the second wraps the function name. PublicFunctionNotReadOnly(String, String), + /// Attempt to define a contract with a name that already exists. + /// The `String` wraps the conflicting contract name. ContractAlreadyExists(String), + /// Expected a contract name in a `contract-call?` expression but found an invalid token. ContractCallExpectName, + /// Expected a callable type (e.g., function or trait) but found a different type. + /// The `Box` wraps the actual type provided. ExpectedCallableType(Box), // get-block-info? errors + /// Referenced block info property does not exist. + /// The `String` wraps the non-existent property name. NoSuchBlockInfoProperty(String), + /// Referenced burn block info property does not exist. + /// The `String` wraps the non-existent property name. NoSuchBurnBlockInfoProperty(String), + /// Referenced Stacks block info property does not exist. + /// The `String` wraps the non-existent property name. NoSuchStacksBlockInfoProperty(String), + /// Referenced tenure info property does not exist. + /// The `String` wraps the non-existent property name. NoSuchTenureInfoProperty(String), + /// Expected a block info property name but found an invalid token. GetBlockInfoExpectPropertyName, + /// Expected a burn block info property name but found an invalid token. GetBurnBlockInfoExpectPropertyName, + /// Expected a Stacks block info property name but found an invalid token. GetStacksBlockInfoExpectPropertyName, + /// Expected a tenure info property name but found an invalid token. GetTenureInfoExpectPropertyName, + /// Name (e.g., variable, function) is already in use within the same scope. + /// The `String` wraps the conflicting name. NameAlreadyUsed(String), + /// Name is a reserved word in Clarity and cannot be used. + /// The `String` wraps the reserved name. ReservedWord(String), - // expect a function, or applying a function to a list + // Expect a function, or applying a function to a list + /// Attempt to apply a non-function value as a function. NonFunctionApplication, + /// Expected a list application but found a different expression. ExpectedListApplication, + /// Expected a sequence type (e.g., list, buffer) but found a different type. + /// The `Box` wraps the actual type provided. ExpectedSequence(Box), + /// Sequence length exceeds the maximum allowed limit. MaxLengthOverflow, - // let syntax + // Let syntax + /// Invalid syntax in a `let` expression, violating binding or structure rules. BadLetSyntax, - // generic binding syntax + // Generic binding syntax + /// Invalid binding syntax in a generic construct (e.g., `let`, `match`). + /// The `SyntaxBindingError` wraps the specific binding error. BadSyntaxBinding(SyntaxBindingError), + /// Maximum context depth for type-checking has been reached. MaxContextDepthReached, + /// Referenced function is not defined in the current scope. + /// The `String` wraps the non-existent function name. UndefinedFunction(String), + /// Referenced variable is not defined in the current scope. + /// The `String` wraps the non-existent variable name. UndefinedVariable(String), - // argument counts + // Argument counts + /// Function requires at least the specified number of arguments, but fewer were provided. + /// The first `usize` represents the minimum required, and the second represents the actual count. RequiresAtLeastArguments(usize, usize), + /// Function requires at most the specified number of arguments, but more were provided. + /// The first `usize` represents the maximum allowed, and the second represents the actual count. RequiresAtMostArguments(usize, usize), + /// Incorrect number of arguments provided to a function. + /// The first `usize` represents the expected count, and the second represents the actual count. IncorrectArgumentCount(usize, usize), + /// `if` expression arms have mismatched return types. + /// The first `Box` wraps the type of one arm, and the second wraps the other. IfArmsMustMatch(Box, Box), + /// `match` expression arms have mismatched return types. + /// The first `Box` wraps the type of one arm, and the second wraps the other. MatchArmsMustMatch(Box, Box), + /// `default-to` expression types are mismatched. + /// The first `Box` wraps the expected type, and the second wraps the actual type. DefaultTypesMustMatch(Box, Box), + /// Application of an illegal or unknown function. + /// The `String` wraps the function name. IllegalOrUnknownFunctionApplication(String), + /// Referenced function is unknown or not defined. + /// The `String` wraps the non-existent function name. UnknownFunction(String), - // traits + // Traits + /// Referenced trait does not exist in the specified contract. + /// The first `String` wraps the contract name, and the second wraps the trait name. NoSuchTrait(String, String), + /// Referenced trait is not defined or cannot be found. + /// The `String` wraps the non-existent trait name. TraitReferenceUnknown(String), + /// Referenced method does not exist in the specified trait. + /// The first `String` wraps the trait name, and the second wraps the method name. TraitMethodUnknown(String, String), + /// Expected a trait identifier (e.g., `.trait-name`) but found an invalid token. ExpectedTraitIdentifier, + /// Trait reference is not allowed in the current context (e.g., storage). TraitReferenceNotAllowed, + /// Invalid implementation of a trait method. + /// The first `String` wraps the trait name, and the second wraps the method name. BadTraitImplementation(String, String), + /// Invalid or malformed signature in a `(define-trait ...)` expression. DefineTraitBadSignature, + /// Trait definition contains duplicate method names. + /// The `String` wraps the duplicate method name. DefineTraitDuplicateMethod(String), + /// Unexpected use of a trait or field reference in a non-trait context. UnexpectedTraitOrFieldReference, + /// Trait-based contract call used in a read-only context, which is prohibited. TraitBasedContractCallInReadOnly, + /// `contract-of` expects a trait type but found a different type. ContractOfExpectsTrait, + /// Trait implementation is incompatible with the expected trait definition. + /// The first `Box` wraps the expected trait, and the second wraps the actual trait. IncompatibleTrait(Box, Box), - // strings + // Strings + /// String contains invalid or disallowed characters (e.g., non-ASCII in ASCII strings). InvalidCharactersDetected, + /// String contains invalid UTF-8 encoding. InvalidUTF8Encoding, // secp256k1 signature + /// Invalid secp256k1 signature provided in an expression. InvalidSecp65k1Signature, + /// Attempt to write to contract state in a read-only function. WriteAttemptedInReadOnly, + /// `at-block` closure must be read-only but contains write operations. AtBlockClosureMustBeReadOnly, - - // time checker errors - ExecutionTimeExpired, } #[derive(Debug, PartialEq)] -pub struct CheckError { - pub err: Box, +/// Represents an error encountered during Clarity's type-checking and semantic analysis phase. +/// Wraps a `CheckErrorKind` variant, optionally includes the expressions causing the error, +/// and provides diagnostic information for debugging. +pub struct StaticCheckError { + /// The specific type-checking or semantic error that occurred. + pub err: Box, + /// Optional vector of expressions related to the error, if available. pub expressions: Option>, + /// Diagnostic details (e.g., line/column numbers, error message, suggestions) around the error. pub diagnostic: Diagnostic, } -impl CheckErrors { +impl CheckErrorKind { /// Does this check error indicate that the transaction should be /// rejected? pub fn rejectable(&self) -> bool { matches!( self, - CheckErrors::SupertypeTooLarge | CheckErrors::Expects(_) + CheckErrorKind::SupertypeTooLarge | CheckErrorKind::Expects(_) ) } } -impl CheckError { - pub fn new(err: CheckErrors) -> CheckError { +impl StaticCheckError { + pub fn new(err: CheckErrorKind) -> StaticCheckError { let diagnostic = Diagnostic::err(&err); - CheckError { + StaticCheckError { err: Box::new(err), expressions: None, diagnostic, @@ -351,40 +532,40 @@ impl CheckError { self.expressions.replace(exprs.to_vec()); } - pub fn with_expression(err: CheckErrors, expr: &SymbolicExpression) -> Self { + pub fn with_expression(err: CheckErrorKind, expr: &SymbolicExpression) -> Self { let mut r = Self::new(err); r.set_expression(expr); r } } -impl From<(SyntaxBindingError, &SymbolicExpression)> for CheckError { +impl From<(SyntaxBindingError, &SymbolicExpression)> for StaticCheckError { fn from(e: (SyntaxBindingError, &SymbolicExpression)) -> Self { - Self::with_expression(CheckErrors::BadSyntaxBinding(e.0), e.1) + Self::with_expression(CheckErrorKind::BadSyntaxBinding(e.0), e.1) } } -impl From<(CheckErrors, &SymbolicExpression)> for CheckError { - fn from(e: (CheckErrors, &SymbolicExpression)) -> Self { +impl From<(CheckErrorKind, &SymbolicExpression)> for StaticCheckError { + fn from(e: (CheckErrorKind, &SymbolicExpression)) -> Self { let mut ce = Self::new(e.0); ce.set_expression(e.1); ce } } -impl From<(CheckErrors, &SymbolicExpression)> for CheckErrors { - fn from(e: (CheckErrors, &SymbolicExpression)) -> Self { +impl From<(CheckErrorKind, &SymbolicExpression)> for CheckErrorKind { + fn from(e: (CheckErrorKind, &SymbolicExpression)) -> Self { e.0 } } -impl fmt::Display for CheckErrors { +impl fmt::Display for CheckErrorKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self:?}") } } -impl fmt::Display for CheckError { +impl fmt::Display for StaticCheckError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.err)?; @@ -396,75 +577,81 @@ impl fmt::Display for CheckError { } } -impl From for CheckError { +impl From for StaticCheckError { fn from(err: CostErrors) -> Self { - CheckError::from(CheckErrors::from(err)) + StaticCheckError::from(CheckErrorKind::from(err)) } } -impl From for CheckErrors { +impl From for CheckErrorKind { fn from(err: CostErrors) -> Self { match err { - CostErrors::CostOverflow => CheckErrors::CostOverflow, - CostErrors::CostBalanceExceeded(a, b) => CheckErrors::CostBalanceExceeded(a, b), - CostErrors::MemoryBalanceExceeded(a, b) => CheckErrors::MemoryBalanceExceeded(a, b), - CostErrors::CostComputationFailed(s) => CheckErrors::CostComputationFailed(s), + CostErrors::CostOverflow => CheckErrorKind::CostOverflow, + CostErrors::CostBalanceExceeded(a, b) => CheckErrorKind::CostBalanceExceeded(a, b), + CostErrors::MemoryBalanceExceeded(a, b) => CheckErrorKind::MemoryBalanceExceeded(a, b), + CostErrors::CostComputationFailed(s) => CheckErrorKind::CostComputationFailed(s), CostErrors::CostContractLoadFailure => { - CheckErrors::CostComputationFailed("Failed to load cost contract".into()) + CheckErrorKind::CostComputationFailed("Failed to load cost contract".into()) } CostErrors::InterpreterFailure => { - CheckErrors::Expects("Unexpected interpreter failure in cost computation".into()) + CheckErrorKind::Expects("Unexpected interpreter failure in cost computation".into()) } - CostErrors::Expect(s) => CheckErrors::Expects(s), - CostErrors::ExecutionTimeExpired => CheckErrors::ExecutionTimeExpired, + CostErrors::Expect(s) => CheckErrorKind::Expects(s), + CostErrors::ExecutionTimeExpired => CheckErrorKind::ExecutionTimeExpired, } } } -impl error::Error for CheckError { +impl error::Error for StaticCheckError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { None } } -impl error::Error for CheckErrors { +impl error::Error for CheckErrorKind { fn source(&self) -> Option<&(dyn error::Error + 'static)> { None } } -impl From for CheckError { - fn from(err: CheckErrors) -> Self { - CheckError::new(err) +impl From for StaticCheckError { + fn from(err: CheckErrorKind) -> Self { + StaticCheckError::new(err) } } #[cfg(any(test, feature = "testing"))] -impl From for String { - fn from(o: CheckErrors) -> Self { +impl From for String { + fn from(o: CheckErrorKind) -> Self { o.to_string() } } -pub fn check_argument_count(expected: usize, args: &[T]) -> Result<(), CheckErrors> { +pub fn check_argument_count(expected: usize, args: &[T]) -> Result<(), CheckErrorKind> { if args.len() != expected { - Err(CheckErrors::IncorrectArgumentCount(expected, args.len())) + Err(CheckErrorKind::IncorrectArgumentCount(expected, args.len())) } else { Ok(()) } } -pub fn check_arguments_at_least(expected: usize, args: &[T]) -> Result<(), CheckErrors> { +pub fn check_arguments_at_least(expected: usize, args: &[T]) -> Result<(), CheckErrorKind> { if args.len() < expected { - Err(CheckErrors::RequiresAtLeastArguments(expected, args.len())) + Err(CheckErrorKind::RequiresAtLeastArguments( + expected, + args.len(), + )) } else { Ok(()) } } -pub fn check_arguments_at_most(expected: usize, args: &[T]) -> Result<(), CheckErrors> { +pub fn check_arguments_at_most(expected: usize, args: &[T]) -> Result<(), CheckErrorKind> { if args.len() > expected { - Err(CheckErrors::RequiresAtMostArguments(expected, args.len())) + Err(CheckErrorKind::RequiresAtMostArguments( + expected, + args.len(), + )) } else { Ok(()) } @@ -485,139 +672,139 @@ fn formatted_expected_types(expected_types: &[TypeSignature]) -> String { expected_types_joined } -impl DiagnosableError for CheckErrors { +impl DiagnosableError for CheckErrorKind { fn message(&self) -> String { match &self { - CheckErrors::SupertypeTooLarge => "supertype of two types is too large".into(), - CheckErrors::Expects(s) => format!("unexpected interpreter behavior: {s}"), - CheckErrors::BadMatchOptionSyntax(source) => + CheckErrorKind::SupertypeTooLarge => "supertype of two types is too large".into(), + CheckErrorKind::Expects(s) => format!("unexpected interpreter behavior: {s}"), + CheckErrorKind::BadMatchOptionSyntax(source) => format!("match on a optional type uses the following syntax: (match input some-name if-some-expression if-none-expression). Caused by: {}", source.message()), - CheckErrors::BadMatchResponseSyntax(source) => + CheckErrorKind::BadMatchResponseSyntax(source) => format!("match on a result type uses the following syntax: (match input ok-name if-ok-expression err-name if-err-expression). Caused by: {}", source.message()), - CheckErrors::BadMatchInput(t) => + CheckErrorKind::BadMatchInput(t) => format!("match requires an input of either a response or optional, found input: '{t}'"), - CheckErrors::CostOverflow => "contract execution cost overflowed cost counter".into(), - CheckErrors::CostBalanceExceeded(a, b) => format!("contract execution cost exceeded budget: {a:?} > {b:?}"), - CheckErrors::MemoryBalanceExceeded(a, b) => format!("contract execution cost exceeded memory budget: {a:?} > {b:?}"), - CheckErrors::InvalidTypeDescription => "supplied type description is invalid".into(), - CheckErrors::EmptyTuplesNotAllowed => "tuple types may not be empty".into(), - CheckErrors::UnknownTypeName(name) => format!("failed to parse type: '{name}'"), - CheckErrors::ValueTooLarge => "created a type which was greater than maximum allowed value size".into(), - CheckErrors::ValueOutOfBounds => "created a type which value size was out of defined bounds".into(), - CheckErrors::TypeSignatureTooDeep => "created a type which was deeper than maximum allowed type depth".into(), - CheckErrors::ExpectedName => "expected a name argument to this function".into(), - CheckErrors::ListTypesMustMatch => "expecting elements of same type in a list".into(), - CheckErrors::ConstructedListTooLarge => "reached limit of elements in a sequence".into(), - CheckErrors::TypeError(expected_type, found_type) => format!("expecting expression of type '{expected_type}', found '{found_type}'"), - CheckErrors::TypeValueError(expected_type, found_value) => format!("expecting expression of type '{expected_type}', found '{found_value}'"), - CheckErrors::UnionTypeError(expected_types, found_type) => format!("expecting expression of type {}, found '{}'", formatted_expected_types(expected_types), found_type), - CheckErrors::UnionTypeValueError(expected_types, found_type) => format!("expecting expression of type {}, found '{}'", formatted_expected_types(expected_types), found_type), - CheckErrors::ExpectedOptionalType(found_type) => format!("expecting expression of type 'optional', found '{found_type}'"), - CheckErrors::ExpectedOptionalOrResponseType(found_type) => format!("expecting expression of type 'optional' or 'response', found '{found_type}'"), - CheckErrors::ExpectedOptionalOrResponseValue(found_value) => format!("expecting expression of type 'optional' or 'response', found '{found_value}'"), - CheckErrors::ExpectedResponseType(found_type) => format!("expecting expression of type 'response', found '{found_type}'"), - CheckErrors::ExpectedOptionalValue(found_value) => format!("expecting expression of type 'optional', found '{found_value}'"), - CheckErrors::ExpectedResponseValue(found_value) => format!("expecting expression of type 'response', found '{found_value}'"), - CheckErrors::ExpectedContractPrincipalValue(found_value) => format!("expecting contract principal value, found '{found_value}'"), - CheckErrors::CouldNotDetermineResponseOkType => "attempted to obtain 'ok' value from response, but 'ok' type is indeterminate".into(), - CheckErrors::CouldNotDetermineResponseErrType => "attempted to obtain 'err' value from response, but 'err' type is indeterminate".into(), - CheckErrors::CouldNotDetermineMatchTypes => "attempted to match on an (optional) or (response) type where either the some, ok, or err type is indeterminate. you may wish to use unwrap-panic or unwrap-err-panic instead.".into(), - CheckErrors::CouldNotDetermineType => "type of expression cannot be determined".into(), - CheckErrors::BadTupleFieldName => "invalid tuple field name".into(), - CheckErrors::ExpectedTuple(type_signature) => format!("expecting tuple, found '{type_signature}'"), - CheckErrors::NoSuchTupleField(field_name, tuple_signature) => format!("cannot find field '{field_name}' in tuple '{tuple_signature}'"), - CheckErrors::BadTupleConstruction(message) => format!("invalid tuple syntax: {message}"), - CheckErrors::NoSuchDataVariable(var_name) => format!("use of unresolved persisted variable '{var_name}'"), - CheckErrors::BadTransferSTXArguments => "STX transfer expects an int amount, from principal, to principal".into(), - CheckErrors::BadTransferFTArguments => "transfer expects an int amount, from principal, to principal".into(), - CheckErrors::BadTransferNFTArguments => "transfer expects an asset, from principal, to principal".into(), - CheckErrors::BadMintFTArguments => "mint expects a uint amount and from principal".into(), - CheckErrors::BadBurnFTArguments => "burn expects a uint amount and from principal".into(), - CheckErrors::BadMapName => "invalid map name".into(), - CheckErrors::NoSuchMap(map_name) => format!("use of unresolved map '{map_name}'"), - CheckErrors::DefineFunctionBadSignature => "invalid function definition".into(), - CheckErrors::BadFunctionName => "invalid function name".into(), - CheckErrors::BadMapTypeDefinition => "invalid map definition".into(), - CheckErrors::PublicFunctionMustReturnResponse(found_type) => format!("public functions must return an expression of type 'response', found '{found_type}'"), - CheckErrors::DefineVariableBadSignature => "invalid variable definition".into(), - CheckErrors::ReturnTypesMustMatch(type_1, type_2) => format!("detected two execution paths, returning two different expression types (got '{type_1}' and '{type_2}')"), - CheckErrors::NoSuchContract(contract_identifier) => format!("use of unresolved contract '{contract_identifier}'"), - CheckErrors::NoSuchPublicFunction(contract_identifier, function_name) => format!("contract '{contract_identifier}' has no public function '{function_name}'"), - CheckErrors::PublicFunctionNotReadOnly(contract_identifier, function_name) => format!("function '{contract_identifier}' in '{function_name}' is not read-only"), - CheckErrors::ContractAlreadyExists(contract_identifier) => format!("contract name '{contract_identifier}' conflicts with existing contract"), - CheckErrors::ContractCallExpectName => "missing contract name for call".into(), - CheckErrors::ExpectedCallableType(found_type) => format!("expected a callable contract, found {found_type}"), - CheckErrors::NoSuchBlockInfoProperty(property_name) => format!("use of block unknown property '{property_name}'"), - CheckErrors::NoSuchBurnBlockInfoProperty(property_name) => format!("use of burn block unknown property '{property_name}'"), - CheckErrors::NoSuchStacksBlockInfoProperty(property_name) => format!("use of unknown stacks block property '{property_name}'"), - CheckErrors::NoSuchTenureInfoProperty(property_name) => format!("use of unknown tenure property '{property_name}'"), - CheckErrors::GetBlockInfoExpectPropertyName => "missing property name for block info introspection".into(), - CheckErrors::GetBurnBlockInfoExpectPropertyName => "missing property name for burn block info introspection".into(), - CheckErrors::GetStacksBlockInfoExpectPropertyName => "missing property name for stacks block info introspection".into(), - CheckErrors::GetTenureInfoExpectPropertyName => "missing property name for tenure info introspection".into(), - CheckErrors::NameAlreadyUsed(name) => format!("defining '{name}' conflicts with previous value"), - CheckErrors::ReservedWord(name) => format!("{name} is a reserved word"), - CheckErrors::NonFunctionApplication => "expecting expression of type function".into(), - CheckErrors::ExpectedListApplication => "expecting expression of type list".into(), - CheckErrors::ExpectedSequence(found_type) => format!("expecting expression of type 'list', 'buff', 'string-ascii' or 'string-utf8' - found '{found_type}'"), - CheckErrors::MaxLengthOverflow => format!("expecting a value <= {}", u32::MAX), - CheckErrors::BadLetSyntax => "invalid syntax of 'let'".into(), - CheckErrors::CircularReference(references) => format!("detected circular reference: ({})", references.join(", ")), - CheckErrors::BadSyntaxBinding(binding_error) => format!("invalid syntax binding: {}", &binding_error.message()), - CheckErrors::MaxContextDepthReached => "reached depth limit".into(), - CheckErrors::UndefinedVariable(var_name) => format!("use of unresolved variable '{var_name}'"), - CheckErrors::UndefinedFunction(var_name) => format!("use of unresolved function '{var_name}'"), - CheckErrors::RequiresAtLeastArguments(expected, found) => format!("expecting >= {expected} arguments, got {found}"), - CheckErrors::RequiresAtMostArguments(expected, found) => format!("expecting < {expected} arguments, got {found}"), - CheckErrors::IncorrectArgumentCount(expected_count, found_count) => format!("expecting {expected_count} arguments, got {found_count}"), - CheckErrors::IfArmsMustMatch(type_1, type_2) => format!("expression types returned by the arms of 'if' must match (got '{type_1}' and '{type_2}')"), - CheckErrors::MatchArmsMustMatch(type_1, type_2) => format!("expression types returned by the arms of 'match' must match (got '{type_1}' and '{type_2}')"), - CheckErrors::DefaultTypesMustMatch(type_1, type_2) => format!("expression types passed in 'default-to' must match (got '{type_1}' and '{type_2}')"), - CheckErrors::IllegalOrUnknownFunctionApplication(function_name) => format!("use of illegal / unresolved function '{function_name}"), - CheckErrors::UnknownFunction(function_name) => format!("use of unresolved function '{function_name}'"), - CheckErrors::TraitBasedContractCallInReadOnly => "use of trait based contract calls are not allowed in read-only context".into(), - CheckErrors::WriteAttemptedInReadOnly => "expecting read-only statements, detected a writing operation".into(), - CheckErrors::AtBlockClosureMustBeReadOnly => "(at-block ...) closures expect read-only statements, but detected a writing operation".into(), - CheckErrors::BadTokenName => "expecting an token name as an argument".into(), - CheckErrors::DefineNFTBadSignature => "(define-asset ...) expects an asset name and an asset identifier type signature as arguments".into(), - CheckErrors::NoSuchNFT(asset_name) => format!("tried to use asset function with a undefined asset ('{asset_name}')"), - CheckErrors::NoSuchFT(asset_name) => format!("tried to use token function with a undefined token ('{asset_name}')"), - CheckErrors::NoSuchTrait(contract_name, trait_name) => format!("use of unresolved trait {contract_name}.{trait_name}"), - CheckErrors::TraitReferenceUnknown(trait_name) => format!("use of undeclared trait <{trait_name}>"), - CheckErrors::TraitMethodUnknown(trait_name, func_name) => format!("method '{func_name}' unspecified in trait <{trait_name}>"), - CheckErrors::BadTraitImplementation(trait_name, func_name) => format!("invalid signature for method '{func_name}' regarding trait's specification <{trait_name}>"), - CheckErrors::ExpectedTraitIdentifier => "expecting expression of type trait identifier".into(), - CheckErrors::UnexpectedTraitOrFieldReference => "unexpected use of trait reference or field".into(), - CheckErrors::DefineTraitBadSignature => "invalid trait definition".into(), - CheckErrors::DefineTraitDuplicateMethod(method_name) => format!("duplicate method name '{method_name}' in trait definition"), - CheckErrors::TraitReferenceNotAllowed => "trait references can not be stored".into(), - CheckErrors::ContractOfExpectsTrait => "trait reference expected".into(), - CheckErrors::IncompatibleTrait(expected_trait, actual_trait) => format!("trait '{actual_trait}' is not a compatible with expected trait, '{expected_trait}'"), - CheckErrors::InvalidCharactersDetected => "invalid characters detected".into(), - CheckErrors::InvalidUTF8Encoding => "invalid UTF8 encoding".into(), - CheckErrors::InvalidSecp65k1Signature => "invalid seckp256k1 signature".into(), - CheckErrors::TypeAlreadyAnnotatedFailure | CheckErrors::CheckerImplementationFailure => { + CheckErrorKind::CostOverflow => "contract execution cost overflowed cost counter".into(), + CheckErrorKind::CostBalanceExceeded(a, b) => format!("contract execution cost exceeded budget: {a:?} > {b:?}"), + CheckErrorKind::MemoryBalanceExceeded(a, b) => format!("contract execution cost exceeded memory budget: {a:?} > {b:?}"), + CheckErrorKind::InvalidTypeDescription => "supplied type description is invalid".into(), + CheckErrorKind::EmptyTuplesNotAllowed => "tuple types may not be empty".into(), + CheckErrorKind::UnknownTypeName(name) => format!("failed to parse type: '{name}'"), + CheckErrorKind::ValueTooLarge => "created a type which was greater than maximum allowed value size".into(), + CheckErrorKind::ValueOutOfBounds => "created a type which value size was out of defined bounds".into(), + CheckErrorKind::TypeSignatureTooDeep => "created a type which was deeper than maximum allowed type depth".into(), + CheckErrorKind::ExpectedName => "expected a name argument to this function".into(), + CheckErrorKind::ListTypesMustMatch => "expecting elements of same type in a list".into(), + CheckErrorKind::ConstructedListTooLarge => "reached limit of elements in a sequence".into(), + CheckErrorKind::TypeError(expected_type, found_type) => format!("expecting expression of type '{expected_type}', found '{found_type}'"), + CheckErrorKind::TypeValueError(expected_type, found_value) => format!("expecting expression of type '{expected_type}', found '{found_value}'"), + CheckErrorKind::UnionTypeError(expected_types, found_type) => format!("expecting expression of type {}, found '{}'", formatted_expected_types(expected_types), found_type), + CheckErrorKind::UnionTypeValueError(expected_types, found_type) => format!("expecting expression of type {}, found '{}'", formatted_expected_types(expected_types), found_type), + CheckErrorKind::ExpectedOptionalType(found_type) => format!("expecting expression of type 'optional', found '{found_type}'"), + CheckErrorKind::ExpectedOptionalOrResponseType(found_type) => format!("expecting expression of type 'optional' or 'response', found '{found_type}'"), + CheckErrorKind::ExpectedOptionalOrResponseValue(found_value) => format!("expecting expression of type 'optional' or 'response', found '{found_value}'"), + CheckErrorKind::ExpectedResponseType(found_type) => format!("expecting expression of type 'response', found '{found_type}'"), + CheckErrorKind::ExpectedOptionalValue(found_value) => format!("expecting expression of type 'optional', found '{found_value}'"), + CheckErrorKind::ExpectedResponseValue(found_value) => format!("expecting expression of type 'response', found '{found_value}'"), + CheckErrorKind::ExpectedContractPrincipalValue(found_value) => format!("expecting contract principal value, found '{found_value}'"), + CheckErrorKind::CouldNotDetermineResponseOkType => "attempted to obtain 'ok' value from response, but 'ok' type is indeterminate".into(), + CheckErrorKind::CouldNotDetermineResponseErrType => "attempted to obtain 'err' value from response, but 'err' type is indeterminate".into(), + CheckErrorKind::CouldNotDetermineMatchTypes => "attempted to match on an (optional) or (response) type where either the some, ok, or err type is indeterminate. you may wish to use unwrap-panic or unwrap-err-panic instead.".into(), + CheckErrorKind::CouldNotDetermineType => "type of expression cannot be determined".into(), + CheckErrorKind::BadTupleFieldName => "invalid tuple field name".into(), + CheckErrorKind::ExpectedTuple(type_signature) => format!("expecting tuple, found '{type_signature}'"), + CheckErrorKind::NoSuchTupleField(field_name, tuple_signature) => format!("cannot find field '{field_name}' in tuple '{tuple_signature}'"), + CheckErrorKind::BadTupleConstruction(message) => format!("invalid tuple syntax: {message}"), + CheckErrorKind::NoSuchDataVariable(var_name) => format!("use of unresolved persisted variable '{var_name}'"), + CheckErrorKind::BadTransferSTXArguments => "STX transfer expects an int amount, from principal, to principal".into(), + CheckErrorKind::BadTransferFTArguments => "transfer expects an int amount, from principal, to principal".into(), + CheckErrorKind::BadTransferNFTArguments => "transfer expects an asset, from principal, to principal".into(), + CheckErrorKind::BadMintFTArguments => "mint expects a uint amount and from principal".into(), + CheckErrorKind::BadBurnFTArguments => "burn expects a uint amount and from principal".into(), + CheckErrorKind::BadMapName => "invalid map name".into(), + CheckErrorKind::NoSuchMap(map_name) => format!("use of unresolved map '{map_name}'"), + CheckErrorKind::DefineFunctionBadSignature => "invalid function definition".into(), + CheckErrorKind::BadFunctionName => "invalid function name".into(), + CheckErrorKind::BadMapTypeDefinition => "invalid map definition".into(), + CheckErrorKind::PublicFunctionMustReturnResponse(found_type) => format!("public functions must return an expression of type 'response', found '{found_type}'"), + CheckErrorKind::DefineVariableBadSignature => "invalid variable definition".into(), + CheckErrorKind::ReturnTypesMustMatch(type_1, type_2) => format!("detected two execution paths, returning two different expression types (got '{type_1}' and '{type_2}')"), + CheckErrorKind::NoSuchContract(contract_identifier) => format!("use of unresolved contract '{contract_identifier}'"), + CheckErrorKind::NoSuchPublicFunction(contract_identifier, function_name) => format!("contract '{contract_identifier}' has no public function '{function_name}'"), + CheckErrorKind::PublicFunctionNotReadOnly(contract_identifier, function_name) => format!("function '{contract_identifier}' in '{function_name}' is not read-only"), + CheckErrorKind::ContractAlreadyExists(contract_identifier) => format!("contract name '{contract_identifier}' conflicts with existing contract"), + CheckErrorKind::ContractCallExpectName => "missing contract name for call".into(), + CheckErrorKind::ExpectedCallableType(found_type) => format!("expected a callable contract, found {found_type}"), + CheckErrorKind::NoSuchBlockInfoProperty(property_name) => format!("use of block unknown property '{property_name}'"), + CheckErrorKind::NoSuchBurnBlockInfoProperty(property_name) => format!("use of burn block unknown property '{property_name}'"), + CheckErrorKind::NoSuchStacksBlockInfoProperty(property_name) => format!("use of unknown stacks block property '{property_name}'"), + CheckErrorKind::NoSuchTenureInfoProperty(property_name) => format!("use of unknown tenure property '{property_name}'"), + CheckErrorKind::GetBlockInfoExpectPropertyName => "missing property name for block info introspection".into(), + CheckErrorKind::GetBurnBlockInfoExpectPropertyName => "missing property name for burn block info introspection".into(), + CheckErrorKind::GetStacksBlockInfoExpectPropertyName => "missing property name for stacks block info introspection".into(), + CheckErrorKind::GetTenureInfoExpectPropertyName => "missing property name for tenure info introspection".into(), + CheckErrorKind::NameAlreadyUsed(name) => format!("defining '{name}' conflicts with previous value"), + CheckErrorKind::ReservedWord(name) => format!("{name} is a reserved word"), + CheckErrorKind::NonFunctionApplication => "expecting expression of type function".into(), + CheckErrorKind::ExpectedListApplication => "expecting expression of type list".into(), + CheckErrorKind::ExpectedSequence(found_type) => format!("expecting expression of type 'list', 'buff', 'string-ascii' or 'string-utf8' - found '{found_type}'"), + CheckErrorKind::MaxLengthOverflow => format!("expecting a value <= {}", u32::MAX), + CheckErrorKind::BadLetSyntax => "invalid syntax of 'let'".into(), + CheckErrorKind::CircularReference(references) => format!("detected circular reference: ({})", references.join(", ")), + CheckErrorKind::BadSyntaxBinding(binding_error) => format!("invalid syntax binding: {}", &binding_error.message()), + CheckErrorKind::MaxContextDepthReached => "reached depth limit".into(), + CheckErrorKind::UndefinedVariable(var_name) => format!("use of unresolved variable '{var_name}'"), + CheckErrorKind::UndefinedFunction(var_name) => format!("use of unresolved function '{var_name}'"), + CheckErrorKind::RequiresAtLeastArguments(expected, found) => format!("expecting >= {expected} arguments, got {found}"), + CheckErrorKind::RequiresAtMostArguments(expected, found) => format!("expecting < {expected} arguments, got {found}"), + CheckErrorKind::IncorrectArgumentCount(expected_count, found_count) => format!("expecting {expected_count} arguments, got {found_count}"), + CheckErrorKind::IfArmsMustMatch(type_1, type_2) => format!("expression types returned by the arms of 'if' must match (got '{type_1}' and '{type_2}')"), + CheckErrorKind::MatchArmsMustMatch(type_1, type_2) => format!("expression types returned by the arms of 'match' must match (got '{type_1}' and '{type_2}')"), + CheckErrorKind::DefaultTypesMustMatch(type_1, type_2) => format!("expression types passed in 'default-to' must match (got '{type_1}' and '{type_2}')"), + CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name) => format!("use of illegal / unresolved function '{function_name}"), + CheckErrorKind::UnknownFunction(function_name) => format!("use of unresolved function '{function_name}'"), + CheckErrorKind::TraitBasedContractCallInReadOnly => "use of trait based contract calls are not allowed in read-only context".into(), + CheckErrorKind::WriteAttemptedInReadOnly => "expecting read-only statements, detected a writing operation".into(), + CheckErrorKind::AtBlockClosureMustBeReadOnly => "(at-block ...) closures expect read-only statements, but detected a writing operation".into(), + CheckErrorKind::BadTokenName => "expecting an token name as an argument".into(), + CheckErrorKind::DefineNFTBadSignature => "(define-asset ...) expects an asset name and an asset identifier type signature as arguments".into(), + CheckErrorKind::NoSuchNFT(asset_name) => format!("tried to use asset function with a undefined asset ('{asset_name}')"), + CheckErrorKind::NoSuchFT(asset_name) => format!("tried to use token function with a undefined token ('{asset_name}')"), + CheckErrorKind::NoSuchTrait(contract_name, trait_name) => format!("use of unresolved trait {contract_name}.{trait_name}"), + CheckErrorKind::TraitReferenceUnknown(trait_name) => format!("use of undeclared trait <{trait_name}>"), + CheckErrorKind::TraitMethodUnknown(trait_name, func_name) => format!("method '{func_name}' unspecified in trait <{trait_name}>"), + CheckErrorKind::BadTraitImplementation(trait_name, func_name) => format!("invalid signature for method '{func_name}' regarding trait's specification <{trait_name}>"), + CheckErrorKind::ExpectedTraitIdentifier => "expecting expression of type trait identifier".into(), + CheckErrorKind::UnexpectedTraitOrFieldReference => "unexpected use of trait reference or field".into(), + CheckErrorKind::DefineTraitBadSignature => "invalid trait definition".into(), + CheckErrorKind::DefineTraitDuplicateMethod(method_name) => format!("duplicate method name '{method_name}' in trait definition"), + CheckErrorKind::TraitReferenceNotAllowed => "trait references can not be stored".into(), + CheckErrorKind::ContractOfExpectsTrait => "trait reference expected".into(), + CheckErrorKind::IncompatibleTrait(expected_trait, actual_trait) => format!("trait '{actual_trait}' is not a compatible with expected trait, '{expected_trait}'"), + CheckErrorKind::InvalidCharactersDetected => "invalid characters detected".into(), + CheckErrorKind::InvalidUTF8Encoding => "invalid UTF8 encoding".into(), + CheckErrorKind::InvalidSecp65k1Signature => "invalid seckp256k1 signature".into(), + CheckErrorKind::TypeAlreadyAnnotatedFailure | CheckErrorKind::CheckerImplementationFailure => { "internal error - please file an issue on https://github.com/stacks-network/stacks-blockchain".into() }, - CheckErrors::UncheckedIntermediaryResponses => "intermediary responses in consecutive statements must be checked".into(), - CheckErrors::CostComputationFailed(s) => format!("contract cost computation failed: {s}"), - CheckErrors::CouldNotDetermineSerializationType => "could not determine the input type for the serialization function".into(), - CheckErrors::ExecutionTimeExpired => "execution time expired".into(), + CheckErrorKind::UncheckedIntermediaryResponses => "intermediary responses in consecutive statements must be checked".into(), + CheckErrorKind::CostComputationFailed(s) => format!("contract cost computation failed: {s}"), + CheckErrorKind::CouldNotDetermineSerializationType => "could not determine the input type for the serialization function".into(), + CheckErrorKind::ExecutionTimeExpired => "execution time expired".into(), } } fn suggestion(&self) -> Option { match &self { - CheckErrors::BadLetSyntax => Some( + CheckErrorKind::BadLetSyntax => Some( "'let' syntax example: (let ((supply 1000) (ttl 60)) )".into(), ), - CheckErrors::TraitReferenceUnknown(_) => Some( + CheckErrorKind::TraitReferenceUnknown(_) => Some( "traits should be either defined, with define-trait, or imported, with use-trait." .into(), ), - CheckErrors::NoSuchBlockInfoProperty(_) => Some( + CheckErrorKind::NoSuchBlockInfoProperty(_) => Some( "properties available: time, header-hash, burnchain-header-hash, vrf-seed".into(), ), _ => None, diff --git a/clarity-types/src/errors/ast.rs b/clarity-types/src/errors/ast.rs index f2b774bd1b7..9edfba4bbdf 100644 --- a/clarity-types/src/errors/ast.rs +++ b/clarity-types/src/errors/ast.rs @@ -23,88 +23,177 @@ use crate::representations::{PreSymbolicExpression, Span}; use crate::token::Token; pub type ParseResult = Result; - +/// Errors encountered during the lexical and syntactic analysis of Clarity source code +/// when constructing the abstract syntax tree (AST). #[derive(Debug, PartialEq)] -pub enum ParseErrors { - // Cost errors +pub enum ParseErrorKind { + // Cost-related errors + /// Arithmetic overflow in cost computation during AST construction, exceeding the maximum threshold. CostOverflow, + /// Cumulative parsing cost exceeds the allocated budget. + /// The first `ExecutionCost` represents the total consumed cost, and the second represents the budget limit. CostBalanceExceeded(ExecutionCost, ExecutionCost), + /// Memory usage during AST construction exceeds the allocated budget. + /// The first `u64` represents the total consumed memory, and the second represents the memory limit. MemoryBalanceExceeded(u64, u64), + /// Failure in cost-tracking due to an unexpected condition or invalid state. + /// The `String` represents the specific reason for the failure. CostComputationFailed(String), + /// Parsing time exceeds the allowed budget, halting AST construction to ensure responsiveness. ExecutionTimeExpired, + // Structural errors + /// Number of expressions exceeds the maximum allowed limit. TooManyExpressions, + /// Nesting depth of expressions exceeds the maximum allowed stack depth. ExpressionStackDepthTooDeep, + /// Nesting depth of expressions exceeds the maximum allowed stack depth. VaryExpressionStackDepthTooDeep, + + // Semantic errors + /// Failed to parse a string into an integer literal. + /// The `String` represents the invalid input string. FailedParsingIntValue(String), + /// Circular reference detected in interdependent function definitions. + /// The `Vec` represents the list of function names forming the cycle. CircularReference(Vec), + /// Variable name is already in use within the same scope. + /// The `String` represents the conflicting variable name. NameAlreadyUsed(String), + /// Attempt to store a trait reference, which is prohibited to ensure type safety. TraitReferenceNotAllowed, + /// Invalid or malformed signature in a `(use-trait ...)` expression. ImportTraitBadSignature, + /// Invalid or malformed signature in a `(define-trait ...)` expression. DefineTraitBadSignature, + /// Invalid or malformed signature in a `(impl-trait ...)` expression. ImplTraitBadSignature, + /// Referenced trait does not exist or cannot be found. + /// The `String` represents the non-existent trait name. TraitReferenceUnknown(String), - // V1 errors + // V1 Errors + /// Failed to capture an expected substring or value during pattern matching in lexical analysis. FailedCapturingInput, + /// Expected a whitespace or closing parenthesis but found an unexpected token or character. + /// The `String` represents the unexpected token or character found. SeparatorExpected(String), + /// Expected a whitespace after a colon but found an unexpected token. + /// The `String` represents the unexpected token found. SeparatorExpectedAfterColon(String), + /// Input program exceeds the maximum allowed number of lines. ProgramTooLarge, + /// Variable name contains invalid characters or violates naming rules. + /// The `String` represents the invalid variable name. IllegalVariableName(String), + /// Failed to parse a string into a buffer literal. + /// The `String` represents the invalid buffer string. FailedParsingBuffer(String), + /// Failed to parse a string into a hexadecimal value. + /// The first `String` represents the invalid input string, and the second represents the error details. FailedParsingHexValue(String, String), + /// Failed to parse a string into a principal literal (e.g., invalid principal format). + /// The `String` represents the invalid principal string. FailedParsingPrincipal(String), + /// Failed to parse a string into a valid field literal. + /// The `String` represents the invalid field string. FailedParsingField(String), + /// Failed to parse the remaining input after processing a construct, leaving invalid tokens. + /// The `String` represents the unparsed remainder of the input. FailedParsingRemainder(String), + /// Unexpected closing parenthesis encountered in the input. ClosingParenthesisUnexpected, + /// Expected a closing parenthesis but found another token or end of input. ClosingParenthesisExpected, + /// Unexpected closing brace for a tuple literal encountered in the input. ClosingTupleLiteralUnexpected, + /// Expected a closing brace for a tuple literal but it was missing. ClosingTupleLiteralExpected, + /// Expected a colon in a tuple literal at the specified position, but it was missing. + /// The `usize` represents the index where the colon was expected. TupleColonExpected(usize), + /// Expected a comma in a tuple literal at the specified position, but it was missing. + /// The `usize` represents the index where the comma was expected. TupleCommaExpected(usize), + /// Expected a tuple item (e.g., key-value pair) at the specified position, but it was missing or invalid. + /// The `usize` represents the index where the item was expected. TupleItemExpected(usize), + /// Unexpected comma separator encountered outside a valid list or tuple context. CommaSeparatorUnexpected, + /// Unexpected colon separator encountered. ColonSeparatorUnexpected, + /// Input contains invalid or disallowed characters. InvalidCharactersDetected, + /// Invalid escape sequence in a string literal (e.g., incorrect use of `\`). InvalidEscaping, // V2 Errors + /// Lexical analysis failed due to an underlying lexer error. + /// The `LexerError` represents the specific lexer error encountered. Lexer(LexerError), + /// Contract name exceeds the maximum allowed length. + /// The `String` represents the overly long contract name. ContractNameTooLong(String), + /// Expected a specific closing token (e.g., parenthesis or brace) but found another token. + /// The `Token` represents the expected closing token. ExpectedClosing(Token), + /// Expected a contract identifier (e.g., `.contract-name`) but found an invalid or missing token. ExpectedContractIdentifier, + /// Expected a trait identifier (e.g., `.trait-name`) but found an invalid or missing token. ExpectedTraitIdentifier, + /// Expected whitespace to separate tokens but found an unexpected token or character. ExpectedWhitespace, + /// Failed to parse a string into an unsigned integer literal. + /// The `String` represents the invalid unsigned integer string. FailedParsingUIntValue(String), + /// Trait name contains invalid characters or violates naming rules. + /// The `String` represents the invalid trait name. IllegalTraitName(String), + /// Invalid principal literal format, preventing parsing into a valid principal. InvalidPrincipalLiteral, + /// Invalid buffer literal format, preventing parsing into a valid buffer. InvalidBuffer, + /// Name (e.g., variable or function) exceeds the maximum allowed length. + /// The `String` represents the overly long name. NameTooLong(String), + /// Encountered an unexpected token during parsing. + /// The `Token` represents the unexpected token found. UnexpectedToken(Token), + /// Expected a colon in a tuple literal (version 2 syntax) but it was missing. TupleColonExpectedv2, + /// Expected a comma in a tuple literal (version 2 syntax) but it was missing. TupleCommaExpectedv2, + /// Expected a value in a tuple literal but it was missing or invalid. TupleValueExpected, + /// Clarity name (e.g., variable, function, or trait) contains invalid characters or violates naming rules. + /// The `String` represents the invalid Clarity name. IllegalClarityName(String), + /// ASCII string literal contains invalid characters or violates format rules. + /// The `String` represents the invalid ASCII string. IllegalASCIIString(String), + /// Contract name contains invalid characters or violates naming rules. + /// The `String` represents the invalid contract name. IllegalContractName(String), + // Notes + /// Indicates a token mismatch for internal parser diagnostics. + /// The `Token` represents the expected token to match. NoteToMatchThis(Token), - /// Should be an unreachable error + /// Unreachable error indicating an unexpected parser failure; should never occur in valid execution. UnexpectedParserFailure, - - /// Should be an unreachable failure which invalidates the transaction + /// Unreachable failure indicating an invalid transaction due to an unexpected interpreter error. InterpreterFailure, } #[derive(Debug, PartialEq)] pub struct ParseError { - pub err: Box, + pub err: Box, pub pre_expressions: Option>, pub diagnostic: Diagnostic, } impl ParseError { - pub fn new(err: ParseErrors) -> ParseError { + pub fn new(err: ParseErrorKind) -> ParseError { let diagnostic = Diagnostic::err(&err); ParseError { err: Box::new(err), @@ -116,9 +205,9 @@ impl ParseError { pub fn rejectable(&self) -> bool { matches!( *self.err, - ParseErrors::InterpreterFailure - | ParseErrors::ExpressionStackDepthTooDeep - | ParseErrors::VaryExpressionStackDepthTooDeep + ParseErrorKind::InterpreterFailure + | ParseErrorKind::ExpressionStackDepthTooDeep + | ParseErrorKind::VaryExpressionStackDepthTooDeep ) } @@ -155,8 +244,8 @@ impl error::Error for ParseError { } } -impl From for ParseError { - fn from(err: ParseErrors) -> Self { +impl From for ParseError { + fn from(err: ParseErrorKind) -> Self { ParseError::new(err) } } @@ -164,143 +253,153 @@ impl From for ParseError { impl From for ParseError { fn from(err: CostErrors) -> Self { match err { - CostErrors::CostOverflow => ParseError::new(ParseErrors::CostOverflow), + CostErrors::CostOverflow => ParseError::new(ParseErrorKind::CostOverflow), CostErrors::CostBalanceExceeded(a, b) => { - ParseError::new(ParseErrors::CostBalanceExceeded(a, b)) + ParseError::new(ParseErrorKind::CostBalanceExceeded(a, b)) } CostErrors::MemoryBalanceExceeded(a, b) => { - ParseError::new(ParseErrors::MemoryBalanceExceeded(a, b)) + ParseError::new(ParseErrorKind::MemoryBalanceExceeded(a, b)) } CostErrors::CostComputationFailed(s) => { - ParseError::new(ParseErrors::CostComputationFailed(s)) + ParseError::new(ParseErrorKind::CostComputationFailed(s)) } CostErrors::CostContractLoadFailure => ParseError::new( - ParseErrors::CostComputationFailed("Failed to load cost contract".into()), + ParseErrorKind::CostComputationFailed("Failed to load cost contract".into()), ), CostErrors::InterpreterFailure | CostErrors::Expect(_) => { - ParseError::new(ParseErrors::InterpreterFailure) + ParseError::new(ParseErrorKind::InterpreterFailure) + } + CostErrors::ExecutionTimeExpired => { + ParseError::new(ParseErrorKind::ExecutionTimeExpired) } - CostErrors::ExecutionTimeExpired => ParseError::new(ParseErrors::ExecutionTimeExpired), } } } -impl DiagnosableError for ParseErrors { +impl DiagnosableError for ParseErrorKind { fn message(&self) -> String { match &self { - ParseErrors::CostOverflow => "Used up cost budget during the parse".into(), - ParseErrors::CostBalanceExceeded(bal, used) => { + ParseErrorKind::CostOverflow => "Used up cost budget during the parse".into(), + ParseErrorKind::CostBalanceExceeded(bal, used) => { format!("Used up cost budget during the parse: {bal} balance, {used} used") } - ParseErrors::MemoryBalanceExceeded(bal, used) => { + ParseErrorKind::MemoryBalanceExceeded(bal, used) => { format!("Used up memory budget during the parse: {bal} balance, {used} used") } - ParseErrors::TooManyExpressions => "Too many expressions".into(), - ParseErrors::FailedCapturingInput => "Failed to capture value from input".into(), - ParseErrors::SeparatorExpected(found) => { + ParseErrorKind::TooManyExpressions => "Too many expressions".into(), + ParseErrorKind::FailedCapturingInput => "Failed to capture value from input".into(), + ParseErrorKind::SeparatorExpected(found) => { format!("Expected whitespace or a close parens. Found: '{found}'") } - ParseErrors::SeparatorExpectedAfterColon(found) => { + ParseErrorKind::SeparatorExpectedAfterColon(found) => { format!("Whitespace expected after colon (:), Found: '{found}'") } - ParseErrors::ProgramTooLarge => "Program too large to parse".into(), - ParseErrors::IllegalContractName(contract_name) => { + ParseErrorKind::ProgramTooLarge => "Program too large to parse".into(), + ParseErrorKind::IllegalContractName(contract_name) => { format!("Illegal contract name: '{contract_name}'") } - ParseErrors::IllegalVariableName(var_name) => { + ParseErrorKind::IllegalVariableName(var_name) => { format!("Illegal variable name: '{var_name}'") } - ParseErrors::FailedParsingIntValue(value) => { + ParseErrorKind::FailedParsingIntValue(value) => { format!("Failed to parse int literal '{value}'") } - ParseErrors::FailedParsingUIntValue(value) => { + ParseErrorKind::FailedParsingUIntValue(value) => { format!("Failed to parse uint literal 'u{value}'") } - ParseErrors::FailedParsingHexValue(value, x) => { + ParseErrorKind::FailedParsingHexValue(value, x) => { format!("Invalid hex-string literal {value}: {x}") } - ParseErrors::FailedParsingPrincipal(value) => { + ParseErrorKind::FailedParsingPrincipal(value) => { format!("Invalid principal literal: {value}") } - ParseErrors::FailedParsingBuffer(value) => format!("Invalid buffer literal: {value}"), - ParseErrors::FailedParsingField(value) => format!("Invalid field literal: {value}"), - ParseErrors::FailedParsingRemainder(remainder) => { + ParseErrorKind::FailedParsingBuffer(value) => { + format!("Invalid buffer literal: {value}") + } + ParseErrorKind::FailedParsingField(value) => format!("Invalid field literal: {value}"), + ParseErrorKind::FailedParsingRemainder(remainder) => { format!("Failed to lex input remainder: '{remainder}'") } - ParseErrors::ClosingParenthesisUnexpected => { + ParseErrorKind::ClosingParenthesisUnexpected => { "Tried to close list which isn't open.".into() } - ParseErrors::ClosingParenthesisExpected => "List expressions (..) left opened.".into(), - ParseErrors::ClosingTupleLiteralUnexpected => { + ParseErrorKind::ClosingParenthesisExpected => { + "List expressions (..) left opened.".into() + } + ParseErrorKind::ClosingTupleLiteralUnexpected => { "Tried to close tuple literal which isn't open.".into() } - ParseErrors::ClosingTupleLiteralExpected => "Tuple literal {{..}} left opened.".into(), - ParseErrors::ColonSeparatorUnexpected => "Misplaced colon.".into(), - ParseErrors::CommaSeparatorUnexpected => "Misplaced comma.".into(), - ParseErrors::TupleColonExpected(i) => { + ParseErrorKind::ClosingTupleLiteralExpected => { + "Tuple literal {{..}} left opened.".into() + } + ParseErrorKind::ColonSeparatorUnexpected => "Misplaced colon.".into(), + ParseErrorKind::CommaSeparatorUnexpected => "Misplaced comma.".into(), + ParseErrorKind::TupleColonExpected(i) => { format!("Tuple literal construction expects a colon at index {i}") } - ParseErrors::TupleCommaExpected(i) => { + ParseErrorKind::TupleCommaExpected(i) => { format!("Tuple literal construction expects a comma at index {i}") } - ParseErrors::TupleItemExpected(i) => { + ParseErrorKind::TupleItemExpected(i) => { format!("Tuple literal construction expects a key or value at index {i}") } - ParseErrors::CircularReference(function_names) => format!( + ParseErrorKind::CircularReference(function_names) => format!( "detected interdependent functions ({})", function_names.join(", ") ), - ParseErrors::NameAlreadyUsed(name) => { + ParseErrorKind::NameAlreadyUsed(name) => { format!("defining '{name}' conflicts with previous value") } - ParseErrors::ImportTraitBadSignature => { + ParseErrorKind::ImportTraitBadSignature => { "(use-trait ...) expects a trait name and a trait identifier".into() } - ParseErrors::DefineTraitBadSignature => { + ParseErrorKind::DefineTraitBadSignature => { "(define-trait ...) expects a trait name and a trait definition".into() } - ParseErrors::ImplTraitBadSignature => { + ParseErrorKind::ImplTraitBadSignature => { "(impl-trait ...) expects a trait identifier".into() } - ParseErrors::TraitReferenceNotAllowed => "trait references can not be stored".into(), - ParseErrors::TraitReferenceUnknown(trait_name) => { + ParseErrorKind::TraitReferenceNotAllowed => "trait references can not be stored".into(), + ParseErrorKind::TraitReferenceUnknown(trait_name) => { format!("use of undeclared trait <{trait_name}>") } - ParseErrors::ExpressionStackDepthTooDeep => format!( + ParseErrorKind::ExpressionStackDepthTooDeep => format!( "AST has too deep of an expression nesting. The maximum stack depth is {MAX_CALL_STACK_DEPTH}" ), - ParseErrors::VaryExpressionStackDepthTooDeep => format!( + ParseErrorKind::VaryExpressionStackDepthTooDeep => format!( "AST has too deep of an expression nesting. The maximum stack depth is {MAX_CALL_STACK_DEPTH}" ), - ParseErrors::InvalidCharactersDetected => "invalid characters detected".into(), - ParseErrors::InvalidEscaping => "invalid escaping detected in string".into(), - ParseErrors::CostComputationFailed(s) => format!("Cost computation failed: {s}"), + ParseErrorKind::InvalidCharactersDetected => "invalid characters detected".into(), + ParseErrorKind::InvalidEscaping => "invalid escaping detected in string".into(), + ParseErrorKind::CostComputationFailed(s) => format!("Cost computation failed: {s}"), // Parser v2 errors - ParseErrors::Lexer(le) => le.message(), - ParseErrors::ContractNameTooLong(name) => { + ParseErrorKind::Lexer(le) => le.message(), + ParseErrorKind::ContractNameTooLong(name) => { format!("contract name '{name}' is too long") } - ParseErrors::ExpectedContractIdentifier => "expected contract identifier".into(), - ParseErrors::ExpectedTraitIdentifier => "expected trait identifier".into(), - ParseErrors::IllegalTraitName(name) => format!("illegal trait name, '{name}'"), - ParseErrors::InvalidPrincipalLiteral => "invalid principal literal".into(), - ParseErrors::InvalidBuffer => "invalid hex-string literal".into(), - ParseErrors::NameTooLong(name) => format!("illegal name (too long), '{name}'"), - ParseErrors::UnexpectedToken(token) => format!("unexpected '{token}'"), - ParseErrors::ExpectedClosing(token) => format!("expected closing '{token}'"), - ParseErrors::TupleColonExpectedv2 => "expected ':' after key in tuple".into(), - ParseErrors::TupleCommaExpectedv2 => { + ParseErrorKind::ExpectedContractIdentifier => "expected contract identifier".into(), + ParseErrorKind::ExpectedTraitIdentifier => "expected trait identifier".into(), + ParseErrorKind::IllegalTraitName(name) => format!("illegal trait name, '{name}'"), + ParseErrorKind::InvalidPrincipalLiteral => "invalid principal literal".into(), + ParseErrorKind::InvalidBuffer => "invalid hex-string literal".into(), + ParseErrorKind::NameTooLong(name) => format!("illegal name (too long), '{name}'"), + ParseErrorKind::UnexpectedToken(token) => format!("unexpected '{token}'"), + ParseErrorKind::ExpectedClosing(token) => format!("expected closing '{token}'"), + ParseErrorKind::TupleColonExpectedv2 => "expected ':' after key in tuple".into(), + ParseErrorKind::TupleCommaExpectedv2 => { "expected ',' separating key-value pairs in tuple".into() } - ParseErrors::TupleValueExpected => "expected value expression for tuple".into(), - ParseErrors::IllegalClarityName(name) => format!("illegal clarity name, '{name}'"), - ParseErrors::IllegalASCIIString(s) => format!("illegal ascii string \"{s}\""), - ParseErrors::ExpectedWhitespace => "expected whitespace before expression".into(), - ParseErrors::NoteToMatchThis(token) => format!("to match this '{token}'"), - ParseErrors::UnexpectedParserFailure => "unexpected failure while parsing".to_string(), - ParseErrors::InterpreterFailure => "unexpected failure while parsing".to_string(), - ParseErrors::ExecutionTimeExpired => "max execution time expired".to_string(), + ParseErrorKind::TupleValueExpected => "expected value expression for tuple".into(), + ParseErrorKind::IllegalClarityName(name) => format!("illegal clarity name, '{name}'"), + ParseErrorKind::IllegalASCIIString(s) => format!("illegal ascii string \"{s}\""), + ParseErrorKind::ExpectedWhitespace => "expected whitespace before expression".into(), + ParseErrorKind::NoteToMatchThis(token) => format!("to match this '{token}'"), + ParseErrorKind::UnexpectedParserFailure => { + "unexpected failure while parsing".to_string() + } + ParseErrorKind::InterpreterFailure => "unexpected failure while parsing".to_string(), + ParseErrorKind::ExecutionTimeExpired => "max execution time expired".to_string(), } } @@ -310,14 +409,14 @@ impl DiagnosableError for ParseErrors { fn level(&self) -> Level { match self { - ParseErrors::NoteToMatchThis(_) => Level::Note, - ParseErrors::Lexer(lexer_error) => lexer_error.level(), + ParseErrorKind::NoteToMatchThis(_) => Level::Note, + ParseErrorKind::Lexer(lexer_error) => lexer_error.level(), _ => Level::Error, } } } pub struct PlacedError { - pub e: ParseErrors, + pub e: ParseErrorKind, pub span: Span, } diff --git a/clarity-types/src/errors/mod.rs b/clarity-types/src/errors/mod.rs index 58b42b8a99d..370a93f88db 100644 --- a/clarity-types/src/errors/mod.rs +++ b/clarity-types/src/errors/mod.rs @@ -20,8 +20,8 @@ pub mod lexer; use std::{error, fmt}; -pub use analysis::{CheckError, CheckErrors}; -pub use ast::{ParseError, ParseErrors, ParseResult}; +pub use analysis::{CheckErrorKind, StaticCheckError}; +pub use ast::{ParseError, ParseErrorKind, ParseResult}; pub use cost::CostErrors; pub use lexer::LexerError; #[cfg(feature = "rusqlite")] @@ -33,83 +33,181 @@ use crate::types::{FunctionIdentifier, Value}; pub type StackTrace = Vec; +/// 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 { + /// The wrapped error value. pub err: T, } +/// Errors that can occur during the runtime execution of Clarity contracts in the virtual machine. +/// These encompass type-checking failures, interpreter issues, runtime errors, and premature returns. +/// Unlike static analysis errors in `ClarityError::StaticCheck(CheckError)` or `ClarityError::Parse(ParseError)`, +/// which are caught before execution during type-checking or parsing, these errors occur during dynamic +/// evaluation and may involve conditions not detectable statically, such as dynamically constructed expressions +/// (e.g., based on VRF seeds or runtime data). #[derive(Debug)] -pub enum Error { - /// UncheckedErrors are errors that *should* be caught by the - /// TypeChecker and other check passes. Test executions may - /// trigger these errors. - Unchecked(CheckErrors), - Interpreter(InterpreterError), - Runtime(RuntimeErrorType, Option), - ShortReturn(ShortReturnType), +pub enum VmExecutionError { + /// Type-checking errors caught during runtime analysis, which should typically be detected by + /// static type-checking passes before execution. These may occur in test executions or when + /// dynamic expression construction (e.g., using runtime data like VRF seeds) creates structures + /// violating type or resource constraints (e.g., excessive stack depth). + /// The `CheckErrorKind` wraps the specific type-checking error encountered at runtime. + Unchecked(CheckErrorKind), + /// 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), + /// Errors that occur during runtime execution of Clarity code, such as arithmetic errors or + /// invalid operations, expected as part of contract evaluation. + /// The `RuntimeErrorType` wraps the specific runtime error, and the `Option` provides + /// an optional stack trace for debugging, if available. + Runtime(RuntimeError, Option), + /// Errors triggered during Clarity contract evaluation that cause early termination with + /// insufficient results (e.g., unwrapping an empty `Option`). + /// The `EarlyReturnError` wraps the specific early return condition, detailing the premature + /// termination cause. + 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 + /// 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), + /// 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, + /// 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), } -/// RuntimeErrors are errors that smart contracts are expected -/// to be able to trigger during execution (e.g., arithmetic errors) +/// Runtime errors that Clarity smart contracts are expected to trigger during execution in the virtual +/// machine, such as arithmetic errors, invalid operations, or blockchain-specific issues. These errors +/// are distinct from static analysis errors and occur during dynamic evaluation of contract code. #[derive(Debug, PartialEq)] -pub enum RuntimeErrorType { +pub enum RuntimeError { + /// A generic arithmetic error encountered during contract execution. + /// The `String` represents a descriptive message detailing the specific arithmetic issue. Arithmetic(String), + /// An arithmetic operation exceeded the maximum value for the data type (e.g., `u128`). ArithmeticOverflow, + /// An arithmetic operation resulted in a value below zero for an unsigned type. ArithmeticUnderflow, + /// Attempt to increase token supply beyond the maximum limit. + /// The first u128 represents the attempted new supply (current supply plus increase), + /// and the second represents the maximum allowed supply. SupplyOverflow(u128, u128), + /// Attempt to decrease token supply below zero. + /// The first `u128` represents the current token supply, and the second represents the attempted decrease amount. SupplyUnderflow(u128, u128), + /// Attempt to divide or compute modulo by zero. DivisionByZero, - // error in parsing types - ParseError(String), - // error in parsing the AST + /// Failure to parse types dynamically during contract execution. + /// The `String` represents the specific parsing issue, such as invalid data formats. + TypeParseFailure(String), + /// Failure to parse the abstract syntax tree (AST) during dynamic evaluation. + /// The `Box` wraps the specific parsing error encountered, detailing code interpretation issues. ASTError(Box), + /// The call stack exceeded the virtual machine's maximum depth. MaxStackDepthReached, + /// The execution context depth exceeded the virtual machine's limit. MaxContextDepthReached, + /// Attempt to construct an invalid or unsupported type at runtime (e.g., malformed data structure). BadTypeConstruction, + /// Reference to an invalid or out-of-bounds block height. + /// The `String` represents the string representation of the queried block height that was invalid. BadBlockHeight(String), + /// Attempt to interact with a non-existent token (e.g., in NFT or fungible token operations). NoSuchToken, + /// Feature or function not yet implemented in the virtual machine. NotImplemented, + /// No caller principal available in the current execution context. NoCallerInContext, + /// No sender principal available in the current execution context. NoSenderInContext, + /// Invalid name-value pair in contract data (e.g., map keys). + /// The `&'static str` represents the name of the invalid pair, and the `String` represents the offending value. BadNameValue(&'static str, String), + /// Reference to a non-existent block header hash. + /// The `BlockHeaderHash` represents the unknown block header hash. UnknownBlockHeaderHash(BlockHeaderHash), + /// Invalid block hash provided (e.g., incorrect format or length). + /// The `Vec` represents the invalid block hash data. BadBlockHash(Vec), + /// Failed to unwrap an `Optional` (`none`) or `Response` (`err` or `ok`) Clarity value. UnwrapFailure, + /// Attempt to set metadata (e.g., for NFTs or tokens) that was already initialized. MetadataAlreadySet, - // pox-locking errors + /// Interaction with a deprecated or inactive Proof of Transfer (PoX) contract. DefunctPoxContract, + /// Attempt to lock STX for stacking when already locked in an active PoX cycle. PoxAlreadyLocked, - + /// Block time unavailable during execution. BlockTimeNotAvailable, } #[derive(Debug, PartialEq)] -pub enum ShortReturnType { - ExpectedValue(Box), +/// Errors triggered during Clarity contract evaluation that cause early termination. +/// These errors halt evaluation and fail the transaction. +pub enum EarlyReturnError { + /// Failed to unwrap an `Optional` (`none`) or `Response` (`err` or `ok`) Clarity value. + /// The `Box` holds the original or thrown value. Triggered by `try!`, `unwrap-or`, or + /// `unwrap-err-or`. + UnwrapFailed(Box), + /// An 'asserts!' expression evaluated to false. + /// The `Box` holds the value provided as the second argument to `asserts!`. AssertionFailed(Box), } -pub type InterpreterResult = Result; +pub type InterpreterResult = Result; impl PartialEq> for IncomparableError { fn eq(&self, _other: &IncomparableError) -> bool { @@ -117,22 +215,22 @@ impl PartialEq> for IncomparableError { } } -impl PartialEq for Error { - fn eq(&self, other: &Error) -> bool { +impl PartialEq for VmExecutionError { + fn eq(&self, other: &VmExecutionError) -> bool { match (self, other) { - (Error::Runtime(x, _), Error::Runtime(y, _)) => x == y, - (Error::Unchecked(x), Error::Unchecked(y)) => x == y, - (Error::ShortReturn(x), Error::ShortReturn(y)) => x == y, - (Error::Interpreter(x), Error::Interpreter(y)) => x == y, + (VmExecutionError::Runtime(x, _), VmExecutionError::Runtime(y, _)) => x == y, + (VmExecutionError::Unchecked(x), VmExecutionError::Unchecked(y)) => x == y, + (VmExecutionError::EarlyReturn(x), VmExecutionError::EarlyReturn(y)) => x == y, + (VmExecutionError::Internal(x), VmExecutionError::Internal(y)) => x == y, _ => false, } } } -impl fmt::Display for Error { +impl fmt::Display for VmExecutionError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Error::Runtime(err, stack) => { + VmExecutionError::Runtime(err, stack) => { write!(f, "{err}")?; if let Some(stack_trace) = stack { writeln!(f, "\n Stack Trace: ")?; @@ -147,89 +245,89 @@ impl fmt::Display for Error { } } -impl fmt::Display for RuntimeErrorType { +impl fmt::Display for RuntimeError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{self:?}") } } -impl error::Error for Error { +impl error::Error for VmExecutionError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { None } } -impl error::Error for RuntimeErrorType { +impl error::Error for RuntimeError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { None } } -impl From for Error { +impl From for VmExecutionError { fn from(err: ParseError) -> Self { match *err.err { - ParseErrors::InterpreterFailure => Error::from(InterpreterError::Expect( + ParseErrorKind::InterpreterFailure => VmExecutionError::from(VmInternalError::Expect( "Unexpected interpreter failure during parsing".into(), )), - _ => Error::from(RuntimeErrorType::ASTError(Box::new(err))), + _ => VmExecutionError::from(RuntimeError::ASTError(Box::new(err))), } } } -impl From for Error { +impl From for VmExecutionError { fn from(err: CostErrors) -> Self { match err { - CostErrors::InterpreterFailure => Error::from(InterpreterError::Expect( + CostErrors::InterpreterFailure => VmExecutionError::from(VmInternalError::Expect( "Interpreter failure during cost calculation".into(), )), - CostErrors::Expect(s) => Error::from(InterpreterError::Expect(format!( + CostErrors::Expect(s) => VmExecutionError::from(VmInternalError::Expect(format!( "Interpreter failure during cost calculation: {s}" ))), - other_err => Error::from(CheckErrors::from(other_err)), + other_err => VmExecutionError::from(CheckErrorKind::from(other_err)), } } } -impl From for Error { - fn from(err: RuntimeErrorType) -> Self { - Error::Runtime(err, None) +impl From for VmExecutionError { + fn from(err: RuntimeError) -> Self { + VmExecutionError::Runtime(err, None) } } -impl From for Error { - fn from(err: CheckErrors) -> Self { - Error::Unchecked(err) +impl From for VmExecutionError { + fn from(err: CheckErrorKind) -> Self { + VmExecutionError::Unchecked(err) } } -impl From<(CheckErrors, &SymbolicExpression)> for Error { - fn from(err: (CheckErrors, &SymbolicExpression)) -> Self { - Error::Unchecked(err.0) +impl From<(CheckErrorKind, &SymbolicExpression)> for VmExecutionError { + fn from(err: (CheckErrorKind, &SymbolicExpression)) -> Self { + VmExecutionError::Unchecked(err.0) } } -impl From for Error { - fn from(err: ShortReturnType) -> Self { - Error::ShortReturn(err) +impl From for VmExecutionError { + fn from(err: EarlyReturnError) -> Self { + VmExecutionError::EarlyReturn(err) } } -impl From for Error { - fn from(err: InterpreterError) -> Self { - Error::Interpreter(err) +impl From for VmExecutionError { + fn from(err: VmInternalError) -> Self { + VmExecutionError::Internal(err) } } #[cfg(any(test, feature = "testing"))] -impl From for () { - fn from(_err: Error) -> Self {} +impl From for () { + fn from(_err: VmExecutionError) -> Self {} } -impl From for Value { - fn from(val: ShortReturnType) -> Self { +impl From for Value { + fn from(val: EarlyReturnError) -> Self { match val { - ShortReturnType::ExpectedValue(v) => *v, - ShortReturnType::AssertionFailed(v) => *v, + EarlyReturnError::UnwrapFailed(v) => *v, + EarlyReturnError::AssertionFailed(v) => *v, } } } @@ -241,16 +339,21 @@ mod test { #[test] fn equality() { assert_eq!( - Error::ShortReturn(ShortReturnType::ExpectedValue(Box::new(Value::Bool(true)))), - Error::ShortReturn(ShortReturnType::ExpectedValue(Box::new(Value::Bool(true)))) + VmExecutionError::EarlyReturn(EarlyReturnError::UnwrapFailed(Box::new(Value::Bool( + true + )))), + VmExecutionError::EarlyReturn(EarlyReturnError::UnwrapFailed(Box::new(Value::Bool( + true + )))) ); assert_eq!( - Error::Interpreter(InterpreterError::InterpreterError("".to_string())), - Error::Interpreter(InterpreterError::InterpreterError("".to_string())) + VmExecutionError::Internal(VmInternalError::InvariantViolation("".to_string())), + VmExecutionError::Internal(VmInternalError::InvariantViolation("".to_string())) ); assert!( - Error::ShortReturn(ShortReturnType::ExpectedValue(Box::new(Value::Bool(true)))) - != Error::Interpreter(InterpreterError::InterpreterError("".to_string())) + VmExecutionError::EarlyReturn(EarlyReturnError::UnwrapFailed(Box::new(Value::Bool( + true + )))) != VmExecutionError::Internal(VmInternalError::InvariantViolation("".to_string())) ); } } diff --git a/clarity-types/src/lib.rs b/clarity-types/src/lib.rs index de51f539156..68cc269b47f 100644 --- a/clarity-types/src/lib.rs +++ b/clarity-types/src/lib.rs @@ -31,7 +31,7 @@ pub mod representations; pub mod token; pub mod types; -pub use errors::Error; +pub use errors::VmExecutionError; pub use representations::{ClarityName, ContractName}; pub use types::Value; diff --git a/clarity-types/src/representations.rs b/clarity-types/src/representations.rs index e941e9b7ec0..86275e25a43 100644 --- a/clarity-types/src/representations.rs +++ b/clarity-types/src/representations.rs @@ -23,7 +23,7 @@ use regex::Regex; use stacks_common::codec::{Error as codec_error, StacksMessageCodec, read_next, write_next}; use crate::Value; -use crate::errors::RuntimeErrorType; +use crate::errors::RuntimeError; use crate::types::TraitIdentifier; pub const CONTRACT_MIN_NAME_LENGTH: usize = 1; @@ -66,8 +66,8 @@ guarded_string!( "ClarityName", CLARITY_NAME_REGEX, MAX_STRING_LEN, - RuntimeErrorType, - RuntimeErrorType::BadNameValue + RuntimeError, + RuntimeError::BadNameValue ); guarded_string!( @@ -75,8 +75,8 @@ guarded_string!( "ContractName", CONTRACT_NAME_REGEX, MAX_STRING_LEN, - RuntimeErrorType, - RuntimeErrorType::BadNameValue + RuntimeError, + RuntimeError::BadNameValue ); impl StacksMessageCodec for ClarityName { @@ -623,14 +623,14 @@ impl SymbolicExpression { } /// Encode this SymbolicExpression as a String suitable for logging an error (such as in - /// CheckErrors). The `developer-mode` feature includes the `span`. + /// CheckErrorKind). The `developer-mode` feature includes the `span`. #[cfg(feature = "developer-mode")] pub fn as_error_string(&self) -> String { format!("{} at {:?}", &self.expr, &self.span) } /// Encode this SymbolicExpression as a String suitable for logging an error (such as in - /// CheckErrors). + /// CheckErrorKind). #[cfg(not(feature = "developer-mode"))] pub fn as_error_string(&self) -> String { format!("{}", &self.expr) diff --git a/clarity-types/src/tests/representations.rs b/clarity-types/src/tests/representations.rs index ac395809c7d..0d00f7bc87f 100644 --- a/clarity-types/src/tests/representations.rs +++ b/clarity-types/src/tests/representations.rs @@ -15,7 +15,7 @@ use rstest::rstest; -use crate::errors::RuntimeErrorType; +use crate::errors::RuntimeError; use crate::representations::{ CONTRACT_MAX_NAME_LENGTH, CONTRACT_MIN_NAME_LENGTH, ClarityName, ContractName, MAX_STRING_LEN, }; @@ -73,7 +73,7 @@ fn test_clarity_name_invalid(#[case] name: &str) { assert!(result.is_err()); assert!(matches!( result.unwrap_err(), - RuntimeErrorType::BadNameValue(_, _) + RuntimeError::BadNameValue(_, _) )); } @@ -157,7 +157,7 @@ fn test_contract_name_invalid(#[case] name: &str) { assert!(result.is_err()); assert!(matches!( result.unwrap_err(), - RuntimeErrorType::BadNameValue(_, _) + RuntimeError::BadNameValue(_, _) )); } diff --git a/clarity-types/src/tests/types/mod.rs b/clarity-types/src/tests/types/mod.rs index 8c8d861c7ce..ef0a023a60b 100644 --- a/clarity-types/src/tests/types/mod.rs +++ b/clarity-types/src/tests/types/mod.rs @@ -18,8 +18,8 @@ mod signatures; use rstest::rstest; use stacks_common::types::StacksEpochId; -use crate::Error; -use crate::errors::{CheckErrors, InterpreterError, RuntimeErrorType}; +use crate::VmExecutionError; +use crate::errors::{CheckErrorKind, RuntimeError, VmInternalError}; use crate::types::{ ASCIIData, BuffData, CharType, ListTypeData, MAX_VALUE_SIZE, PrincipalData, QualifiedContractIdentifier, SequenceData, SequencedValue as _, StandardPrincipalData, @@ -34,16 +34,16 @@ fn test_constructors() { vec![Value::Int(5), Value::Int(2)], ListTypeData::new_list(TypeSignature::BoolType, 3).unwrap() ), - Err(InterpreterError::FailureConstructingListWithType.into()) + Err(VmInternalError::FailureConstructingListWithType.into()) ); assert_eq!( ListTypeData::new_list(TypeSignature::IntType, MAX_VALUE_SIZE), - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) ); assert_eq!( Value::buff_from(vec![0; (MAX_VALUE_SIZE + 1) as usize]), - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) ); // Test that wrappers (okay, error, some) @@ -52,17 +52,17 @@ fn test_constructors() { // isn't causing the error). assert_eq!( Value::okay(Value::buff_from(vec![0; (MAX_VALUE_SIZE) as usize]).unwrap()), - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) ); assert_eq!( Value::error(Value::buff_from(vec![0; (MAX_VALUE_SIZE) as usize]).unwrap()), - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) ); assert_eq!( Value::some(Value::buff_from(vec![0; (MAX_VALUE_SIZE) as usize]).unwrap()), - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) ); // Test that the depth limit is correctly enforced: @@ -86,24 +86,24 @@ fn test_constructors() { let inner_value = cons().unwrap(); assert_eq!( TupleData::from_data(vec![("a".into(), inner_value.clone())]), - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) ); assert_eq!( Value::list_from(vec![inner_value.clone()]), - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) ); assert_eq!( Value::okay(inner_value.clone()), - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) ); assert_eq!( Value::error(inner_value.clone()), - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) ); assert_eq!( Value::some(inner_value), - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) ); if std::env::var("CIRCLE_TESTING") == Ok("1".to_string()) { @@ -115,7 +115,7 @@ fn test_constructors() { if (u32::MAX as usize) < usize::MAX { assert_eq!( Value::buff_from(vec![0; (u32::MAX as usize) + 10]), - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) ); } } @@ -255,7 +255,7 @@ fn test_qualified_contract_identifier_local_returns_runtime_error() { let err = QualifiedContractIdentifier::local("1nvalid-name") .expect_err("Unexpected qualified contract identifier"); assert_eq!( - Error::from(RuntimeErrorType::BadNameValue( + VmExecutionError::from(RuntimeError::BadNameValue( "ContractName", "1nvalid-name".into() )), @@ -264,55 +264,55 @@ fn test_qualified_contract_identifier_local_returns_runtime_error() { } #[rstest] -#[case::too_short("S162RK3CHJPCSSK6BM757FW", RuntimeErrorType::ParseError( +#[case::too_short("S162RK3CHJPCSSK6BM757FW", RuntimeError::TypeParseFailure( "Invalid principal literal: Expected 20 data bytes.".to_string(), ))] -#[case::too_long("S1C5H66S35CSKK6CK1C9HP8SB6CWSK4RB2CDJK8HY4", RuntimeErrorType::ParseError( +#[case::too_long("S1C5H66S35CSKK6CK1C9HP8SB6CWSK4RB2CDJK8HY4", RuntimeError::TypeParseFailure( "Invalid principal literal: Expected 20 data bytes.".to_string(), ))] -#[case::invalid_c32("II2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G", RuntimeErrorType::ParseError( +#[case::invalid_c32("II2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G", RuntimeError::TypeParseFailure( "Invalid principal literal: base58ck checksum 0x1074d4f7 does not match expected 0xae29c6e0".to_string(), ))] fn test_principal_data_parse_standard_principal_returns_runtime_error( #[case] input: &str, - #[case] expected_err: RuntimeErrorType, + #[case] expected_err: RuntimeError, ) { let err = PrincipalData::parse_standard_principal(input).expect_err("Unexpected principal data"); - assert_eq!(Error::from(expected_err), err); + assert_eq!(VmExecutionError::from(expected_err), err); } #[rstest] -#[case::no_dot("SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0Gcontract-name", RuntimeErrorType::ParseError( +#[case::no_dot("SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0Gcontract-name", RuntimeError::TypeParseFailure( "Invalid principal literal: expected a `.` in a qualified contract name" .to_string(), ))] -#[case::invalid_contract_name("SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G.1nvalid-name", RuntimeErrorType::BadNameValue("ContractName", "1nvalid-name".into()))] +#[case::invalid_contract_name("SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G.1nvalid-name", RuntimeError::BadNameValue("ContractName", "1nvalid-name".into()))] -fn test_qualified_contract_identifier_parse_returns_interpreter_error( +fn test_qualified_contract_identifier_parse_returns_vm_internal_error( #[case] input: &str, - #[case] expected_err: RuntimeErrorType, + #[case] expected_err: RuntimeError, ) { let err = QualifiedContractIdentifier::parse(input) .expect_err("Unexpected qualified contract identifier"); - assert_eq!(Error::from(expected_err), err); + assert_eq!(VmExecutionError::from(expected_err), err); } #[rstest] -#[case::no_dot("SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-traitnft-trait", RuntimeErrorType::ParseError( +#[case::no_dot("SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-traitnft-trait", RuntimeError::TypeParseFailure( "Invalid principal literal: expected a `.` in a qualified contract name" .to_string(), ))] -#[case::invalid_contract_name("SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.1nvalid-contract.valid-trait", RuntimeErrorType::BadNameValue("ContractName", "1nvalid-contract".into()))] -#[case::invalid_trait_name("SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.valid-contract.1nvalid-trait", RuntimeErrorType::BadNameValue("ClarityName", "1nvalid-trait".into()))] -#[case::invalid_standard_principal("S162RK3CHJPCSSK6BM757FW.valid-contract.valid-trait", RuntimeErrorType::ParseError( +#[case::invalid_contract_name("SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.1nvalid-contract.valid-trait", RuntimeError::BadNameValue("ContractName", "1nvalid-contract".into()))] +#[case::invalid_trait_name("SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.valid-contract.1nvalid-trait", RuntimeError::BadNameValue("ClarityName", "1nvalid-trait".into()))] +#[case::invalid_standard_principal("S162RK3CHJPCSSK6BM757FW.valid-contract.valid-trait", RuntimeError::TypeParseFailure( "Invalid principal literal: Expected 20 data bytes.".to_string(), ))] fn test_trait_identifier_parse_returns_runtime_error( #[case] input: &str, - #[case] expected_err: RuntimeErrorType, + #[case] expected_err: RuntimeError, ) { - let expected_err = Error::from(expected_err); + let expected_err = VmExecutionError::from(expected_err); let err = TraitIdentifier::parse(input).expect_err("Unexpected trait identifier"); assert_eq!(expected_err, err); @@ -323,71 +323,71 @@ fn test_trait_identifier_parse_returns_runtime_error( } #[rstest] -#[case::bad_type_construction(".valid-contract.valid-trait", RuntimeErrorType::BadTypeConstruction)] -#[case::forwards_parse_errors("S162RK3CHJPCSSK6BM757FW.valid-contract.valid-trait", RuntimeErrorType::ParseError( +#[case::bad_type_construction(".valid-contract.valid-trait", RuntimeError::BadTypeConstruction)] +#[case::forwards_parse_errors("S162RK3CHJPCSSK6BM757FW.valid-contract.valid-trait", RuntimeError::TypeParseFailure( "Invalid principal literal: Expected 20 data bytes.".to_string(), ))] fn test_trait_identifier_parse_fully_qualified_returns_runtime_error( #[case] input: &str, - #[case] expected_err: RuntimeErrorType, + #[case] expected_err: RuntimeError, ) { let err = TraitIdentifier::parse_fully_qualified(input).expect_err("Unexpected trait identifier"); - assert_eq!(Error::from(expected_err), err); + assert_eq!(VmExecutionError::from(expected_err), err); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_standard_principal_data_new_returns_interpreter_error_consensus_critical() { +fn test_standard_principal_data_new_returns_vm_internal_error_consensus_critical() { let result = StandardPrincipalData::new(32, [0; 20]); let err = result.expect_err("Unexpected principal data"); assert_eq!( - Error::from(InterpreterError::Expect("Unexpected principal data".into())), + VmExecutionError::from(VmInternalError::Expect("Unexpected principal data".into())), err.into(), ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_sequence_data_element_at_returns_interpreter_error_consensus_critical() { +fn test_sequence_data_element_at_returns_vm_internal_error_consensus_critical() { let buff = SequenceData::String(CharType::ASCII(ASCIIData { data: vec![1] })); let err = buff.element_at(0).unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "BUG: failed to initialize single-byte ASCII buffer".into() )), err ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_ascii_data_to_value_returns_interpreter_error_consensus_critical() { +fn test_ascii_data_to_value_returns_vm_internal_error_consensus_critical() { let err = ASCIIData::to_value(&1).unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "ERROR: Invalid ASCII string successfully constructed".into() )), err ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_utf8_data_to_value_returns_interpreter_error_consensus_critical() { +fn test_utf8_data_to_value_returns_vm_internal_error_consensus_critical() { let err = UTF8Data::to_value(&vec![0xED, 0xA0, 0x80]).unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "ERROR: Invalid UTF8 string successfully constructed".into() )), err ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_tuple_data_from_data_typed_returns_interpreter_error_consensus_critical() { +fn test_tuple_data_from_data_typed_returns_vm_internal_error_consensus_critical() { let tuple_type = TupleTypeSignature::try_from(vec![("a".into(), TypeSignature::IntType)]).unwrap(); let err = TupleData::from_data_typed( @@ -397,159 +397,159 @@ fn test_tuple_data_from_data_typed_returns_interpreter_error_consensus_critical( ) .unwrap_err(); assert_eq!( - Error::from(InterpreterError::FailureConstructingTupleWithType), + VmExecutionError::from(VmInternalError::FailureConstructingTupleWithType), err ); } #[rstest] -#[case::not_a_string(Value::none(), InterpreterError::Expect("Expected ASCII string".to_string()))] -#[case::invalid_utf8(Value::Sequence(SequenceData::String(CharType::ASCII(ASCIIData { data: vec![0xED, 0xA0, 0x80] }))), InterpreterError::Expect("Non UTF-8 data in string".to_string()))] -fn test_value_expect_ascii_returns_interpreter_error( +#[case::not_a_string(Value::none(), VmInternalError::Expect("Expected ASCII string".to_string()))] +#[case::invalid_utf8(Value::Sequence(SequenceData::String(CharType::ASCII(ASCIIData { data: vec![0xED, 0xA0, 0x80] }))), VmInternalError::Expect("Non UTF-8 data in string".to_string()))] +fn test_value_expect_ascii_returns_vm_internal_error( #[case] value: Value, - #[case] expected_err: InterpreterError, + #[case] expected_err: VmInternalError, ) { let err = value.expect_ascii().unwrap_err(); - assert_eq!(Error::from(expected_err), err); + assert_eq!(VmExecutionError::from(expected_err), err); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_value_expect_u128_returns_interpreter_error_consensus_critical() { +fn test_value_expect_u128_returns_vm_internal_error_consensus_critical() { let err = Value::none().expect_u128().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected u128".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected u128".to_string())), err ); } #[test] -fn test_value_expect_i128_returns_interpreter_error() { +fn test_value_expect_i128_returns_vm_internal_error() { let err = Value::none().expect_i128().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected i128".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected i128".to_string())), err ); } #[rstest] -#[case::not_a_buffer(Value::none(), InterpreterError::Expect("Expected buff".to_string()))] -#[case::too_small(Value::buff_from(vec![1, 2, 3, 4]).unwrap(), InterpreterError::Expect("Unexpected buff length".to_string()))] -fn test_value_expect_buff_returns_interpreter_error( +#[case::not_a_buffer(Value::none(), VmInternalError::Expect("Expected buff".to_string()))] +#[case::too_small(Value::buff_from(vec![1, 2, 3, 4]).unwrap(), VmInternalError::Expect("Unexpected buff length".to_string()))] +fn test_value_expect_buff_returns_vm_internal_error( #[case] value: Value, - #[case] expected_err: InterpreterError, + #[case] expected_err: VmInternalError, ) { let err = value.expect_buff(1).unwrap_err(); - assert_eq!(Error::from(expected_err), err); + assert_eq!(VmExecutionError::from(expected_err), err); } #[test] -fn test_value_expect_tuple_returns_interpreter_error() { +fn test_value_expect_tuple_returns_vm_internal_error() { let err = Value::none().expect_tuple().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected tuple".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected tuple".to_string())), err ); } #[test] -fn test_value_expect_list_returns_interpreter_error() { +fn test_value_expect_list_returns_vm_internal_error() { let err = Value::none().expect_list().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected list".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected list".to_string())), err ); } #[test] -fn test_value_expect_buff_padded_returns_interpreter_error() { +fn test_value_expect_buff_padded_returns_vm_internal_error() { let err = Value::none().expect_buff_padded(10, 0).unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected buff".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected buff".to_string())), err ); } #[test] -fn test_value_expect_bool_returns_interpreter_error() { +fn test_value_expect_bool_returns_vm_internal_error() { let err = Value::none().expect_bool().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected bool".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected bool".to_string())), err ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_value_expect_optional_returns_interpreter_error_consensus_critical() { +fn test_value_expect_optional_returns_vm_internal_error_consensus_critical() { let err = Value::okay_true().expect_optional().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected optional".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected optional".to_string())), err ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_value_expect_principal_returns_interpreter_error_consensus_critical() { +fn test_value_expect_principal_returns_vm_internal_error_consensus_critical() { let err = Value::none().expect_principal().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected principal".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected principal".to_string())), err ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_value_expect_callable_returns_interpreter_error_consensus_critical() { +fn test_value_expect_callable_returns_vm_internal_error_consensus_critical() { let err = Value::none().expect_callable().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected callable".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected callable".to_string())), err ); } #[test] -fn test_value_expect_result_returns_interpreter_error() { +fn test_value_expect_result_returns_vm_internal_error() { let err = Value::none().expect_result().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect("Expected response".to_string())), + VmExecutionError::from(VmInternalError::Expect("Expected response".to_string())), err ); } #[rstest] -#[case::not_a_response(Value::none(), InterpreterError::Expect("Expected response".to_string()))] -#[case::not_an_ok_response(Value::error(Value::Int(1)).unwrap(), InterpreterError::Expect("Expected ok response".to_string()))] -fn test_value_expect_result_ok_returns_interpreter_error( +#[case::not_a_response(Value::none(), VmInternalError::Expect("Expected response".to_string()))] +#[case::not_an_ok_response(Value::error(Value::Int(1)).unwrap(), VmInternalError::Expect("Expected ok response".to_string()))] +fn test_value_expect_result_ok_returns_vm_internal_error( #[case] value: Value, - #[case] expected_err: InterpreterError, + #[case] expected_err: VmInternalError, ) { let err = value.expect_result_ok().unwrap_err(); - assert_eq!(Error::from(expected_err), err); + assert_eq!(VmExecutionError::from(expected_err), err); } #[rstest] -#[case::not_a_response(Value::none(), InterpreterError::Expect("Expected response".to_string()))] -#[case::not_an_err_response(Value::okay_true(), InterpreterError::Expect("Expected err response".to_string()))] -fn test_value_expect_result_err_returns_interpreter_error( +#[case::not_a_response(Value::none(), VmInternalError::Expect("Expected response".to_string()))] +#[case::not_an_err_response(Value::okay_true(), VmInternalError::Expect("Expected err response".to_string()))] +fn test_value_expect_result_err_returns_vm_internal_error( #[case] value: Value, - #[case] expected_err: InterpreterError, + #[case] expected_err: VmInternalError, ) { let err = value.expect_result_err().unwrap_err(); - assert_eq!(Error::from(expected_err), err); + assert_eq!(VmExecutionError::from(expected_err), err); } -/// The returned InterpreterError is consensus-critical. +/// The returned VMInternalError is consensus-critical. #[test] -fn test_buff_data_len_returns_interpreter_error_consensus_critical() { +fn test_buff_data_len_returns_vm_internal_error_consensus_critical() { let err = BuffData { data: vec![1; MAX_VALUE_SIZE as usize + 1], } .len() .unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "Data length should be valid".into() )), err @@ -557,14 +557,14 @@ fn test_buff_data_len_returns_interpreter_error_consensus_critical() { } #[test] -fn test_ascii_data_len_returns_interpreter_error() { +fn test_ascii_data_len_returns_vm_internal_error() { let err = ASCIIData { data: vec![1; MAX_VALUE_SIZE as usize + 1], } .len() .unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "Data length should be valid".into() )), err @@ -572,14 +572,14 @@ fn test_ascii_data_len_returns_interpreter_error() { } #[test] -fn test_utf8_data_len_returns_interpreter_error() { +fn test_utf8_data_len_returns_vm_internal_error() { let err = UTF8Data { data: vec![vec![]; MAX_VALUE_SIZE as usize + 1], } .len() .unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "Data length should be valid".into() )), err diff --git a/clarity-types/src/tests/types/serialization.rs b/clarity-types/src/tests/types/serialization.rs index 679befd351c..9878bf148c1 100644 --- a/clarity-types/src/tests/types/serialization.rs +++ b/clarity-types/src/tests/types/serialization.rs @@ -14,8 +14,8 @@ // along with this program. If not, see . use std::io::Write; -use crate::Error; -use crate::errors::{CheckErrors, InterpreterError}; +use crate::VmExecutionError; +use crate::errors::{CheckErrorKind, VmInternalError}; use crate::types::serialization::SerializationError; use crate::types::{ ASCIIData, CharType, MAX_VALUE_SIZE, PrincipalData, QualifiedContractIdentifier, SequenceData, @@ -394,7 +394,7 @@ fn try_deser_large_tuple() { fn try_overflow_stack() { let input = "08080808080808080808070707080807080808080808080708080808080708080707080707080807080808080808080708080808080708080707080708070807080808080808080708080808080708080708080808080808080807070807080808080808070808070707080807070808070808080808070808070708070807080808080808080707080708070807080708080808080808070808080808070808070808080808080808080707080708080808080807080807070708080707080807080808080807080807070807080708080808080808070708070808080808080708080707070808070708080807080807070708"; assert_eq!( - Err(CheckErrors::TypeSignatureTooDeep.into()), + Err(CheckErrorKind::TypeSignatureTooDeep.into()), Value::try_deserialize_hex_untyped(input) ); } @@ -416,30 +416,30 @@ fn test_principals() { test_bad_expectation(standard_p, TypeSignature::BoolType); } -/// The returned InterpreterError is consensus-critical. +/// The returned VmInternalError is consensus-critical. #[test] -fn test_serialize_to_vec_returns_interpreter_error_consensus_critical() { +fn test_serialize_to_vec_returns_vm_internal_error_consensus_critical() { let value = Value::Sequence(SequenceData::String(CharType::ASCII(ASCIIData { data: vec![0; MAX_VALUE_SIZE as usize + 1], }))); let err = value.serialize_to_vec().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "IOError filling byte buffer.".into() )), err.into() ); } -/// The returned InterpreterError is consensus-critical. +/// The returned VmInternalError is consensus-critical. #[test] -fn test_serialize_to_hex_returns_interpreter_error_consensus_critical() { +fn test_serialize_to_hex_returns_vm_internal_error_consensus_critical() { let value = Value::Sequence(SequenceData::String(CharType::ASCII(ASCIIData { data: vec![0; MAX_VALUE_SIZE as usize + 1], }))); let err = value.serialize_to_hex().unwrap_err(); assert_eq!( - Error::from(InterpreterError::Expect( + VmExecutionError::from(VmInternalError::Expect( "IOError filling byte buffer.".into() )), err.into() diff --git a/clarity-types/src/tests/types/signatures.rs b/clarity-types/src/tests/types/signatures.rs index bb8fa5231a7..97768778357 100644 --- a/clarity-types/src/tests/types/signatures.rs +++ b/clarity-types/src/tests/types/signatures.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use std::collections::HashSet; -use crate::errors::CheckErrors; +use crate::errors::CheckErrorKind; use crate::types::TypeSignature::{BoolType, IntType, ListUnionType, UIntType}; use crate::types::signatures::{CallableSubtype, TypeSignature}; use crate::types::{ @@ -518,11 +518,11 @@ fn test_least_supertype() { for pair in bad_pairs { matches!( TypeSignature::least_supertype_v2_1(&pair.0, &pair.1).unwrap_err(), - CheckErrors::TypeError(..) + CheckErrorKind::TypeError(..) ); matches!( TypeSignature::least_supertype_v2_1(&pair.1, &pair.0).unwrap_err(), - CheckErrors::TypeError(..) + CheckErrorKind::TypeError(..) ); } } @@ -531,7 +531,7 @@ fn test_least_supertype() { fn test_type_signature_bound_string_ascii_type_returns_check_errors() { let err = TypeSignature::bound_string_ascii_type(MAX_VALUE_SIZE + 1).unwrap_err(); assert_eq!( - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: Max Clarity Value Size is no longer realizable in ASCII Type".to_string() ), err diff --git a/clarity-types/src/types/mod.rs b/clarity-types/src/types/mod.rs index 5fb3e36a1c0..d4f277b290a 100644 --- a/clarity-types/src/types/mod.rs +++ b/clarity-types/src/types/mod.rs @@ -37,7 +37,7 @@ pub use self::signatures::{ ListTypeData, SequenceSubtype, StringSubtype, StringUTF8Length, TupleTypeSignature, TypeSignature, }; -use crate::errors::{CheckErrors, InterpreterError, InterpreterResult as Result, RuntimeErrorType}; +use crate::errors::{CheckErrorKind, InterpreterResult as Result, RuntimeError, VmInternalError}; use crate::representations::{ClarityName, ContractName, SymbolicExpression}; // use crate::vm::ClarityVersion; @@ -81,9 +81,9 @@ impl StandardPrincipalData { } impl StandardPrincipalData { - pub fn new(version: u8, bytes: [u8; 20]) -> std::result::Result { + pub fn new(version: u8, bytes: [u8; 20]) -> std::result::Result { if version >= 32 { - return Err(InterpreterError::Expect("Unexpected principal data".into())); + return Err(VmInternalError::Expect("Unexpected principal data".into())); } Ok(Self(version, bytes)) } @@ -187,7 +187,7 @@ impl QualifiedContractIdentifier { pub fn parse(literal: &str) -> Result { let split: Vec<_> = literal.splitn(2, '.').collect(); if split.len() != 2 { - return Err(RuntimeErrorType::ParseError( + return Err(RuntimeError::TypeParseFailure( "Invalid principal literal: expected a `.` in a qualified contract name" .to_string(), ) @@ -275,7 +275,7 @@ impl TraitIdentifier { pub fn parse_fully_qualified(literal: &str) -> Result { let (issuer, contract_name, name) = Self::parse(literal)?; - let issuer = issuer.ok_or(RuntimeErrorType::BadTypeConstruction)?; + let issuer = issuer.ok_or(RuntimeError::BadTypeConstruction)?; Ok(TraitIdentifier::new(issuer, contract_name, name)) } @@ -289,7 +289,7 @@ impl TraitIdentifier { ) -> Result<(Option, ContractName, ClarityName)> { let split: Vec<_> = literal.splitn(3, '.').collect(); if split.len() != 3 { - return Err(RuntimeErrorType::ParseError( + return Err(RuntimeError::TypeParseFailure( "Invalid principal literal: expected a `.` in a qualified contract name" .to_string(), ) @@ -372,7 +372,7 @@ impl SequenceData { SequenceData::List(mut data) => data.data.remove(index), SequenceData::String(CharType::ASCII(data)) => { Value::string_ascii_from_bytes(vec![data.data[index]]).map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "BUG: failed to initialize single-byte ASCII buffer".into(), ) })? @@ -396,14 +396,14 @@ impl SequenceData { if let Value::Sequence(data) = &element { let elem_length = data.len(); if elem_length != 1 { - return Err(RuntimeErrorType::BadTypeConstruction.into()); + return Err(RuntimeError::BadTypeConstruction.into()); } } else { - return Err(RuntimeErrorType::BadTypeConstruction.into()); + return Err(RuntimeError::BadTypeConstruction.into()); } } if index >= seq_length { - return Err(CheckErrors::ValueOutOfBounds.into()); + return Err(CheckErrorKind::ValueOutOfBounds.into()); } let new_seq_data = match (self, element) { @@ -414,7 +414,7 @@ impl SequenceData { (SequenceData::List(mut data), elem) => { let entry_type = data.type_signature.get_list_item_type(); if !entry_type.admits(epoch, &elem)? { - return Err(CheckErrors::ListTypesMustMatch.into()); + return Err(CheckErrorKind::ListTypesMustMatch.into()); } data.data[index] = elem; SequenceData::List(data) @@ -433,7 +433,7 @@ impl SequenceData { data.data[index] = elem.data.swap_remove(0); SequenceData::String(CharType::UTF8(data)) } - _ => return Err(CheckErrors::ListTypesMustMatch.into()), + _ => return Err(CheckErrorKind::ListTypesMustMatch.into()), }; Value::some(Value::Sequence(new_seq_data)) @@ -454,7 +454,7 @@ impl SequenceData { Ok(None) } } else { - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::min_buffer()?), Box::new(to_find), ) @@ -483,7 +483,7 @@ impl SequenceData { Ok(None) } } else { - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::min_string_ascii()?), Box::new(to_find), ) @@ -504,7 +504,7 @@ impl SequenceData { Ok(None) } } else { - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::min_string_utf8()?), Box::new(to_find), ) @@ -573,7 +573,7 @@ impl SequenceData { SequenceData::String(CharType::UTF8(inner_data)), SequenceData::String(CharType::UTF8(ref mut other_inner_data)), ) => inner_data.append(other_inner_data), - _ => return Err(RuntimeErrorType::BadTypeConstruction.into()), + _ => return Err(RuntimeError::BadTypeConstruction.into()), }; Ok(()) } @@ -691,7 +691,7 @@ impl fmt::Display for UTF8Data { } pub trait SequencedValue { - fn type_signature(&self) -> std::result::Result; + fn type_signature(&self) -> std::result::Result; fn items(&self) -> &Vec; @@ -716,7 +716,7 @@ impl SequencedValue for ListData { self.data.drain(..).collect() } - fn type_signature(&self) -> std::result::Result { + fn type_signature(&self) -> std::result::Result { Ok(TypeSignature::SequenceType(SequenceSubtype::ListType( self.type_signature.clone(), ))) @@ -736,9 +736,9 @@ impl SequencedValue for BuffData { self.data.drain(..).collect() } - fn type_signature(&self) -> std::result::Result { + fn type_signature(&self) -> std::result::Result { let buff_length = BufferLength::try_from(self.data.len()).map_err(|_| { - CheckErrors::Expects("ERROR: Too large of a buffer successfully constructed.".into()) + CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into()) })?; Ok(TypeSignature::SequenceType(SequenceSubtype::BufferType( buff_length, @@ -759,9 +759,9 @@ impl SequencedValue for ASCIIData { self.data.drain(..).collect() } - fn type_signature(&self) -> std::result::Result { + fn type_signature(&self) -> std::result::Result { let buff_length = BufferLength::try_from(self.data.len()).map_err(|_| { - CheckErrors::Expects("ERROR: Too large of a buffer successfully constructed.".into()) + CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into()) })?; Ok(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(buff_length), @@ -770,7 +770,7 @@ impl SequencedValue for ASCIIData { fn to_value(v: &u8) -> Result { Value::string_ascii_from_bytes(vec![*v]).map_err(|_| { - InterpreterError::Expect("ERROR: Invalid ASCII string successfully constructed".into()) + VmInternalError::Expect("ERROR: Invalid ASCII string successfully constructed".into()) .into() }) } @@ -785,9 +785,9 @@ impl SequencedValue> for UTF8Data { self.data.drain(..).collect() } - fn type_signature(&self) -> std::result::Result { + fn type_signature(&self) -> std::result::Result { let str_len = StringUTF8Length::try_from(self.data.len()).map_err(|_| { - CheckErrors::Expects("ERROR: Too large of a buffer successfully constructed.".into()) + CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into()) })?; Ok(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::UTF8(str_len), @@ -796,26 +796,26 @@ impl SequencedValue> for UTF8Data { fn to_value(v: &Vec) -> Result { Value::string_utf8_from_bytes(v.clone()).map_err(|_| { - InterpreterError::Expect("ERROR: Invalid UTF8 string successfully constructed".into()) + VmInternalError::Expect("ERROR: Invalid UTF8 string successfully constructed".into()) .into() }) } } impl OptionalData { - pub fn type_signature(&self) -> std::result::Result { + pub fn type_signature(&self) -> std::result::Result { let type_result = match self.data { Some(ref v) => TypeSignature::new_option(TypeSignature::type_of(v)?), None => TypeSignature::new_option(TypeSignature::NoType), }; type_result.map_err(|_| { - CheckErrors::Expects("Should not have constructed too large of a type.".into()) + CheckErrorKind::Expects("Should not have constructed too large of a type.".into()) }) } } impl ResponseData { - pub fn type_signature(&self) -> std::result::Result { + pub fn type_signature(&self) -> std::result::Result { let type_result = match self.committed { true => TypeSignature::new_response( TypeSignature::type_of(&self.data)?, @@ -827,7 +827,7 @@ impl ResponseData { ), }; type_result.map_err(|_| { - CheckErrors::Expects("Should not have constructed too large of a type.".into()) + CheckErrorKind::Expects("Should not have constructed too large of a type.".into()) }) } } @@ -849,9 +849,9 @@ pub const NONE: Value = Value::Optional(OptionalData { data: None }); impl Value { pub fn some(data: Value) -> Result { if data.size()? + WRAPPER_VALUE_SIZE > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) } else if data.depth()? + 1 > MAX_TYPE_DEPTH { - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) } else { Ok(Value::Optional(OptionalData { data: Some(Box::new(data)), @@ -886,9 +886,9 @@ impl Value { pub fn okay(data: Value) -> Result { if data.size()? + WRAPPER_VALUE_SIZE > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) } else if data.depth()? + 1 > MAX_TYPE_DEPTH { - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) } else { Ok(Value::Response(ResponseData { committed: true, @@ -899,9 +899,9 @@ impl Value { pub fn error(data: Value) -> Result { if data.size()? + WRAPPER_VALUE_SIZE > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge.into()) + Err(CheckErrorKind::ValueTooLarge.into()) } else if data.depth()? + 1 > MAX_TYPE_DEPTH { - Err(CheckErrors::TypeSignatureTooDeep.into()) + Err(CheckErrorKind::TypeSignatureTooDeep.into()) } else { Ok(Value::Response(ResponseData { committed: false, @@ -930,7 +930,7 @@ impl Value { // be greater than MAX_VALUE_SIZE (they error on such constructions) // so we do not need to perform that check here. if (expected_type.get_max_len() as usize) < list_data.len() { - return Err(InterpreterError::FailureConstructingListWithType.into()); + return Err(VmInternalError::FailureConstructingListWithType.into()); } { @@ -938,7 +938,7 @@ impl Value { for item in &list_data { if !expected_item_type.admits(epoch, item)? { - return Err(InterpreterError::FailureConstructingListWithType.into()); + return Err(VmInternalError::FailureConstructingListWithType.into()); } } } @@ -977,7 +977,7 @@ impl Value { .map(|(value, _did_sanitize)| value) }) .collect(); - let list_data = list_data_opt.ok_or_else(|| CheckErrors::ListTypesMustMatch)?; + let list_data = list_data_opt.ok_or_else(|| CheckErrorKind::ListTypesMustMatch)?; Ok(Value::Sequence(SequenceData::List(ListData { data: list_data, type_signature: type_sig, @@ -985,7 +985,7 @@ impl Value { } /// # Errors - /// - CheckErrors::ValueTooLarge if `buff_data` is too large. + /// - CheckErrorKind::ValueTooLarge if `buff_data` is too large. pub fn buff_from(buff_data: Vec) -> Result { // check the buffer size BufferLength::try_from(buff_data.len())?; @@ -1005,7 +1005,7 @@ impl Value { for b in bytes.iter() { if !b.is_ascii_alphanumeric() && !b.is_ascii_punctuation() && !b.is_ascii_whitespace() { - return Err(CheckErrors::InvalidCharactersDetected.into()); + return Err(CheckErrorKind::InvalidCharactersDetected.into()); } } // construct the string @@ -1016,7 +1016,7 @@ impl Value { pub fn string_utf8_from_string_utf8_literal(tokenized_str: String) -> Result { let wrapped_codepoints_matcher = Regex::new("^\\\\u\\{(?P[[:xdigit:]]+)\\}") - .map_err(|_| InterpreterError::Expect("Bad regex".into()))?; + .map_err(|_| VmInternalError::Expect("Bad regex".into()))?; let mut window = tokenized_str.as_str(); let mut cursor = 0; let mut data: Vec> = vec![]; @@ -1024,12 +1024,12 @@ impl Value { if let Some(captures) = wrapped_codepoints_matcher.captures(window) { let matched = captures .name("value") - .ok_or_else(|| InterpreterError::Expect("Expected capture".into()))?; + .ok_or_else(|| VmInternalError::Expect("Expected capture".into()))?; let scalar_value = window[matched.start()..matched.end()].to_string(); let unicode_char = { let u = u32::from_str_radix(&scalar_value, 16) - .map_err(|_| CheckErrors::InvalidUTF8Encoding)?; - let c = char::from_u32(u).ok_or_else(|| CheckErrors::InvalidUTF8Encoding)?; + .map_err(|_| CheckErrorKind::InvalidUTF8Encoding)?; + let c = char::from_u32(u).ok_or_else(|| CheckErrorKind::InvalidUTF8Encoding)?; let mut encoded_char: Vec = vec![0; c.len_utf8()]; c.encode_utf8(&mut encoded_char[..]); encoded_char @@ -1056,7 +1056,7 @@ impl Value { pub fn string_utf8_from_bytes(bytes: Vec) -> Result { let validated_utf8_str = match str::from_utf8(&bytes) { Ok(string) => string, - _ => return Err(CheckErrors::InvalidCharactersDetected.into()), + _ => return Err(CheckErrorKind::InvalidCharactersDetected.into()), }; let data = validated_utf8_str .chars() @@ -1077,10 +1077,10 @@ impl Value { pub fn expect_ascii(self) -> Result { if let Value::Sequence(SequenceData::String(CharType::ASCII(ASCIIData { data }))) = self { Ok(String::from_utf8(data) - .map_err(|_| InterpreterError::Expect("Non UTF-8 data in string".into()))?) + .map_err(|_| VmInternalError::Expect("Non UTF-8 data in string".into()))?) } else { error!("Value '{self:?}' is not an ASCII string"); - Err(InterpreterError::Expect("Expected ASCII string".into()).into()) + Err(VmInternalError::Expect("Expected ASCII string".into()).into()) } } @@ -1089,7 +1089,7 @@ impl Value { Ok(inner) } else { error!("Value '{self:?}' is not a u128"); - Err(InterpreterError::Expect("Expected u128".into()).into()) + Err(VmInternalError::Expect("Expected u128".into()).into()) } } @@ -1098,7 +1098,7 @@ impl Value { Ok(inner) } else { error!("Value '{self:?}' is not an i128"); - Err(InterpreterError::Expect("Expected i128".into()).into()) + Err(VmInternalError::Expect("Expected i128".into()).into()) } } @@ -1111,11 +1111,11 @@ impl Value { "Value buffer has len {}, expected {sz}", buffdata.data.len() ); - Err(InterpreterError::Expect("Unexpected buff length".into()).into()) + Err(VmInternalError::Expect("Unexpected buff length".into()).into()) } } else { error!("Value '{self:?}' is not a buff"); - Err(InterpreterError::Expect("Expected buff".into()).into()) + Err(VmInternalError::Expect("Expected buff".into()).into()) } } @@ -1124,7 +1124,7 @@ impl Value { Ok(listdata.data) } else { error!("Value '{self:?}' is not a list"); - Err(InterpreterError::Expect("Expected list".into()).into()) + Err(VmInternalError::Expect("Expected list".into()).into()) } } @@ -1143,7 +1143,7 @@ impl Value { Ok(b) } else { error!("Value '{self:?}' is not a bool"); - Err(InterpreterError::Expect("Expected bool".into()).into()) + Err(VmInternalError::Expect("Expected bool".into()).into()) } } @@ -1152,7 +1152,7 @@ impl Value { Ok(data) } else { error!("Value '{self:?}' is not a tuple"); - Err(InterpreterError::Expect("Expected tuple".into()).into()) + Err(VmInternalError::Expect("Expected tuple".into()).into()) } } @@ -1164,7 +1164,7 @@ impl Value { } } else { error!("Value '{self:?}' is not an optional"); - Err(InterpreterError::Expect("Expected optional".into()).into()) + Err(VmInternalError::Expect("Expected optional".into()).into()) } } @@ -1173,7 +1173,7 @@ impl Value { Ok(p) } else { error!("Value '{self:?}' is not a principal"); - Err(InterpreterError::Expect("Expected principal".into()).into()) + Err(VmInternalError::Expect("Expected principal".into()).into()) } } @@ -1182,7 +1182,7 @@ impl Value { Ok(t) } else { error!("Value '{self:?}' is not a callable contract"); - Err(InterpreterError::Expect("Expected callable".into()).into()) + Err(VmInternalError::Expect("Expected callable".into()).into()) } } @@ -1195,7 +1195,7 @@ impl Value { } } else { error!("Value '{self:?}' is not a response"); - Err(InterpreterError::Expect("Expected response".into()).into()) + Err(VmInternalError::Expect("Expected response".into()).into()) } } @@ -1205,11 +1205,11 @@ impl Value { Ok(*res_data.data) } else { error!("Value is not a (ok ..)"); - Err(InterpreterError::Expect("Expected ok response".into()).into()) + Err(VmInternalError::Expect("Expected ok response".into()).into()) } } else { error!("Value '{self:?}' is not a response"); - Err(InterpreterError::Expect("Expected response".into()).into()) + Err(VmInternalError::Expect("Expected response".into()).into()) } } @@ -1219,11 +1219,11 @@ impl Value { Ok(*res_data.data) } else { error!("Value is not a (err ..)"); - Err(InterpreterError::Expect("Expected err response".into()).into()) + Err(VmInternalError::Expect("Expected err response".into()).into()) } } else { error!("Value '{self:?}' is not a response"); - Err(InterpreterError::Expect("Expected response".into()).into()) + Err(VmInternalError::Expect("Expected response".into()).into()) } } } @@ -1233,7 +1233,7 @@ impl BuffData { self.data .len() .try_into() - .map_err(|_| InterpreterError::Expect("Data length should be valid".into()).into()) + .map_err(|_| VmInternalError::Expect("Data length should be valid".into()).into()) } pub fn as_slice(&self) -> &[u8] { @@ -1254,7 +1254,7 @@ impl ListData { self.data .len() .try_into() - .map_err(|_| InterpreterError::Expect("Data length should be valid".into()).into()) + .map_err(|_| VmInternalError::Expect("Data length should be valid".into()).into()) } pub fn is_empty(&self) -> bool { @@ -1268,7 +1268,7 @@ impl ListData { let max_len = self.type_signature.get_max_len() + other_seq.type_signature.get_max_len(); for item in other_seq.data.into_iter() { let (item, _) = Value::sanitize_value(epoch, &entry_type, item) - .ok_or_else(|| CheckErrors::ListTypesMustMatch)?; + .ok_or_else(|| CheckErrorKind::ListTypesMustMatch)?; self.data.push(item); } @@ -1286,7 +1286,7 @@ impl ASCIIData { self.data .len() .try_into() - .map_err(|_| InterpreterError::Expect("Data length should be valid".into()).into()) + .map_err(|_| VmInternalError::Expect("Data length should be valid".into()).into()) } } @@ -1299,7 +1299,7 @@ impl UTF8Data { self.data .len() .try_into() - .map_err(|_| InterpreterError::Expect("Data length should be valid".into()).into()) + .map_err(|_| VmInternalError::Expect("Data length should be valid".into()).into()) } } @@ -1401,10 +1401,11 @@ impl PrincipalData { } pub fn parse_standard_principal(literal: &str) -> Result { - let (version, data) = c32::c32_address_decode(literal) - .map_err(|x| RuntimeErrorType::ParseError(format!("Invalid principal literal: {x}")))?; + let (version, data) = c32::c32_address_decode(literal).map_err(|x| { + RuntimeError::TypeParseFailure(format!("Invalid principal literal: {x}")) + })?; if data.len() != 20 { - return Err(RuntimeErrorType::ParseError( + return Err(RuntimeError::TypeParseFailure( "Invalid principal literal: Expected 20 data bytes.".to_string(), ) .into()); @@ -1552,7 +1553,9 @@ impl TupleData { let entry = type_map.entry(name.clone()); match entry { Entry::Vacant(e) => e.insert(type_info), - Entry::Occupied(_) => return Err(CheckErrors::NameAlreadyUsed(name.into()).into()), + Entry::Occupied(_) => { + return Err(CheckErrorKind::NameAlreadyUsed(name.into()).into()); + } }; data_map.insert(name, value); } @@ -1571,9 +1574,9 @@ impl TupleData { for (name, value) in data.into_iter() { let expected_type = expected .field_type(&name) - .ok_or(InterpreterError::FailureConstructingTupleWithType)?; + .ok_or(VmInternalError::FailureConstructingTupleWithType)?; if !expected_type.admits(epoch, &value)? { - return Err(InterpreterError::FailureConstructingTupleWithType.into()); + return Err(VmInternalError::FailureConstructingTupleWithType.into()); } data_map.insert(name, value); } @@ -1582,13 +1585,13 @@ impl TupleData { pub fn get(&self, name: &str) -> Result<&Value> { self.data_map.get(name).ok_or_else(|| { - CheckErrors::NoSuchTupleField(name.to_string(), self.type_signature.clone()).into() + CheckErrorKind::NoSuchTupleField(name.to_string(), self.type_signature.clone()).into() }) } pub fn get_owned(mut self, name: &str) -> Result { self.data_map.remove(name).ok_or_else(|| { - CheckErrors::NoSuchTupleField(name.to_string(), self.type_signature.clone()).into() + CheckErrorKind::NoSuchTupleField(name.to_string(), self.type_signature.clone()).into() }) } diff --git a/clarity-types/src/types/serialization.rs b/clarity-types/src/types/serialization.rs index 2179efd824c..929b2e43136 100644 --- a/clarity-types/src/types/serialization.rs +++ b/clarity-types/src/types/serialization.rs @@ -23,7 +23,7 @@ use stacks_common::util::hash::{hex_bytes, to_hex}; use stacks_common::util::retry::BoundReader; use super::{ListTypeData, TupleTypeSignature}; -use crate::errors::{CheckErrors, IncomparableError, InterpreterError}; +use crate::errors::{CheckErrorKind, IncomparableError, VmInternalError}; use crate::representations::{ClarityName, ContractName, MAX_STRING_LEN}; use crate::types::{ BOUND_VALUE_SERIALIZATION_BYTES, BufferLength, CallableData, CharType, MAX_TYPE_DEPTH, @@ -33,14 +33,14 @@ use crate::types::{ /// Errors that may occur in serialization or deserialization /// If deserialization failed because the described type is a bad type and -/// a CheckError is thrown, it gets wrapped in BadTypeError. +/// a CheckErrorKind is thrown, it gets wrapped in BadTypeError. /// Any IOErrrors from the supplied buffer will manifest as IOError variants, /// except for EOF -- if the deserialization code experiences an EOF, it is caught /// and rethrown as DeserializationError #[derive(Debug, PartialEq)] pub enum SerializationError { IOError(IncomparableError), - BadTypeError(CheckErrors), + BadTypeError(CheckErrorKind), DeserializationError(String), DeserializeExpected(Box), LeftoverBytesInDeserialization, @@ -122,8 +122,8 @@ impl From<&str> for SerializationError { } } -impl From for SerializationError { - fn from(e: CheckErrors) -> Self { +impl From for SerializationError { + fn from(e: CheckErrorKind) -> Self { SerializationError::BadTypeError(e) } } @@ -394,7 +394,7 @@ impl TypeSignature { /// size of a `(buff 1024*1024)` is `1+1024*1024` because of the /// type prefix byte. However, that is 1 byte larger than the maximum /// buffer size in Clarity. - pub fn max_serialized_size(&self) -> Result { + pub fn max_serialized_size(&self) -> Result { let type_prefix_size = 1; let max_output_size = match self { @@ -405,7 +405,7 @@ impl TypeSignature { // `some` or similar with `result` types). So, when // serializing an object with a `NoType`, the other // branch should always be used. - return Err(CheckErrors::CouldNotDetermineSerializationType); + return Err(CheckErrorKind::CouldNotDetermineSerializationType); } TypeSignature::IntType => 16, TypeSignature::UIntType => 16, @@ -417,14 +417,14 @@ impl TypeSignature { .get_max_len() .checked_mul(list_type.get_list_item_type().max_serialized_size()?) .and_then(|x| x.checked_add(list_length_encode)) - .ok_or_else(|| CheckErrors::ValueTooLarge)? + .ok_or_else(|| CheckErrorKind::ValueTooLarge)? } TypeSignature::SequenceType(SequenceSubtype::BufferType(buff_length)) => { // u32 length as big-endian bytes let buff_length_encode = 4; u32::from(buff_length) .checked_add(buff_length_encode) - .ok_or_else(|| CheckErrors::ValueTooLarge)? + .ok_or_else(|| CheckErrorKind::ValueTooLarge)? } TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::ASCII( length, @@ -434,7 +434,7 @@ impl TypeSignature { // ascii is 1-byte per character u32::from(length) .checked_add(str_length_encode) - .ok_or_else(|| CheckErrors::ValueTooLarge)? + .ok_or_else(|| CheckErrorKind::ValueTooLarge)? } TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::UTF8( length, @@ -445,7 +445,7 @@ impl TypeSignature { u32::from(length) .checked_mul(4) .and_then(|x| x.checked_add(str_length_encode)) - .ok_or_else(|| CheckErrors::ValueTooLarge)? + .ok_or_else(|| CheckErrorKind::ValueTooLarge)? } TypeSignature::PrincipalType | TypeSignature::CallableType(_) @@ -468,7 +468,7 @@ impl TypeSignature { .checked_add(1) // length of key-name .and_then(|x| x.checked_add(key.len() as u32)) // ClarityName is ascii-only, so 1 byte per length .and_then(|x| x.checked_add(value_size)) - .ok_or_else(|| CheckErrors::ValueTooLarge)?; + .ok_or_else(|| CheckErrorKind::ValueTooLarge)?; } total_size } @@ -477,7 +477,7 @@ impl TypeSignature { Ok(size) => size, // if NoType, then this is just serializing a none // value, which is only the type prefix - Err(CheckErrors::CouldNotDetermineSerializationType) => 0, + Err(CheckErrorKind::CouldNotDetermineSerializationType) => 0, Err(e) => return Err(e), } } @@ -485,17 +485,17 @@ impl TypeSignature { let (ok_type, err_type) = response_types.as_ref(); let (ok_type_max_size, no_ok_type) = match ok_type.max_serialized_size() { Ok(size) => (size, false), - Err(CheckErrors::CouldNotDetermineSerializationType) => (0, true), + Err(CheckErrorKind::CouldNotDetermineSerializationType) => (0, true), Err(e) => return Err(e), }; let err_type_max_size = match err_type.max_serialized_size() { Ok(size) => size, - Err(CheckErrors::CouldNotDetermineSerializationType) => { + Err(CheckErrorKind::CouldNotDetermineSerializationType) => { if no_ok_type { // if both the ok type and the error type are NoType, - // throw a CheckError. This should not be possible, but the check + // throw a CheckErrorKind. This should not be possible, but the check // is done out of caution. - return Err(CheckErrors::CouldNotDetermineSerializationType); + return Err(CheckErrorKind::CouldNotDetermineSerializationType); } else { 0 } @@ -505,13 +505,13 @@ impl TypeSignature { cmp::max(ok_type_max_size, err_type_max_size) } TypeSignature::ListUnionType(_) => { - return Err(CheckErrors::CouldNotDetermineSerializationType); + return Err(CheckErrorKind::CouldNotDetermineSerializationType); } }; max_output_size .checked_add(type_prefix_size) - .ok_or_else(|| CheckErrors::ValueTooLarge) + .ok_or_else(|| CheckErrorKind::ValueTooLarge) } } @@ -583,7 +583,7 @@ impl Value { UNSANITIZED_DEPTH_CHECK }; if stack.len() > depth_check { - return Err(CheckErrors::TypeSignatureTooDeep.into()); + return Err(CheckErrorKind::TypeSignatureTooDeep.into()); } #[allow(clippy::expect_used)] @@ -1215,15 +1215,15 @@ impl Write for WriteCounter { } impl Value { - pub fn serialize_to_vec(&self) -> Result, InterpreterError> { + pub fn serialize_to_vec(&self) -> Result, VmInternalError> { let mut byte_serialization = Vec::new(); self.serialize_write(&mut byte_serialization) - .map_err(|_| InterpreterError::Expect("IOError filling byte buffer.".into()))?; + .map_err(|_| VmInternalError::Expect("IOError filling byte buffer.".into()))?; Ok(byte_serialization) } /// This does *not* perform any data sanitization - pub fn serialize_to_hex(&self) -> Result { + pub fn serialize_to_hex(&self) -> Result { let byte_serialization = self.serialize_to_vec()?; Ok(to_hex(byte_serialization.as_slice())) } diff --git a/clarity-types/src/types/signatures.rs b/clarity-types/src/types/signatures.rs index a8e49b92f9d..3fd0ee57cb4 100644 --- a/clarity-types/src/types/signatures.rs +++ b/clarity-types/src/types/signatures.rs @@ -23,7 +23,7 @@ use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use stacks_common::types::StacksEpochId; -use crate::errors::CheckErrors; +use crate::errors::CheckErrorKind; use crate::representations::{CONTRACT_MAX_NAME_LENGTH, ClarityName, ContractName}; use crate::types::{ CharType, MAX_TYPE_DEPTH, MAX_VALUE_SIZE, PrincipalData, QualifiedContractIdentifier, @@ -150,7 +150,7 @@ pub enum SequenceSubtype { } impl SequenceSubtype { - pub fn unit_type(&self) -> Result { + pub fn unit_type(&self) -> Result { match &self { SequenceSubtype::ListType(list_data) => Ok(list_data.clone().destruct().0), SequenceSubtype::BufferType(_) => TypeSignature::min_buffer(), @@ -296,10 +296,10 @@ impl From for u32 { } impl TryFrom for BufferLength { - type Error = CheckErrors; - fn try_from(data: u32) -> Result { + type Error = CheckErrorKind; + fn try_from(data: u32) -> Result { if data > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else { Ok(BufferLength(data)) } @@ -307,10 +307,10 @@ impl TryFrom for BufferLength { } impl TryFrom for BufferLength { - type Error = CheckErrors; - fn try_from(data: usize) -> Result { + type Error = CheckErrorKind; + fn try_from(data: usize) -> Result { if data > (MAX_VALUE_SIZE as usize) { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else { Ok(BufferLength(data as u32)) } @@ -318,12 +318,12 @@ impl TryFrom for BufferLength { } impl TryFrom for BufferLength { - type Error = CheckErrors; - fn try_from(data: i128) -> Result { + type Error = CheckErrorKind; + fn try_from(data: i128) -> Result { if data > (MAX_VALUE_SIZE as i128) { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else if data < 0 { - Err(CheckErrors::ValueOutOfBounds) + Err(CheckErrorKind::ValueOutOfBounds) } else { Ok(BufferLength(data as u32)) } @@ -343,13 +343,13 @@ impl From for u32 { } impl TryFrom for StringUTF8Length { - type Error = CheckErrors; - fn try_from(data: u32) -> Result { + type Error = CheckErrorKind; + fn try_from(data: u32) -> Result { let len = data .checked_mul(4) - .ok_or_else(|| CheckErrors::ValueTooLarge)?; + .ok_or_else(|| CheckErrorKind::ValueTooLarge)?; if len > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else { Ok(StringUTF8Length(data)) } @@ -357,13 +357,13 @@ impl TryFrom for StringUTF8Length { } impl TryFrom for StringUTF8Length { - type Error = CheckErrors; - fn try_from(data: usize) -> Result { + type Error = CheckErrorKind; + fn try_from(data: usize) -> Result { let len = data .checked_mul(4) - .ok_or_else(|| CheckErrors::ValueTooLarge)?; + .ok_or_else(|| CheckErrorKind::ValueTooLarge)?; if len > (MAX_VALUE_SIZE as usize) { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else { Ok(StringUTF8Length(data as u32)) } @@ -371,15 +371,15 @@ impl TryFrom for StringUTF8Length { } impl TryFrom for StringUTF8Length { - type Error = CheckErrors; - fn try_from(data: i128) -> Result { + type Error = CheckErrorKind; + fn try_from(data: i128) -> Result { let len = data .checked_mul(4) - .ok_or_else(|| CheckErrors::ValueTooLarge)?; + .ok_or_else(|| CheckErrorKind::ValueTooLarge)?; if len > (MAX_VALUE_SIZE as i128) { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else if data < 0 { - Err(CheckErrors::ValueOutOfBounds) + Err(CheckErrorKind::ValueOutOfBounds) } else { Ok(StringUTF8Length(data as u32)) } @@ -387,10 +387,13 @@ impl TryFrom for StringUTF8Length { } impl ListTypeData { - pub fn new_list(entry_type: TypeSignature, max_len: u32) -> Result { + pub fn new_list( + entry_type: TypeSignature, + max_len: u32, + ) -> Result { let would_be_depth = 1 + entry_type.depth(); if would_be_depth > MAX_TYPE_DEPTH { - return Err(CheckErrors::TypeSignatureTooDeep); + return Err(CheckErrorKind::TypeSignatureTooDeep); } let list_data = ListTypeData { @@ -399,9 +402,9 @@ impl ListTypeData { }; let would_be_size = list_data .inner_size()? - .ok_or_else(|| CheckErrors::ValueTooLarge)?; + .ok_or_else(|| CheckErrorKind::ValueTooLarge)?; if would_be_size > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else { Ok(list_data) } @@ -429,13 +432,13 @@ impl ListTypeData { } impl TypeSignature { - pub fn new_option(inner_type: TypeSignature) -> Result { + pub fn new_option(inner_type: TypeSignature) -> Result { let new_size = WRAPPER_VALUE_SIZE + inner_type.size()?; let new_depth = 1 + inner_type.depth(); if new_size > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else if new_depth > MAX_TYPE_DEPTH { - Err(CheckErrors::TypeSignatureTooDeep) + Err(CheckErrorKind::TypeSignatureTooDeep) } else { Ok(OptionalType(Box::new(inner_type))) } @@ -444,27 +447,27 @@ impl TypeSignature { pub fn new_response( ok_type: TypeSignature, err_type: TypeSignature, - ) -> Result { + ) -> Result { let new_size = WRAPPER_VALUE_SIZE + cmp::max(ok_type.size()?, err_type.size()?); let new_depth = 1 + cmp::max(ok_type.depth(), err_type.depth()); if new_size > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else if new_depth > MAX_TYPE_DEPTH { - Err(CheckErrors::TypeSignatureTooDeep) + Err(CheckErrorKind::TypeSignatureTooDeep) } else { Ok(ResponseType(Box::new((ok_type, err_type)))) } } - pub fn new_string_ascii(len: usize) -> Result { + pub fn new_string_ascii(len: usize) -> Result { let len = BufferLength::try_from(len)?; Ok(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(len), ))) } - pub fn new_string_utf8(len: usize) -> Result { + pub fn new_string_utf8(len: usize) -> Result { let len = StringUTF8Length::try_from(len)?; Ok(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::UTF8(len), @@ -479,7 +482,7 @@ impl TypeSignature { &TypeSignature::NoType == self } - pub fn admits(&self, epoch: &StacksEpochId, x: &Value) -> Result { + pub fn admits(&self, epoch: &StacksEpochId, x: &Value) -> Result { let x_type = TypeSignature::type_of(x)?; self.admits_type(epoch, &x_type) } @@ -488,7 +491,7 @@ impl TypeSignature { &self, epoch: &StacksEpochId, other: &TypeSignature, - ) -> Result { + ) -> Result { match epoch { StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => self.admits_type_v2_0(other), StacksEpochId::Epoch21 @@ -500,11 +503,13 @@ impl TypeSignature { | StacksEpochId::Epoch31 | StacksEpochId::Epoch32 | StacksEpochId::Epoch33 => self.admits_type_v2_1(other), - StacksEpochId::Epoch10 => Err(CheckErrors::Expects("epoch 1.0 not supported".into())), + StacksEpochId::Epoch10 => { + Err(CheckErrorKind::Expects("epoch 1.0 not supported".into())) + } } } - pub fn admits_type_v2_0(&self, other: &TypeSignature) -> Result { + pub fn admits_type_v2_0(&self, other: &TypeSignature) -> Result { match self { SequenceType(SequenceSubtype::ListType(my_list_type)) => { if let SequenceType(SequenceSubtype::ListType(other_list_type)) = other { @@ -586,18 +591,18 @@ impl TypeSignature { Ok(false) } } - NoType => Err(CheckErrors::CouldNotDetermineType), - CallableType(_) => Err(CheckErrors::Expects( + NoType => Err(CheckErrorKind::CouldNotDetermineType), + CallableType(_) => Err(CheckErrorKind::Expects( "CallableType should not be used in epoch v2.0".into(), )), - ListUnionType(_) => Err(CheckErrors::Expects( + ListUnionType(_) => Err(CheckErrorKind::Expects( "ListUnionType should not be used in epoch v2.0".into(), )), _ => Ok(other == self), } } - fn admits_type_v2_1(&self, other: &TypeSignature) -> Result { + fn admits_type_v2_1(&self, other: &TypeSignature) -> Result { let other = match other.concretize() { Ok(other) => other, Err(_) => { @@ -686,7 +691,7 @@ impl TypeSignature { Ok(false) } } - NoType => Err(CheckErrors::CouldNotDetermineType), + NoType => Err(CheckErrorKind::CouldNotDetermineType), _ => Ok(&other == self), } } @@ -743,7 +748,7 @@ impl TypeSignature { /// Concretize the type. The input to this method may include /// `ListUnionType` and the `CallableType` variant for a `principal. /// This method turns these "temporary" types into actual types. - pub fn concretize(&self) -> Result { + pub fn concretize(&self) -> Result { match self { ListUnionType(types) => { let mut is_trait = None; @@ -752,7 +757,7 @@ impl TypeSignature { match partial { CallableSubtype::Principal(_) => { if is_trait.is_some() { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(TypeSignature::CallableType(partial.clone())), Box::new(TypeSignature::PrincipalType), )); @@ -762,7 +767,7 @@ impl TypeSignature { } CallableSubtype::Trait(t) => { if is_principal { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::CallableType(partial.clone())), )); @@ -785,12 +790,12 @@ impl TypeSignature { } impl TryFrom> for TupleTypeSignature { - type Error = CheckErrors; + type Error = CheckErrorKind; fn try_from( type_data: Vec<(ClarityName, TypeSignature)>, - ) -> Result { + ) -> Result { if type_data.is_empty() { - return Err(CheckErrors::EmptyTuplesNotAllowed); + return Err(CheckErrorKind::EmptyTuplesNotAllowed); } let mut type_map = BTreeMap::new(); @@ -798,7 +803,7 @@ impl TryFrom> for TupleTypeSignature { if let Entry::Vacant(e) = type_map.entry(name.clone()) { e.insert(type_info); } else { - return Err(CheckErrors::NameAlreadyUsed(name.into())); + return Err(CheckErrorKind::NameAlreadyUsed(name.into())); } } TupleTypeSignature::try_from(type_map) @@ -806,25 +811,25 @@ impl TryFrom> for TupleTypeSignature { } impl TryFrom> for TupleTypeSignature { - type Error = CheckErrors; + type Error = CheckErrorKind; fn try_from( type_map: BTreeMap, - ) -> Result { + ) -> Result { if type_map.is_empty() { - return Err(CheckErrors::EmptyTuplesNotAllowed); + return Err(CheckErrorKind::EmptyTuplesNotAllowed); } for child_sig in type_map.values() { if (1 + child_sig.depth()) > MAX_TYPE_DEPTH { - return Err(CheckErrors::TypeSignatureTooDeep); + return Err(CheckErrorKind::TypeSignatureTooDeep); } } let type_map = Arc::new(type_map.into_iter().collect()); let result = TupleTypeSignature { type_map }; let would_be_size = result .inner_size()? - .ok_or_else(|| CheckErrors::ValueTooLarge)?; + .ok_or_else(|| CheckErrorKind::ValueTooLarge)?; if would_be_size > MAX_VALUE_SIZE { - Err(CheckErrors::ValueTooLarge) + Err(CheckErrorKind::ValueTooLarge) } else { Ok(result) } @@ -854,7 +859,7 @@ impl TupleTypeSignature { &self, epoch: &StacksEpochId, other: &TupleTypeSignature, - ) -> Result { + ) -> Result { if self.type_map.len() != other.type_map.len() { return Ok(false); } @@ -878,78 +883,78 @@ impl TupleTypeSignature { } impl TypeSignature { - pub fn empty_buffer() -> Result { + pub fn empty_buffer() -> Result { Ok(SequenceType(SequenceSubtype::BufferType( 0_u32.try_into().map_err(|_| { - CheckErrors::Expects("FAIL: Empty clarity value size is not realizable".into()) + CheckErrorKind::Expects("FAIL: Empty clarity value size is not realizable".into()) })?, ))) } - pub fn min_buffer() -> Result { + pub fn min_buffer() -> Result { Ok(SequenceType(SequenceSubtype::BufferType( 1_u32.try_into().map_err(|_| { - CheckErrors::Expects("FAIL: Min clarity value size is not realizable".into()) + CheckErrorKind::Expects("FAIL: Min clarity value size is not realizable".into()) })?, ))) } - pub fn min_string_ascii() -> Result { + pub fn min_string_ascii() -> Result { Ok(SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(1_u32.try_into().map_err(|_| { - CheckErrors::Expects("FAIL: Min clarity value size is not realizable".into()) + CheckErrorKind::Expects("FAIL: Min clarity value size is not realizable".into()) })?), ))) } - pub fn min_string_utf8() -> Result { + pub fn min_string_utf8() -> Result { Ok(SequenceType(SequenceSubtype::StringType( StringSubtype::UTF8(1_u32.try_into().map_err(|_| { - CheckErrors::Expects("FAIL: Min clarity value size is not realizable".into()) + CheckErrorKind::Expects("FAIL: Min clarity value size is not realizable".into()) })?), ))) } - pub fn max_string_ascii() -> Result { + pub fn max_string_ascii() -> Result { Ok(SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(BufferLength::try_from(MAX_VALUE_SIZE).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: Max Clarity Value Size is no longer realizable in ASCII Type".into(), ) })?), ))) } - pub fn max_string_utf8() -> Result { + pub fn max_string_utf8() -> Result { Ok(SequenceType(SequenceSubtype::StringType( StringSubtype::UTF8(StringUTF8Length::try_from(MAX_VALUE_SIZE / 4).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: Max Clarity Value Size is no longer realizable in UTF8 Type".into(), ) })?), ))) } - pub fn max_buffer() -> Result { + pub fn max_buffer() -> Result { Ok(SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(MAX_VALUE_SIZE).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: Max Clarity Value Size is no longer realizable in Buffer Type".into(), ) })?, ))) } - pub fn contract_name_string_ascii_type() -> Result { + pub fn contract_name_string_ascii_type() -> Result { TypeSignature::bound_string_ascii_type(CONTRACT_MAX_NAME_LENGTH.try_into().map_err( - |_| CheckErrors::Expects("FAIL: contract name max length exceeds u32 space".into()), + |_| CheckErrorKind::Expects("FAIL: contract name max length exceeds u32 space".into()), )?) } - pub fn bound_string_ascii_type(max_len: u32) -> Result { + pub fn bound_string_ascii_type(max_len: u32) -> Result { Ok(SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(BufferLength::try_from(max_len).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: Max Clarity Value Size is no longer realizable in ASCII Type".into(), ) })?), @@ -961,7 +966,7 @@ impl TypeSignature { epoch: &StacksEpochId, a: &TypeSignature, b: &TypeSignature, - ) -> Result { + ) -> Result { if a.is_no_type() { Ok(b.clone()) } else if b.is_no_type() { @@ -1012,7 +1017,7 @@ impl TypeSignature { epoch: &StacksEpochId, a: &TypeSignature, b: &TypeSignature, - ) -> Result { + ) -> Result { match epoch { StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => Self::least_supertype_v2_0(a, b), StacksEpochId::Epoch21 @@ -1024,14 +1029,16 @@ impl TypeSignature { | StacksEpochId::Epoch31 | StacksEpochId::Epoch32 | StacksEpochId::Epoch33 => Self::least_supertype_v2_1(a, b), - StacksEpochId::Epoch10 => Err(CheckErrors::Expects("epoch 1.0 not supported".into())), + StacksEpochId::Epoch10 => { + Err(CheckErrorKind::Expects("epoch 1.0 not supported".into())) + } } } pub fn least_supertype_v2_0( a: &TypeSignature, b: &TypeSignature, - ) -> Result { + ) -> Result { match (a, b) { ( TupleType(TupleTypeSignature { type_map: types_a }), @@ -1039,7 +1046,7 @@ impl TypeSignature { ) => { let mut type_map_out = BTreeMap::new(); for (name, entry_a) in types_a.iter() { - let entry_b = types_b.get(name).ok_or(CheckErrors::TypeError( + let entry_b = types_b.get(name).ok_or(CheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), ))?; @@ -1048,7 +1055,7 @@ impl TypeSignature { } Ok(TupleTypeSignature::try_from(type_map_out) .map(|x| x.into()) - .map_err(|_| CheckErrors::SupertypeTooLarge)?) + .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) } ( SequenceType(SequenceSubtype::ListType(ListTypeData { @@ -1069,7 +1076,7 @@ impl TypeSignature { }; let max_len = cmp::max(len_a, len_b); Ok(Self::list_of(entry_type, *max_len) - .map_err(|_| CheckErrors::SupertypeTooLarge)?) + .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) } (ResponseType(resp_a), ResponseType(resp_b)) => { let ok_type = @@ -1128,7 +1135,7 @@ impl TypeSignature { if x == y { Ok(x.clone()) } else { - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), )) @@ -1140,7 +1147,7 @@ impl TypeSignature { pub fn least_supertype_v2_1( a: &TypeSignature, b: &TypeSignature, - ) -> Result { + ) -> Result { match (a, b) { ( TupleType(TupleTypeSignature { type_map: types_a }), @@ -1148,7 +1155,7 @@ impl TypeSignature { ) => { let mut type_map_out = BTreeMap::new(); for (name, entry_a) in types_a.iter() { - let entry_b = types_b.get(name).ok_or(CheckErrors::TypeError( + let entry_b = types_b.get(name).ok_or(CheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), ))?; @@ -1157,7 +1164,7 @@ impl TypeSignature { } Ok(TupleTypeSignature::try_from(type_map_out) .map(|x| x.into()) - .map_err(|_| CheckErrors::SupertypeTooLarge)?) + .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) } ( SequenceType(SequenceSubtype::ListType(ListTypeData { @@ -1178,7 +1185,7 @@ impl TypeSignature { }; let max_len = cmp::max(len_a, len_b); Ok(Self::list_of(entry_type, *max_len) - .map_err(|_| CheckErrors::SupertypeTooLarge)?) + .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) } (ResponseType(resp_a), ResponseType(resp_b)) => { let ok_type = @@ -1259,7 +1266,7 @@ impl TypeSignature { if all_principals { Ok(PrincipalType) } else { - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), )) @@ -1272,7 +1279,7 @@ impl TypeSignature { if x == y { Ok(x.clone()) } else { - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), )) @@ -1281,7 +1288,10 @@ impl TypeSignature { } } - pub fn list_of(item_type: TypeSignature, max_len: u32) -> Result { + pub fn list_of( + item_type: TypeSignature, + max_len: u32, + ) -> Result { ListTypeData::new_list(item_type, max_len).map(|x| x.into()) } @@ -1292,7 +1302,7 @@ impl TypeSignature { } } - pub fn type_of(x: &Value) -> Result { + pub fn type_of(x: &Value) -> Result { let out = match x { Value::Principal(_) => PrincipalType, Value::Int(_v) => IntType, @@ -1321,7 +1331,7 @@ impl TypeSignature { Ok(out) } - pub fn literal_type_of(x: &Value) -> Result { + pub fn literal_type_of(x: &Value) -> Result { match x { Value::Principal(PrincipalData::Contract(contract_id)) => Ok(CallableType( CallableSubtype::Principal(contract_id.clone()), @@ -1331,19 +1341,19 @@ impl TypeSignature { } // Checks if resulting type signature is of valid size. - pub fn construct_parent_list_type(args: &[Value]) -> Result { - let children_types: Result, CheckErrors> = + pub fn construct_parent_list_type(args: &[Value]) -> Result { + let children_types: Result, CheckErrorKind> = args.iter().map(TypeSignature::type_of).collect(); TypeSignature::parent_list_type(&children_types?) } - pub fn parent_list_type(children: &[TypeSignature]) -> Result { + pub fn parent_list_type(children: &[TypeSignature]) -> Result { if let Some((first, rest)) = children.split_first() { let mut current_entry_type = first.clone(); for next_entry in rest.iter() { current_entry_type = Self::least_supertype_v2_1(¤t_entry_type, next_entry)?; } - let len = u32::try_from(children.len()).map_err(|_| CheckErrors::ValueTooLarge)?; + let len = u32::try_from(children.len()).map_err(|_| CheckErrorKind::ValueTooLarge)?; ListTypeData::new_list(current_entry_type, len) } else { Ok(TypeSignature::empty_list()) @@ -1383,16 +1393,16 @@ impl TypeSignature { } } - pub fn size(&self) -> Result { + pub fn size(&self) -> Result { self.inner_size()?.ok_or_else(|| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: .size() overflowed on too large of a type. construction should have failed!" .into(), ) }) } - fn inner_size(&self) -> Result, CheckErrors> { + fn inner_size(&self) -> Result, CheckErrorKind> { let out = match self { // NoType's may be asked for their size at runtime -- // legal constructions like `(ok 1)` have NoType parts (if they have unknown error variant types). @@ -1425,9 +1435,9 @@ impl TypeSignature { Ok(out) } - pub fn type_size(&self) -> Result { + pub fn type_size(&self) -> Result { self.inner_type_size() - .ok_or_else(|| CheckErrors::ValueTooLarge) + .ok_or_else(|| CheckErrorKind::ValueTooLarge) } /// Returns the size of the _type signature_ @@ -1457,7 +1467,7 @@ impl TypeSignature { impl ListTypeData { /// List Size: type_signature_size + max_len * entry_type.size() - fn inner_size(&self) -> Result, CheckErrors> { + fn inner_size(&self) -> Result, CheckErrorKind> { let total_size = self .entry_type .size()? @@ -1506,9 +1516,10 @@ impl TupleTypeSignature { } } - pub fn size(&self) -> Result { - self.inner_size()? - .ok_or_else(|| CheckErrors::Expects("size() overflowed on a constructed type.".into())) + pub fn size(&self) -> Result { + self.inner_size()?.ok_or_else(|| { + CheckErrorKind::Expects("size() overflowed on a constructed type.".into()) + }) } fn max_depth(&self) -> u8 { @@ -1522,7 +1533,7 @@ impl TupleTypeSignature { /// Tuple Size: /// size( btreemap ) + type_size /// size( btreemap ) = 2*map.len() + sum(names) + sum(values) - fn inner_size(&self) -> Result, CheckErrors> { + fn inner_size(&self) -> Result, CheckErrorKind> { let Some(mut total_size) = u32::try_from(self.type_map.len()) .ok() .and_then(|x| x.checked_mul(2)) diff --git a/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs b/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs index a4fd207c57f..7b509750abe 100644 --- a/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs +++ b/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs @@ -29,7 +29,7 @@ use clarity::vm::ClarityName; use clarity::vm::representations::ContractName; use clarity::vm::types::serialization::SerializationError; use stacks_common::types::StacksEpochId; -use clarity::vm::analysis::CheckErrors; +use clarity::vm::analysis::CheckErrorKind; use clarity::vm::types::StringSubtype; use libfuzzer_sys::arbitrary; @@ -131,9 +131,9 @@ impl arbitrary::Arbitrary<'_> for FuzzClarityValue { } } -pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result { +pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result { match me { - TypeSignature::NoType => Err(CheckErrors::CouldNotDetermineType), + TypeSignature::NoType => Err(CheckErrorKind::CouldNotDetermineType), TypeSignature::IntType => match x { ClarityValue::Int(_) => Ok(true), _ => Ok(false), @@ -238,7 +238,7 @@ pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result Err(CheckErrors::TraitReferenceNotAllowed), + TypeSignature::TraitReferenceType(_) => Err(CheckErrorKind::TraitReferenceNotAllowed), } } @@ -274,7 +274,7 @@ fn fuzz_sanitize(input: ClarityValue) { deserialize_unsanitized.unwrap_err(); } else { let deser_value = match deserialize_unsanitized { - Err(SerializationError::BadTypeError(CheckErrors::TypeSignatureTooDeep)) => { + Err(SerializationError::BadTypeError(CheckErrorKind::TypeSignatureTooDeep)) => { // pre-2.4, deserializer could error on types deeper than a deserialization limit of 16. // with sanitization enabled (a 2.4-gated feature), these serializations are readable. ClarityValue::deserialize_read( @@ -294,7 +294,7 @@ fn fuzz_sanitize(input: ClarityValue) { true ) { Ok(x) => x, - Err(SerializationError::BadTypeError(CheckErrors::TypeSignatureTooDeep)) => { + Err(SerializationError::BadTypeError(CheckErrorKind::TypeSignatureTooDeep)) => { assert!(!did_strict_admit, "Unsanitized inputs may fail to deserialize, but they must have needed sanitization"); // check that the sanitized value *is* readable let serialized = sanitized_value.serialize_to_vec().expect("serialize sanitized"); @@ -303,7 +303,7 @@ fn fuzz_sanitize(input: ClarityValue) { Some(&computed_type), false ) { - Err(SerializationError::BadTypeError(CheckErrors::TypeSignatureTooDeep)) => { + Err(SerializationError::BadTypeError(CheckErrorKind::TypeSignatureTooDeep)) => { // pre-2.4, deserializer could error on legal types deeper than a deserialization limit of 16. // with sanitization enabled (a 2.4-gated feature), these serializations are readable. ClarityValue::deserialize_read( diff --git a/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs b/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs index 39def41c642..52c983daecb 100644 --- a/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs +++ b/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs @@ -19,7 +19,7 @@ #![no_main] use arbitrary::Arbitrary; -use clarity::vm::analysis::CheckErrors; +use clarity::vm::analysis::CheckErrorKind; use clarity::vm::representations::ContractName; use clarity::vm::types::signatures::SequenceSubtype; use clarity::vm::types::{ @@ -131,9 +131,9 @@ impl arbitrary::Arbitrary<'_> for FuzzClarityValue { } } -pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result { +pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result { match me { - TypeSignature::NoType => Err(CheckErrors::CouldNotDetermineType), + TypeSignature::NoType => Err(CheckErrorKind::CouldNotDetermineType), TypeSignature::IntType => match x { ClarityValue::Int(_) => Ok(true), _ => Ok(false), @@ -251,7 +251,7 @@ pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result Err(CheckErrors::TraitReferenceNotAllowed), + | TypeSignature::TraitReferenceType(_) => Err(CheckErrorKind::TraitReferenceNotAllowed), } } diff --git a/clarity/src/vm/analysis/analysis_db.rs b/clarity/src/vm/analysis/analysis_db.rs index 390d3e9dbe0..62c28813ca0 100644 --- a/clarity/src/vm/analysis/analysis_db.rs +++ b/clarity/src/vm/analysis/analysis_db.rs @@ -20,7 +20,7 @@ use clarity_types::representations::ClarityName; use clarity_types::types::{QualifiedContractIdentifier, TraitIdentifier}; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::{CheckError, CheckErrors}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError}; use crate::vm::analysis::type_checker::ContractAnalysis; use crate::vm::database::{ ClarityBackingStore, ClarityDeserializable, ClaritySerializable, RollbackWrapper, @@ -46,16 +46,16 @@ impl<'a> AnalysisDatabase<'a> { pub fn execute(&mut self, f: F) -> Result where F: FnOnce(&mut Self) -> Result, - E: From, + E: From, { self.begin(); let result = f(self).or_else(|e| { self.roll_back() - .map_err(|e| CheckErrors::Expects(format!("{e:?}")))?; + .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")))?; Err(e) })?; self.commit() - .map_err(|e| CheckErrors::Expects(format!("{e:?}")))?; + .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")))?; Ok(result) } @@ -63,16 +63,16 @@ impl<'a> AnalysisDatabase<'a> { self.store.nest(); } - pub fn commit(&mut self) -> Result<(), CheckError> { + pub fn commit(&mut self) -> Result<(), StaticCheckError> { self.store .commit() - .map_err(|e| CheckErrors::Expects(format!("{e:?}")).into()) + .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()) } - pub fn roll_back(&mut self) -> Result<(), CheckError> { + pub fn roll_back(&mut self) -> Result<(), StaticCheckError> { self.store .rollback() - .map_err(|e| CheckErrors::Expects(format!("{e:?}")).into()) + .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()) } pub fn storage_key() -> &'static str { @@ -99,16 +99,16 @@ impl<'a> AnalysisDatabase<'a> { pub fn load_contract_non_canonical( &mut self, contract_identifier: &QualifiedContractIdentifier, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { self.store .get_metadata(contract_identifier, AnalysisDatabase::storage_key()) // treat NoSuchContract error thrown by get_metadata as an Option::None -- - // the analysis will propagate that as a CheckError anyways. + // the analysis will propagate that as a StaticCheckError anyways. .ok() .flatten() .map(|x| { ContractAnalysis::deserialize(&x).map_err(|_| { - CheckErrors::Expects("Bad data deserialized from DB".into()).into() + CheckErrorKind::Expects("Bad data deserialized from DB".into()).into() }) }) .transpose() @@ -118,17 +118,17 @@ impl<'a> AnalysisDatabase<'a> { &mut self, contract_identifier: &QualifiedContractIdentifier, epoch: &StacksEpochId, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { Ok(self .store .get_metadata(contract_identifier, AnalysisDatabase::storage_key()) // treat NoSuchContract error thrown by get_metadata as an Option::None -- - // the analysis will propagate that as a CheckError anyways. + // the analysis will propagate that as a StaticCheckError anyways. .ok() .flatten() .map(|x| { ContractAnalysis::deserialize(&x) - .map_err(|_| CheckErrors::Expects("Bad data deserialized from DB".into())) + .map_err(|_| CheckErrorKind::Expects("Bad data deserialized from DB".into())) }) .transpose()? .map(|mut x| { @@ -141,29 +141,33 @@ impl<'a> AnalysisDatabase<'a> { &mut self, contract_identifier: &QualifiedContractIdentifier, contract: &ContractAnalysis, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { let key = AnalysisDatabase::storage_key(); if self.store.has_metadata_entry(contract_identifier, key) { - return Err(CheckErrors::ContractAlreadyExists(contract_identifier.to_string()).into()); + return Err( + CheckErrorKind::ContractAlreadyExists(contract_identifier.to_string()).into(), + ); } self.store .insert_metadata(contract_identifier, key, &contract.serialize()) - .map_err(|e| CheckErrors::Expects(format!("{e:?}")))?; + .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")))?; Ok(()) } pub fn get_clarity_version( &mut self, contract_identifier: &QualifiedContractIdentifier, - ) -> Result { + ) -> Result { // TODO: this function loads the whole contract to obtain the function type. // but it doesn't need to -- rather this information can just be // stored as its own entry. the analysis cost tracking currently only // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrors::NoSuchContract(contract_identifier.to_string()))?; + .ok_or(CheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ))?; Ok(contract.clarity_version) } @@ -172,14 +176,16 @@ impl<'a> AnalysisDatabase<'a> { contract_identifier: &QualifiedContractIdentifier, function_name: &str, epoch: &StacksEpochId, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { // TODO: this function loads the whole contract to obtain the function type. // but it doesn't need to -- rather this information can just be // stored as its own entry. the analysis cost tracking currently only // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrors::NoSuchContract(contract_identifier.to_string()))?; + .ok_or(CheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ))?; Ok(contract .get_public_function_type(function_name) .map(|x| x.canonicalize(epoch))) @@ -190,14 +196,16 @@ impl<'a> AnalysisDatabase<'a> { contract_identifier: &QualifiedContractIdentifier, function_name: &str, epoch: &StacksEpochId, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { // TODO: this function loads the whole contract to obtain the function type. // but it doesn't need to -- rather this information can just be // stored as its own entry. the analysis cost tracking currently only // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrors::NoSuchContract(contract_identifier.to_string()))?; + .ok_or(CheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ))?; Ok(contract .get_read_only_function_type(function_name) .map(|x| x.canonicalize(epoch))) @@ -208,14 +216,16 @@ impl<'a> AnalysisDatabase<'a> { contract_identifier: &QualifiedContractIdentifier, trait_name: &str, epoch: &StacksEpochId, - ) -> Result>, CheckError> { + ) -> Result>, StaticCheckError> { // TODO: this function loads the whole contract to obtain the function type. // but it doesn't need to -- rather this information can just be // stored as its own entry. the analysis cost tracking currently only // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrors::NoSuchContract(contract_identifier.to_string()))?; + .ok_or(CheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ))?; Ok(contract.get_defined_trait(trait_name).map(|trait_map| { trait_map .iter() @@ -227,10 +237,12 @@ impl<'a> AnalysisDatabase<'a> { pub fn get_implemented_traits( &mut self, contract_identifier: &QualifiedContractIdentifier, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrors::NoSuchContract(contract_identifier.to_string()))?; + .ok_or(CheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ))?; Ok(contract.implemented_traits) } diff --git a/clarity/src/vm/analysis/arithmetic_checker/mod.rs b/clarity/src/vm/analysis/arithmetic_checker/mod.rs index 83be68ab230..c8aaaff2c03 100644 --- a/clarity/src/vm/analysis/arithmetic_checker/mod.rs +++ b/clarity/src/vm/analysis/arithmetic_checker/mod.rs @@ -16,7 +16,9 @@ use clarity_types::representations::ClarityName; -pub use super::errors::{check_argument_count, check_arguments_at_least, CheckError, CheckErrors}; +pub use super::errors::{ + check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, +}; use crate::vm::analysis::types::ContractAnalysis; use crate::vm::functions::define::{DefineFunctions, DefineFunctionsParsed}; use crate::vm::functions::NativeFunctions; diff --git a/clarity/src/vm/analysis/contract_interface_builder/mod.rs b/clarity/src/vm/analysis/contract_interface_builder/mod.rs index 26c71f695b9..5fc0169c5cb 100644 --- a/clarity/src/vm/analysis/contract_interface_builder/mod.rs +++ b/clarity/src/vm/analysis/contract_interface_builder/mod.rs @@ -19,16 +19,16 @@ use std::collections::{BTreeMap, BTreeSet}; use stacks_common::types::StacksEpochId; use crate::vm::analysis::types::ContractAnalysis; -use crate::vm::analysis::CheckError; +use crate::vm::analysis::StaticCheckError; use crate::vm::types::signatures::CallableSubtype; use crate::vm::types::{ FixedFunction, FunctionArg, FunctionType, TupleTypeSignature, TypeSignature, }; -use crate::vm::{CheckErrors, ClarityName, ClarityVersion}; +use crate::vm::{CheckErrorKind, ClarityName, ClarityVersion}; pub fn build_contract_interface( contract_analysis: &ContractAnalysis, -) -> Result { +) -> Result { let mut contract_interface = ContractInterface::new(contract_analysis.epoch, contract_analysis.clarity_version); @@ -267,7 +267,7 @@ impl ContractInterfaceFunction { fn from_map( map: &BTreeMap, access: ContractInterfaceFunctionAccess, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { map.iter() .map(|(name, function_type)| { Ok(ContractInterfaceFunction { @@ -278,7 +278,7 @@ impl ContractInterfaceFunction { FunctionType::Fixed(FixedFunction { returns, .. }) => { ContractInterfaceAtomType::from_type_signature(returns) } - _ => return Err(CheckErrors::Expects( + _ => return Err(CheckErrorKind::Expects( "Contract functions should only have fixed function return types!" .into(), ) @@ -290,7 +290,7 @@ impl ContractInterfaceFunction { ContractInterfaceFunctionArg::from_function_args(args) } _ => { - return Err(CheckErrors::Expects( + return Err(CheckErrorKind::Expects( "Contract functions should only have fixed function arguments!" .into(), ) @@ -400,9 +400,9 @@ impl ContractInterface { } } - pub fn serialize(&self) -> Result { + pub fn serialize(&self) -> Result { serde_json::to_string(self).map_err(|_| { - CheckErrors::Expects("Failed to serialize contract interface".into()).into() + CheckErrorKind::Expects("Failed to serialize contract interface".into()).into() }) } } diff --git a/clarity/src/vm/analysis/errors.rs b/clarity/src/vm/analysis/errors.rs index f7ce7072f38..7bf7faabc13 100644 --- a/clarity/src/vm/analysis/errors.rs +++ b/clarity/src/vm/analysis/errors.rs @@ -15,6 +15,6 @@ // along with this program. If not, see . pub use clarity_types::errors::analysis::{ - check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckError, - CheckErrors, SyntaxBindingError, SyntaxBindingErrorType, + check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, + StaticCheckError, SyntaxBindingError, SyntaxBindingErrorType, }; diff --git a/clarity/src/vm/analysis/mod.rs b/clarity/src/vm/analysis/mod.rs index 0fc0faec658..f25c0d4e732 100644 --- a/clarity/src/vm/analysis/mod.rs +++ b/clarity/src/vm/analysis/mod.rs @@ -28,7 +28,7 @@ use stacks_common::types::StacksEpochId; pub use self::analysis_db::AnalysisDatabase; use self::arithmetic_checker::ArithmeticOnlyChecker; use self::contract_interface_builder::build_contract_interface; -pub use self::errors::{CheckError, CheckErrors}; +pub use self::errors::{CheckErrorKind, StaticCheckError}; use self::read_only_checker::ReadOnlyChecker; use self::trait_checker::TraitChecker; use self::type_checker::v2_05::TypeChecker as TypeChecker2_05; @@ -52,10 +52,10 @@ pub fn mem_type_check( snippet: &str, version: ClarityVersion, epoch: StacksEpochId, -) -> Result<(Option, ContractAnalysis), CheckError> { +) -> Result<(Option, ContractAnalysis), StaticCheckError> { let contract_identifier = QualifiedContractIdentifier::transient(); let contract = build_ast(&contract_identifier, snippet, &mut (), version, epoch) - .map_err(|_| CheckErrors::Expects("Failed to build AST".into()))? + .map_err(|_| CheckErrorKind::Expects("Failed to build AST".into()))? .expressions; let mut marf = MemoryBackingStore::new(); @@ -76,11 +76,11 @@ pub fn mem_type_check( let first_type = x .type_map .as_ref() - .ok_or_else(|| CheckErrors::Expects("Should be non-empty".into()))? + .ok_or_else(|| CheckErrorKind::Expects("Should be non-empty".into()))? .get_type_expected( x.expressions .last() - .ok_or_else(|| CheckErrors::Expects("Should be non-empty".into()))?, + .ok_or_else(|| CheckErrorKind::Expects("Should be non-empty".into()))?, ) .cloned(); Ok((first_type, x)) @@ -99,7 +99,7 @@ pub fn type_check( insert_contract: bool, epoch: &StacksEpochId, version: &ClarityVersion, -) -> Result { +) -> Result { run_analysis( contract_identifier, expressions, @@ -125,7 +125,7 @@ pub fn run_analysis( epoch: StacksEpochId, version: ClarityVersion, build_type_map: bool, -) -> Result> { +) -> Result> { let mut contract_analysis = ContractAnalysis::new( contract_identifier.clone(), expressions.to_vec(), @@ -151,7 +151,7 @@ pub fn run_analysis( TypeChecker2_1::run_pass(&epoch, &mut contract_analysis, db, build_type_map) } StacksEpochId::Epoch10 => { - return Err(CheckErrors::Expects( + return Err(CheckErrorKind::Expects( "Epoch 1.0 is not a valid epoch for analysis".into(), ) .into()) diff --git a/clarity/src/vm/analysis/read_only_checker/mod.rs b/clarity/src/vm/analysis/read_only_checker/mod.rs index 21b2bbd8f7b..9faea79fa0e 100644 --- a/clarity/src/vm/analysis/read_only_checker/mod.rs +++ b/clarity/src/vm/analysis/read_only_checker/mod.rs @@ -21,7 +21,8 @@ use clarity_types::types::{PrincipalData, Value}; use stacks_common::types::StacksEpochId; pub use super::errors::{ - check_argument_count, check_arguments_at_least, CheckError, CheckErrors, SyntaxBindingError, + check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, + SyntaxBindingError, }; use super::AnalysisDatabase; use crate::vm::analysis::types::{AnalysisPass, ContractAnalysis}; @@ -54,7 +55,7 @@ impl AnalysisPass for ReadOnlyChecker<'_, '_> { epoch: &StacksEpochId, contract_analysis: &mut ContractAnalysis, analysis_db: &mut AnalysisDatabase, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { let mut command = ReadOnlyChecker::new(analysis_db, epoch, &contract_analysis.clarity_version); command.run(contract_analysis)?; @@ -81,9 +82,9 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { /// Returns successfully iff this function is read-only correct. /// /// # Errors - /// - `CheckErrors::WriteAttemptedInReadOnly` + /// - `CheckErrorKind::WriteAttemptedInReadOnly` /// - Contract parsing errors - pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), CheckError> { + pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), StaticCheckError> { // Iterate over all the top-level statements in a contract. for exp in contract_analysis.expressions.iter() { let mut result = self.check_top_level_expression(exp); @@ -105,12 +106,12 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { /// Returns successfully iff this function is read-only correct. /// /// # Errors - /// - CheckErrors::WriteAttemptedInReadOnly + /// - CheckErrorKind::WriteAttemptedInReadOnly /// - Contract parsing errors fn check_top_level_expression( &mut self, expression: &SymbolicExpression, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { use crate::vm::functions::define::DefineFunctionsParsed::*; if let Some(define_type) = DefineFunctionsParsed::try_parse(expression)? { match define_type { @@ -135,7 +136,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { let (function_name, is_read_only) = self.check_define_function(signature, body)?; if !is_read_only { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } else { self.defined_functions.insert(function_name, is_read_only); } @@ -168,19 +169,22 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { &mut self, signature: &[SymbolicExpression], body: &SymbolicExpression, - ) -> Result<(ClarityName, bool), CheckError> { + ) -> Result<(ClarityName, bool), StaticCheckError> { let function_name = signature .first() - .ok_or(CheckErrors::DefineFunctionBadSignature)? + .ok_or(CheckErrorKind::DefineFunctionBadSignature)? .match_atom() - .ok_or(CheckErrors::BadFunctionName)?; + .ok_or(CheckErrorKind::BadFunctionName)?; let is_read_only = self.check_read_only(body)?; Ok((function_name.clone(), is_read_only)) } - fn check_reads_only_valid(&mut self, expr: &SymbolicExpression) -> Result<(), CheckError> { + fn check_reads_only_valid( + &mut self, + expr: &SymbolicExpression, + ) -> Result<(), StaticCheckError> { use crate::vm::functions::define::DefineFunctionsParsed::*; if let Some(define_type) = DefineFunctionsParsed::try_parse(expr)? { match define_type { @@ -203,7 +207,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { ReadOnlyFunction { signature, body } => { let (f_name, is_read_only) = self.check_define_function(signature, body)?; if !is_read_only { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } else { self.defined_functions.insert(f_name, is_read_only); } @@ -225,7 +229,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { /// (1) for whether or not they are valid with respect to read-only requirements. /// (2) if valid, returns whether or not they are read only. /// Note that because of (1), this function _cannot_ short-circuit on read-only. - fn check_read_only(&mut self, expr: &SymbolicExpression) -> Result { + fn check_read_only(&mut self, expr: &SymbolicExpression) -> Result { match expr.expr { AtomValue(_) | LiteralValue(_) | Atom(_) | TraitReference(_, _) | Field(_) => Ok(true), List(ref expression) => self.check_expression_application_is_read_only(expression), @@ -242,7 +246,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { fn check_each_expression_is_read_only( &mut self, expressions: &[SymbolicExpression], - ) -> Result { + ) -> Result { let mut result = true; for expression in expressions.iter() { let expr_read_only = self.check_read_only(expression)?; @@ -265,7 +269,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { &mut self, function: &str, args: &[SymbolicExpression], - ) -> Option> { + ) -> Option> { NativeFunctions::lookup_by_name_at_version(function, &self.clarity_version) .map(|function| self.check_native_function_is_read_only(&function, args)) } @@ -278,7 +282,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { &mut self, function: &NativeFunctions, args: &[SymbolicExpression], - ) -> Result { + ) -> Result { use crate::vm::functions::NativeFunctions::*; match function { @@ -310,7 +314,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { let is_block_arg_read_only = self.check_read_only(&args[0])?; let closure_read_only = self.check_read_only(&args[1])?; if !closure_read_only { - return Err(CheckErrors::AtBlockClosureMustBeReadOnly.into()); + return Err(CheckErrorKind::AtBlockClosureMustBeReadOnly.into()); } Ok(is_block_arg_read_only) } @@ -327,17 +331,17 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { Let => { check_arguments_at_least(2, args)?; - let binding_list = args[0].match_list().ok_or(CheckErrors::BadLetSyntax)?; + let binding_list = args[0].match_list().ok_or(CheckErrorKind::BadLetSyntax)?; for (i, pair) in binding_list.iter().enumerate() { let pair_expression = pair.match_list().ok_or_else(|| { - CheckError::with_expression( + StaticCheckError::with_expression( SyntaxBindingError::let_binding_not_list(i).into(), pair, ) })?; if pair_expression.len() != 2 { - return Err(CheckError::with_expression( + return Err(StaticCheckError::with_expression( SyntaxBindingError::let_binding_invalid_length(i).into(), pair, )); @@ -379,13 +383,13 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { TupleCons => { for (i, pair) in args.iter().enumerate() { let pair_expression = pair.match_list().ok_or_else(|| { - CheckError::with_expression( + StaticCheckError::with_expression( SyntaxBindingError::tuple_cons_not_list(i).into(), pair, ) })?; if pair_expression.len() != 2 { - return Err(CheckError::with_expression( + return Err(StaticCheckError::with_expression( SyntaxBindingError::tuple_cons_invalid_length(i).into(), pair, )); @@ -402,7 +406,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { let function_name = args[1] .match_atom() - .ok_or(CheckErrors::ContractCallExpectName)?; + .ok_or(CheckErrorKind::ContractCallExpectName)?; let is_function_read_only = match &args[0].expr { SymbolicExpressionType::LiteralValue(Value::Principal( @@ -421,7 +425,11 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { // As such dynamic dispatch is currently forbidden. false } - _ => return Err(CheckError::new(CheckErrors::ContractCallExpectName)), + _ => { + return Err(StaticCheckError::new( + CheckErrorKind::ContractCallExpectName, + )) + } }; self.check_each_expression_is_read_only(&args[2..]) @@ -437,20 +445,20 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { /// Returns `true` iff the function application is read-only. /// /// # Errors - /// - `CheckErrors::NonFunctionApplication` if there is no first expression, or if the first + /// - `CheckErrorKind::NonFunctionApplication` if there is no first expression, or if the first /// expression is not a `ClarityName`. - /// - `CheckErrors::UnknownFunction` if the first expression does not name a known function. + /// - `CheckErrorKind::UnknownFunction` if the first expression does not name a known function. fn check_expression_application_is_read_only( &mut self, expressions: &[SymbolicExpression], - ) -> Result { + ) -> Result { let (function_name, args) = expressions .split_first() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; let function_name = function_name .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; if let Some(mut result) = self.try_check_native_function_is_read_only(function_name, args) { if let Err(ref mut check_err) = result { @@ -461,7 +469,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { let is_function_read_only = *self .defined_functions .get(function_name) - .ok_or(CheckErrors::UnknownFunction(function_name.to_string()))?; + .ok_or(CheckErrorKind::UnknownFunction(function_name.to_string()))?; self.check_each_expression_is_read_only(args) .map(|args_read_only| args_read_only && is_function_read_only) } diff --git a/clarity/src/vm/analysis/read_only_checker/tests.rs b/clarity/src/vm/analysis/read_only_checker/tests.rs index 585bea62cdc..5b985b7b2f2 100644 --- a/clarity/src/vm/analysis/read_only_checker/tests.rs +++ b/clarity/src/vm/analysis/read_only_checker/tests.rs @@ -21,7 +21,7 @@ use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; use crate::vm::analysis::type_checker::v2_1::tests::mem_type_check; -use crate::vm::analysis::{type_check, CheckErrors}; +use crate::vm::analysis::{type_check, CheckErrorKind}; use crate::vm::ast::parse; use crate::vm::database::MemoryBackingStore; use crate::vm::tests::test_clarity_versions; @@ -34,11 +34,11 @@ fn test_argument_count_violations() { ( "(define-private (foo-bar) (at-block))", - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), ), ( "(define-private (foo-bar) (map-get?))", - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), ), ]; @@ -72,7 +72,7 @@ fn test_at_block_violations() { for contract in examples.iter() { let err = mem_type_check(contract).unwrap_err(); eprintln!("{err}"); - assert_eq!(*err.err, CheckErrors::AtBlockClosureMustBeReadOnly) + assert_eq!(*err.err, CheckErrorKind::AtBlockClosureMustBeReadOnly) } } @@ -163,7 +163,7 @@ fn test_simple_read_only_violations() { for contract in bad_contracts.iter() { let err = mem_type_check(contract).unwrap_err(); - assert_eq!(*err.err, CheckErrors::WriteAttemptedInReadOnly) + assert_eq!(*err.err, CheckErrorKind::WriteAttemptedInReadOnly) } } @@ -180,7 +180,7 @@ fn test_nested_writing_closure() { for contract in bad_contracts.iter() { let err = mem_type_check(contract).unwrap_err(); - assert_eq!(*err.err, CheckErrors::AtBlockClosureMustBeReadOnly) + assert_eq!(*err.err, CheckErrorKind::AtBlockClosureMustBeReadOnly) } } @@ -231,7 +231,7 @@ fn test_contract_call_read_only_violations( ) }) .unwrap_err(); - assert_eq!(*err.err, CheckErrors::WriteAttemptedInReadOnly); + assert_eq!(*err.err, CheckErrorKind::WriteAttemptedInReadOnly); db.execute(|db| { type_check( diff --git a/clarity/src/vm/analysis/trait_checker/mod.rs b/clarity/src/vm/analysis/trait_checker/mod.rs index 491fe81c24c..a2563de2d47 100644 --- a/clarity/src/vm/analysis/trait_checker/mod.rs +++ b/clarity/src/vm/analysis/trait_checker/mod.rs @@ -15,7 +15,7 @@ // along with this program. If not, see . use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::{CheckError, CheckErrors}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError}; use crate::vm::analysis::types::{AnalysisPass, ContractAnalysis}; use crate::vm::analysis::AnalysisDatabase; @@ -28,7 +28,7 @@ impl AnalysisPass for TraitChecker { epoch: &StacksEpochId, contract_analysis: &mut ContractAnalysis, analysis_db: &mut AnalysisDatabase, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { let mut command = TraitChecker::new(epoch); command.run(contract_analysis, analysis_db)?; Ok(()) @@ -44,18 +44,18 @@ impl TraitChecker { &mut self, contract_analysis: &ContractAnalysis, analysis_db: &mut AnalysisDatabase, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { for trait_identifier in &contract_analysis.implemented_traits { let trait_name = trait_identifier.name.to_string(); let contract_defining_trait = analysis_db .load_contract(&trait_identifier.contract_identifier, &self.epoch)? - .ok_or(CheckErrors::TraitReferenceUnknown( + .ok_or(CheckErrorKind::TraitReferenceUnknown( trait_identifier.name.to_string(), ))?; let trait_definition = contract_defining_trait .get_defined_trait(&trait_name) - .ok_or(CheckErrors::TraitReferenceUnknown( + .ok_or(CheckErrorKind::TraitReferenceUnknown( trait_identifier.name.to_string(), ))?; diff --git a/clarity/src/vm/analysis/trait_checker/tests.rs b/clarity/src/vm/analysis/trait_checker/tests.rs index 305781f9593..c103f7a6eaa 100644 --- a/clarity/src/vm/analysis/trait_checker/tests.rs +++ b/clarity/src/vm/analysis/trait_checker/tests.rs @@ -20,9 +20,9 @@ use rstest::rstest; use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::CheckErrors; -use crate::vm::analysis::{type_check, CheckError}; -use crate::vm::ast::errors::ParseErrors; +use crate::vm::analysis::errors::CheckErrorKind; +use crate::vm::analysis::{type_check, StaticCheckError}; +use crate::vm::ast::errors::ParseErrorKind; use crate::vm::ast::{build_ast, parse}; use crate::vm::database::MemoryBackingStore; use crate::vm::tests::test_clarity_versions; @@ -98,7 +98,7 @@ fn test_incomplete_impl_trait_1(#[case] version: ClarityVersion, #[case] epoch: }) .unwrap_err(); match *err.err { - CheckErrors::BadTraitImplementation(_, _) => {} + CheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -125,7 +125,7 @@ fn test_incomplete_impl_trait_2(#[case] version: ClarityVersion, #[case] epoch: }) .unwrap_err(); match *err.err { - CheckErrors::BadTraitImplementation(_, _) => {} + CheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -149,7 +149,7 @@ fn test_impl_trait_arg_admission_1(#[case] version: ClarityVersion, #[case] epoc }) .unwrap_err(); match *err.err { - CheckErrors::BadTraitImplementation(_, _) => {} + CheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -289,7 +289,7 @@ fn test_get_trait_reference_from_tuple( }) .unwrap_err(); match *err.err { - CheckErrors::ContractCallExpectName => {} + CheckErrorKind::ContractCallExpectName => {} _ => panic!("{err:?}"), } } @@ -332,7 +332,7 @@ fn test_dynamic_dispatch_by_defining_and_impl_trait( }) .unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err:?}"), } } @@ -359,7 +359,7 @@ fn test_define_map_storing_trait_references( .unwrap_err(); match *err.err { - ParseErrors::TraitReferenceNotAllowed => {} + ParseErrorKind::TraitReferenceNotAllowed => {} _ => panic!("{err:?}"), } } @@ -383,7 +383,7 @@ fn test_cycle_in_traits_1_contract(#[case] version: ClarityVersion, #[case] epoc ) .unwrap_err(); match *err.err { - ParseErrors::CircularReference(_) => {} + ParseErrorKind::CircularReference(_) => {} _ => panic!("{err:?}"), } } @@ -434,7 +434,7 @@ fn test_cycle_in_traits_2_contracts(#[case] version: ClarityVersion, #[case] epo }) .unwrap_err(); match *err.err { - CheckErrors::NoSuchContract(_) => {} + CheckErrorKind::NoSuchContract(_) => {} _ => panic!("{err:?}"), } } @@ -487,7 +487,7 @@ fn test_dynamic_dispatch_unknown_method( }) .unwrap_err(); match *err.err { - CheckErrors::TraitMethodUnknown(_, _) => {} + CheckErrorKind::TraitMethodUnknown(_, _) => {} _ => panic!("{err:?}"), } } @@ -671,7 +671,7 @@ fn test_dynamic_dispatch_collision_trait( ) .unwrap_err(); match *err.err { - ParseErrors::NameAlreadyUsed(_) => {} + ParseErrorKind::NameAlreadyUsed(_) => {} _ => panic!("{err:?}"), } } @@ -700,7 +700,7 @@ fn test_dynamic_dispatch_collision_defined_trait( ) .unwrap_err(); match *err.err { - ParseErrors::NameAlreadyUsed(_) => {} + ParseErrorKind::NameAlreadyUsed(_) => {} _ => panic!("{err:?}"), } } @@ -740,7 +740,7 @@ fn test_dynamic_dispatch_collision_imported_trait( ) .unwrap_err(); match *err.err { - ParseErrors::NameAlreadyUsed(_) => {} + ParseErrorKind::NameAlreadyUsed(_) => {} _ => panic!("{err:?}"), } } @@ -812,7 +812,7 @@ fn test_dynamic_dispatch_importing_non_existant_trait( }) .unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err:?}"), } } @@ -1099,13 +1099,13 @@ fn test_dynamic_dispatch_including_wrong_nested_trait( .unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, actual) if epoch < StacksEpochId::Epoch21 => { + CheckErrorKind::TypeError(expected, actual) if epoch < StacksEpochId::Epoch21 => { match (&*expected, &*actual) { (TypeSignature::TraitReferenceType(_), TypeSignature::TraitReferenceType(_)) => {} _ => panic!("unexpected TypeSignature: {expected:?} {actual:?}"), } } - CheckErrors::TypeError(expected, actual) + CheckErrorKind::TypeError(expected, actual) if epoch >= StacksEpochId::Epoch21 && version < ClarityVersion::Clarity2 => { match (&*expected, &*actual) { @@ -1113,7 +1113,7 @@ fn test_dynamic_dispatch_including_wrong_nested_trait( _ => panic!("unexpected TypeSignature: {expected:?} {actual:?}"), } } - CheckErrors::TraitReferenceUnknown(name) => assert_eq!(name.as_str(), "trait-a"), + CheckErrorKind::TraitReferenceUnknown(name) => assert_eq!(name.as_str(), "trait-a"), _ => panic!("{err:?}"), } } @@ -1167,7 +1167,7 @@ fn test_dynamic_dispatch_mismatched_args( }) .unwrap_err(); match *err.err { - CheckErrors::TypeError(_, _) => {} + CheckErrorKind::TypeError(_, _) => {} _ => panic!("{err:?}"), } } @@ -1221,7 +1221,7 @@ fn test_dynamic_dispatch_mismatched_returns( }) .unwrap_err(); match *err.err { - CheckErrors::BadTraitImplementation(_, _) => {} + CheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -1257,7 +1257,7 @@ fn test_bad_call_with_trait(#[case] version: ClarityVersion, #[case] epoch: Stac }) .unwrap_err(); match *err.err { - CheckErrors::TypeError(_, _) => {} + CheckErrorKind::TypeError(_, _) => {} _ => panic!("{err:?}"), } } @@ -1466,7 +1466,7 @@ fn test_dynamic_dispatch_pass_bound_principal_as_trait_in_user_defined_functions match result { Err(err) if version == ClarityVersion::Clarity1 => { match *err.err { - CheckErrors::TypeError(_, _) => {} + CheckErrorKind::TypeError(_, _) => {} _ => panic!("{err:?}"), }; } @@ -1560,7 +1560,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_principal.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_principal:?}"), } let err_int = db @@ -1570,7 +1570,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_int.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_int:?}"), } let err_uint = db @@ -1580,7 +1580,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_uint.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_uint:?}"), } let err_bool = db @@ -1590,7 +1590,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_bool.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_bool:?}"), } let err_list = db @@ -1600,7 +1600,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_list.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_list:?}"), } let err_buff = db @@ -1610,7 +1610,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_buff.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_buff:?}"), } let err_tuple = db @@ -1620,7 +1620,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_tuple.err { - CheckErrors::TraitReferenceUnknown(_) => {} + CheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_tuple:?}"), } } @@ -1818,8 +1818,8 @@ fn test_trait_contract_not_found(#[case] version: ClarityVersion, #[case] epoch: &version, ) }) { - Err(CheckError { err, .. }) if version < ClarityVersion::Clarity2 => match *err { - CheckErrors::NoSuchContract(contract) => { + Err(StaticCheckError { err, .. }) if version < ClarityVersion::Clarity2 => match *err { + CheckErrorKind::NoSuchContract(contract) => { assert!(contract.ends_with(".trait-contract")) } _ => panic!("{version}: unexpected NoSuchContract error"), diff --git a/clarity/src/vm/analysis/type_checker/contexts.rs b/clarity/src/vm/analysis/type_checker/contexts.rs index ddc34d8b8b5..50f8cd16104 100644 --- a/clarity/src/vm/analysis/type_checker/contexts.rs +++ b/clarity/src/vm/analysis/type_checker/contexts.rs @@ -18,7 +18,7 @@ use std::collections::{HashMap, HashSet}; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::{CheckError, CheckErrors}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError}; use crate::vm::types::signatures::CallableSubtype; use crate::vm::types::{TraitIdentifier, TypeSignature}; use crate::vm::{ClarityName, ClarityVersion, SymbolicExpression, MAX_CONTEXT_DEPTH}; @@ -64,18 +64,22 @@ impl TypeMap { &mut self, expr: &SymbolicExpression, type_sig: TypeSignature, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { match self.map { TypeMapDataType::Map(ref mut map) => { if map.insert(expr.id, type_sig).is_some() { - Err(CheckError::new(CheckErrors::TypeAlreadyAnnotatedFailure)) + Err(StaticCheckError::new( + CheckErrorKind::TypeAlreadyAnnotatedFailure, + )) } else { Ok(()) } } TypeMapDataType::Set(ref mut map) => { if !map.insert(expr.id) { - Err(CheckError::new(CheckErrors::TypeAlreadyAnnotatedFailure)) + Err(StaticCheckError::new( + CheckErrorKind::TypeAlreadyAnnotatedFailure, + )) } else { Ok(()) } @@ -103,9 +107,11 @@ impl TypingContext<'_> { } } - pub fn extend(&self) -> Result, CheckError> { + pub fn extend(&self) -> Result, StaticCheckError> { if self.depth >= MAX_CONTEXT_DEPTH { - Err(CheckError::new(CheckErrors::MaxContextDepthReached)) + Err(StaticCheckError::new( + CheckErrorKind::MaxContextDepthReached, + )) } else { Ok(TypingContext { epoch: self.epoch, diff --git a/clarity/src/vm/analysis/type_checker/mod.rs b/clarity/src/vm/analysis/type_checker/mod.rs index d33c7c87e67..7305d63d08e 100644 --- a/clarity/src/vm/analysis/type_checker/mod.rs +++ b/clarity/src/vm/analysis/type_checker/mod.rs @@ -20,7 +20,7 @@ pub mod v2_1; use stacks_common::types::StacksEpochId; -use super::errors::{CheckError, CheckErrors}; +use super::errors::{CheckErrorKind, StaticCheckError}; pub use super::types::{AnalysisPass, ContractAnalysis}; use super::AnalysisDatabase; use crate::vm::costs::CostTracker; @@ -34,7 +34,7 @@ impl FunctionType { args: &[TypeSignature], epoch: StacksEpochId, clarity_version: ClarityVersion, - ) -> Result { + ) -> Result { match epoch { StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => { self.check_args_2_05(accounting, args) @@ -49,7 +49,7 @@ impl FunctionType { | StacksEpochId::Epoch32 | StacksEpochId::Epoch33 => self.check_args_2_1(accounting, args, clarity_version), StacksEpochId::Epoch10 => { - Err(CheckErrors::Expects("Epoch10 is not supported".into()).into()) + Err(CheckErrorKind::Expects("Epoch10 is not supported".into()).into()) } } } @@ -60,7 +60,7 @@ impl FunctionType { func_args: &[Value], epoch: StacksEpochId, clarity_version: ClarityVersion, - ) -> Result { + ) -> Result { match epoch { StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => { self.check_args_by_allowing_trait_cast_2_05(db, func_args) @@ -77,7 +77,7 @@ impl FunctionType { self.check_args_by_allowing_trait_cast_2_1(db, clarity_version, func_args) } StacksEpochId::Epoch10 => { - Err(CheckErrors::Expects("Epoch10 is not supported".into()).into()) + Err(CheckErrorKind::Expects("Epoch10 is not supported".into()).into()) } } } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/contexts.rs b/clarity/src/vm/analysis/type_checker/v2_05/contexts.rs index 4af94d41a79..684c7ff872b 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/contexts.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/contexts.rs @@ -16,7 +16,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; -use crate::vm::analysis::errors::{CheckError, CheckErrors}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError}; use crate::vm::analysis::types::ContractAnalysis; use crate::vm::representations::ClarityName; use crate::vm::types::signatures::FunctionSignature; @@ -57,7 +57,7 @@ impl ContractContext { } } - pub fn check_name_used(&self, name: &str) -> Result<(), CheckError> { + pub fn check_name_used(&self, name: &str) -> Result<(), StaticCheckError> { if self.variable_types.contains_key(name) || self.persisted_variable_types.contains_key(name) || self.private_function_types.contains_key(name) @@ -67,7 +67,7 @@ impl ContractContext { || self.traits.contains_key(name) || self.map_types.contains_key(name) { - Err(CheckError::new(CheckErrors::NameAlreadyUsed( + Err(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( name.to_string(), ))) } else { @@ -75,7 +75,7 @@ impl ContractContext { } } - fn check_function_type(&mut self, f_name: &str) -> Result<(), CheckError> { + fn check_function_type(&mut self, f_name: &str) -> Result<(), StaticCheckError> { self.check_name_used(f_name)?; Ok(()) } @@ -92,7 +92,7 @@ impl ContractContext { &mut self, name: ClarityName, func_type: FunctionType, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_function_type(&name)?; self.public_function_types.insert(name, func_type); Ok(()) @@ -102,7 +102,7 @@ impl ContractContext { &mut self, name: ClarityName, func_type: FunctionType, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_function_type(&name)?; self.read_only_function_types.insert(name, func_type); Ok(()) @@ -112,7 +112,7 @@ impl ContractContext { &mut self, name: ClarityName, func_type: FunctionType, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_function_type(&name)?; self.private_function_types.insert(name, func_type); Ok(()) @@ -122,7 +122,7 @@ impl ContractContext { &mut self, map_name: ClarityName, map_type: (TypeSignature, TypeSignature), - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&map_name)?; self.map_types.insert(map_name, map_type); Ok(()) @@ -132,7 +132,7 @@ impl ContractContext { &mut self, const_name: ClarityName, var_type: TypeSignature, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&const_name)?; self.variable_types.insert(const_name, var_type); Ok(()) @@ -142,13 +142,13 @@ impl ContractContext { &mut self, var_name: ClarityName, var_type: TypeSignature, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&var_name)?; self.persisted_variable_types.insert(var_name, var_type); Ok(()) } - pub fn add_ft(&mut self, token_name: ClarityName) -> Result<(), CheckError> { + pub fn add_ft(&mut self, token_name: ClarityName) -> Result<(), StaticCheckError> { self.check_name_used(&token_name)?; self.fungible_tokens.insert(token_name); Ok(()) @@ -158,7 +158,7 @@ impl ContractContext { &mut self, token_name: ClarityName, token_type: TypeSignature, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&token_name)?; self.non_fungible_tokens.insert(token_name, token_type); Ok(()) @@ -168,7 +168,7 @@ impl ContractContext { &mut self, trait_name: ClarityName, trait_signature: BTreeMap, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.traits.insert(trait_name, trait_signature); Ok(()) } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/mod.rs index 86a10c264d6..eb83901b18d 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/mod.rs @@ -27,7 +27,8 @@ pub use self::natives::{SimpleNativeFunction, TypedNativeFunction}; use super::contexts::{TypeMap, TypingContext}; use super::ContractAnalysis; pub use crate::vm::analysis::errors::{ - check_argument_count, check_arguments_at_least, CheckError, CheckErrors, SyntaxBindingErrorType, + check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, + SyntaxBindingErrorType, }; use crate::vm::analysis::AnalysisDatabase; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -114,7 +115,7 @@ impl TypeChecker<'_, '_> { contract_analysis: &mut ContractAnalysis, analysis_db: &mut AnalysisDatabase, build_type_map: bool, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { let cost_track = contract_analysis.take_contract_cost_tracker(); let mut command = TypeChecker::new(analysis_db, cost_track, build_type_map); // run the analysis, and replace the cost tracker whether or not the @@ -139,14 +140,14 @@ impl FunctionType { &self, accounting: &mut T, args: &[TypeSignature], - ) -> Result { + ) -> Result { match self { FunctionType::Variadic(expected_type, return_type) => { check_arguments_at_least(1, args)?; for found_type in args.iter() { analysis_typecheck_cost(accounting, expected_type, found_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch2_05, found_type)? { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -164,7 +165,7 @@ impl FunctionType { { analysis_typecheck_cost(accounting, expected_type, found_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch2_05, found_type)? { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -183,7 +184,7 @@ impl FunctionType { } } Err( - CheckErrors::UnionTypeError(arg_types.clone(), Box::new(found_type.clone())) + CheckErrorKind::UnionTypeError(arg_types.clone(), Box::new(found_type.clone())) .into(), ) } @@ -198,12 +199,12 @@ impl FunctionType { } let (first, rest) = args .split_first() - .ok_or(CheckErrors::RequiresAtLeastArguments(1, args.len()))?; + .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, args.len()))?; analysis_typecheck_cost(accounting, &TypeSignature::IntType, first)?; let return_type = match first { TypeSignature::IntType => Ok(TypeSignature::IntType), TypeSignature::UIntType => Ok(TypeSignature::UIntType), - _ => Err(CheckErrors::UnionTypeError( + _ => Err(CheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(first.clone()), )), @@ -211,7 +212,7 @@ impl FunctionType { for found_type in rest.iter() { analysis_typecheck_cost(accounting, &TypeSignature::IntType, found_type)?; if found_type != &return_type { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(return_type), Box::new(found_type.clone()), ) @@ -227,7 +228,7 @@ impl FunctionType { analysis_typecheck_cost(accounting, &TypeSignature::IntType, second)?; if first != &TypeSignature::IntType && first != &TypeSignature::UIntType { - return Err(CheckErrors::UnionTypeError( + return Err(CheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(first.clone()), ) @@ -235,7 +236,7 @@ impl FunctionType { } if first != second { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(first.clone()), Box::new(second.clone()), ) @@ -244,9 +245,10 @@ impl FunctionType { Ok(TypeSignature::BoolType) } - FunctionType::Binary(_, _, _) => { - Err(CheckErrors::Expects("Binary type should not be reached in 2.05".into()).into()) - } + FunctionType::Binary(_, _, _) => Err(CheckErrorKind::Expects( + "Binary type should not be reached in 2.05".into(), + ) + .into()), } } @@ -254,10 +256,10 @@ impl FunctionType { &self, db: &mut AnalysisDatabase, func_args: &[Value], - ) -> Result { + ) -> Result { let (expected_args, returns) = match self { FunctionType::Fixed(FixedFunction { args, returns }) => (args, returns), - _ => return Err(CheckErrors::Expects("Unexpected function type".into()).into()), + _ => return Err(CheckErrorKind::Expects("Unexpected function type".into()).into()), }; check_argument_count(expected_args.len(), func_args)?; @@ -269,7 +271,7 @@ impl FunctionType { ) => { let contract_to_check = db .load_contract(contract, &StacksEpochId::Epoch2_05)? - .ok_or_else(|| CheckErrors::NoSuchContract(contract.name.to_string()))?; + .ok_or_else(|| CheckErrorKind::NoSuchContract(contract.name.to_string()))?; let trait_definition = db .get_defined_trait( &trait_id.contract_identifier, @@ -277,9 +279,9 @@ impl FunctionType { &StacksEpochId::Epoch2_05, ) .map_err(|_| { - CheckErrors::NoSuchContract(trait_id.contract_identifier.to_string()) + CheckErrorKind::NoSuchContract(trait_id.contract_identifier.to_string()) })? - .ok_or(CheckErrors::NoSuchContract( + .ok_or(CheckErrorKind::NoSuchContract( trait_id.contract_identifier.to_string(), ))?; contract_to_check.check_trait_compliance( @@ -291,7 +293,7 @@ impl FunctionType { (expected_type, value) => { if !expected_type.admits(&StacksEpochId::Epoch2_05, value)? { let actual_type = TypeSignature::type_of(value)?; - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type), ) @@ -306,7 +308,7 @@ impl FunctionType { fn trait_type_size( trait_sig: &BTreeMap, -) -> Result { +) -> Result { let mut total_size = 0; for (_func_name, value) in trait_sig.iter() { total_size = total_size.cost_overflow_add(value.total_type_size()?)?; @@ -314,7 +316,7 @@ fn trait_type_size( Ok(total_size) } -fn type_reserved_variable(variable_name: &str) -> Result, CheckError> { +fn type_reserved_variable(variable_name: &str) -> Result, StaticCheckError> { if let Some(variable) = NativeVariables::lookup_by_name_at_version(variable_name, &ClarityVersion::Clarity1) { @@ -325,13 +327,13 @@ fn type_reserved_variable(variable_name: &str) -> Result, BlockHeight => TypeSignature::UIntType, BurnBlockHeight => TypeSignature::UIntType, NativeNone => TypeSignature::new_option(no_type()) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, NativeTrue => TypeSignature::BoolType, NativeFalse => TypeSignature::BoolType, TotalLiquidMicroSTX => TypeSignature::UIntType, Regtest => TypeSignature::BoolType, TxSponsor | Mainnet | ChainId | StacksBlockHeight | TenureHeight | BlockTime | CurrentContract => { - return Err(CheckErrors::Expects( + return Err(CheckErrorKind::Expects( "tx-sponsor, mainnet, chain-id, stacks-block-height, tenure-height, block-time, and current-contract should not reach here in 2.05".into(), ) .into()) @@ -372,7 +374,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { self.cost_track } - pub fn track_return_type(&mut self, return_type: TypeSignature) -> Result<(), CheckError> { + pub fn track_return_type( + &mut self, + return_type: TypeSignature, + ) -> Result<(), StaticCheckError> { runtime_cost( ClarityCostFunction::AnalysisTypeCheck, self, @@ -388,7 +393,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new(expected_type), Box::new(return_type), ) @@ -407,7 +412,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } } - pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), CheckError> { + pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), StaticCheckError> { // charge for the eventual storage cost of the analysis -- // it is linear in the size of the AST. let mut size: u64 = 0; @@ -419,7 +424,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } Err(e) => Err(e), })? - .ok_or_else(|| CheckErrors::Expects("Expected a depth result".into()))?; + .ok_or_else(|| CheckErrorKind::Expects("Expected a depth result".into()))?; } runtime_cost(ClarityCostFunction::AnalysisStorage, self, size)?; @@ -449,7 +454,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { expr: &SymbolicExpression, context: &TypingContext, expected_type: &TypeSignature, - ) -> Result { + ) -> Result { if let ( LiteralValue(Value::Principal(PrincipalData::Contract(ref contract_identifier))), TypeSignature::TraitReferenceType(trait_identifier), @@ -458,7 +463,9 @@ impl<'a, 'b> TypeChecker<'a, 'b> { let contract_to_check = self .db .load_contract(contract_identifier, &StacksEpochId::Epoch2_05)? - .ok_or(CheckErrors::NoSuchContract(contract_identifier.to_string()))?; + .ok_or(CheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ))?; let contract_defining_trait = self .db @@ -466,13 +473,13 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &trait_identifier.contract_identifier, &StacksEpochId::Epoch2_05, )? - .ok_or(CheckErrors::NoSuchContract( + .ok_or(CheckErrorKind::NoSuchContract( trait_identifier.contract_identifier.to_string(), ))?; let trait_definition = contract_defining_trait .get_defined_trait(&trait_identifier.name) - .ok_or(CheckErrors::NoSuchTrait( + .ok_or(CheckErrorKind::NoSuchTrait( trait_identifier.contract_identifier.to_string(), trait_identifier.name.to_string(), ))?; @@ -489,8 +496,8 @@ impl<'a, 'b> TypeChecker<'a, 'b> { analysis_typecheck_cost(self, expected_type, &actual_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch2_05, &actual_type)? { - let mut err: CheckError = - CheckErrors::TypeError(Box::new(expected_type.clone()), Box::new(actual_type)) + let mut err: StaticCheckError = + CheckErrorKind::TypeError(Box::new(expected_type.clone()), Box::new(actual_type)) .into(); err.set_expression(expr); Err(err) @@ -504,7 +511,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expr: &SymbolicExpression, context: &TypingContext, - ) -> Result { + ) -> Result { runtime_cost(ClarityCostFunction::AnalysisVisit, self, 0)?; let mut result = self.inner_type_check(expr, context); @@ -522,16 +529,16 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, args: &[SymbolicExpression], context: &TypingContext, - ) -> Result { + ) -> Result { let mut types_returned = self.type_check_all(args, context)?; - let last_return = types_returned - .pop() - .ok_or(CheckError::new(CheckErrors::CheckerImplementationFailure))?; + let last_return = types_returned.pop().ok_or(StaticCheckError::new( + CheckErrorKind::CheckerImplementationFailure, + ))?; for type_return in types_returned.iter() { if type_return.is_response_type() { - return Err(CheckErrors::UncheckedIntermediaryResponses.into()); + return Err(CheckErrorKind::UncheckedIntermediaryResponses.into()); } } Ok(last_return) @@ -541,7 +548,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, args: &[SymbolicExpression], context: &TypingContext, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { let mut result = Vec::with_capacity(args.len()); for arg in args.iter() { // don't use map here, since type_check has side-effects. @@ -555,7 +562,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { func_type: &FunctionType, args: &[SymbolicExpression], context: &TypingContext, - ) -> Result { + ) -> Result { let typed_args = self.type_check_all(args, context)?; func_type.check_args(self, &typed_args, context.epoch, context.clarity_version) } @@ -571,14 +578,14 @@ impl<'a, 'b> TypeChecker<'a, 'b> { signature: &[SymbolicExpression], body: &SymbolicExpression, context: &TypingContext, - ) -> Result<(ClarityName, FixedFunction), CheckError> { + ) -> Result<(ClarityName, FixedFunction), StaticCheckError> { let (function_name, args) = signature .split_first() - .ok_or(CheckErrors::RequiresAtLeastArguments(1, 0))?; + .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, 0))?; let function_name = function_name .match_atom() - .ok_or(CheckErrors::BadFunctionName)?; - let args = parse_name_type_pairs::<(), CheckError>( + .ok_or(CheckErrorKind::BadFunctionName)?; + let args = parse_name_type_pairs::<(), StaticCheckError>( StacksEpochId::Epoch2_05, args, SyntaxBindingErrorType::Eval, @@ -586,7 +593,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { )?; if self.function_return_tracker.is_some() { - return Err(CheckErrors::Expects( + return Err(CheckErrorKind::Expects( "Interpreter error: Previous function define left dirty typecheck state.".into(), ) .into()); @@ -628,7 +635,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new(expected.clone()), Box::new(return_type), ) @@ -661,16 +668,16 @@ impl<'a, 'b> TypeChecker<'a, 'b> { map_name: &ClarityName, key_type: &SymbolicExpression, value_type: &SymbolicExpression, - ) -> Result<(ClarityName, (TypeSignature, TypeSignature)), CheckError> { + ) -> Result<(ClarityName, (TypeSignature, TypeSignature)), StaticCheckError> { self.type_map.set_type(key_type, no_type())?; self.type_map.set_type(value_type, no_type())?; // should we set the type of the subexpressions of the signature to no-type as well? let key_type = TypeSignature::parse_type_repr(StacksEpochId::Epoch2_05, key_type, &mut ()) - .map_err(|_| CheckErrors::BadMapTypeDefinition)?; + .map_err(|_| CheckErrorKind::BadMapTypeDefinition)?; let value_type = TypeSignature::parse_type_repr(StacksEpochId::Epoch2_05, value_type, &mut ()) - .map_err(|_| CheckErrors::BadMapTypeDefinition)?; + .map_err(|_| CheckErrorKind::BadMapTypeDefinition)?; Ok((map_name.clone(), (key_type, value_type))) } @@ -681,7 +688,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { function: &str, args: &[SymbolicExpression], context: &TypingContext, - ) -> Option> { + ) -> Option> { if let Some(ref native_function) = NativeFunctions::lookup_by_name_at_version(function, &ClarityVersion::Clarity1) { @@ -699,22 +706,22 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expression: &[SymbolicExpression], context: &TypingContext, - ) -> Result { + ) -> Result { let (function_name, args) = expression .split_first() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; self.type_map.set_type(function_name, no_type())?; let function_name = function_name .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; if let Some(type_result) = self.try_native_function_check(function_name, args, context) { type_result } else { let function = match self.get_function_type(function_name) { Some(FunctionType::Fixed(function)) => Ok(function), - _ => Err(CheckErrors::UnknownFunction(function_name.to_string())), + _ => Err(CheckErrorKind::UnknownFunction(function_name.to_string())), }?; for (expected_type, found_type) in function.args.iter().map(|x| &x.signature).zip(args) @@ -730,7 +737,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, name: &str, context: &TypingContext, - ) -> Result { + ) -> Result { runtime_cost(ClarityCostFunction::AnalysisLookupVariableConst, self, 0)?; if let Some(type_result) = type_reserved_variable(name)? { @@ -744,7 +751,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { // be undefined. This early error prevents a cost function error // due to `context.depth` being 0. if context.depth == 0 { - return Err(CheckErrors::UndefinedVariable(name.to_string()).into()); + return Err(CheckErrorKind::UndefinedVariable(name.to_string()).into()); } runtime_cost( @@ -756,7 +763,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { if let Some(type_result) = context.lookup_variable_type(name) { Ok(type_result.clone()) } else { - Err(CheckErrors::UndefinedVariable(name.to_string()).into()) + Err(CheckErrorKind::UndefinedVariable(name.to_string()).into()) } } } @@ -765,13 +772,13 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expr: &SymbolicExpression, context: &TypingContext, - ) -> Result { + ) -> Result { let type_sig = match expr.expr { AtomValue(ref value) | LiteralValue(ref value) => TypeSignature::type_of(value)?, Atom(ref name) => self.lookup_variable(name, context)?, List(ref expression) => self.type_check_function_application(expression, context)?, TraitReference(_, _) | Field(_) => { - return Err(CheckErrors::UnexpectedTraitOrFieldReference.into()); + return Err(CheckErrorKind::UnexpectedTraitOrFieldReference.into()); } }; @@ -789,7 +796,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { var_name: &ClarityName, var_type: &SymbolicExpression, context: &mut TypingContext, - ) -> Result<(ClarityName, TypeSignature), CheckError> { + ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let var_type = self.type_check(var_type, context)?; Ok((var_name.clone(), var_type)) } @@ -800,10 +807,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { var_type: &SymbolicExpression, initial: &SymbolicExpression, context: &mut TypingContext, - ) -> Result<(ClarityName, TypeSignature), CheckError> { + ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let expected_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch2_05, var_type, &mut ()) - .map_err(|_e| CheckErrors::DefineVariableBadSignature)?; + .map_err(|_e| CheckErrorKind::DefineVariableBadSignature)?; self.type_check_expects(initial, context, &expected_type)?; @@ -815,7 +822,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { token_name: &ClarityName, bound: Option<&SymbolicExpression>, context: &mut TypingContext, - ) -> Result { + ) -> Result { if let Some(bound) = bound { self.type_check_expects(bound, context, &TypeSignature::UIntType)?; } @@ -828,10 +835,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { asset_name: &ClarityName, nft_type: &SymbolicExpression, _context: &mut TypingContext, - ) -> Result<(ClarityName, TypeSignature), CheckError> { + ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let asset_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch2_05, nft_type, &mut ()) - .map_err(|_| CheckErrors::DefineNFTBadSignature)?; + .map_err(|_| CheckErrorKind::DefineNFTBadSignature)?; Ok((asset_name.clone(), asset_type)) } @@ -841,7 +848,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { trait_name: &ClarityName, function_types: &[SymbolicExpression], _context: &mut TypingContext, - ) -> Result<(ClarityName, BTreeMap), CheckError> { + ) -> Result<(ClarityName, BTreeMap), StaticCheckError> { let trait_signature = TypeSignature::parse_trait_type_repr( function_types, &mut (), @@ -857,7 +864,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expression: &SymbolicExpression, context: &mut TypingContext, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { if let Some(define_type) = DefineFunctionsParsed::try_parse(expression)? { match define_type { DefineFunctionsParsed::Constant { name, value } => { @@ -895,7 +902,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { .add_public_function_type(f_name, FunctionType::Fixed(f_type))?; return Ok(Some(())); } else { - return Err(CheckErrors::PublicFunctionMustReturnResponse(Box::new( + return Err(CheckErrorKind::PublicFunctionMustReturnResponse(Box::new( f_type.returns, )) .into()); @@ -1002,7 +1009,9 @@ impl<'a, 'b> TypeChecker<'a, 'b> { None => { // still had to do a db read, even if it didn't exist! runtime_cost(ClarityCostFunction::AnalysisUseTraitEntry, self, 1)?; - return Err(CheckErrors::TraitReferenceUnknown(name.to_string()).into()); + return Err( + CheckErrorKind::TraitReferenceUnknown(name.to_string()).into() + ); } } } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/assets.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/assets.rs index 13f967e6af3..74680694340 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/assets.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/assets.rs @@ -15,7 +15,7 @@ // along with this program. If not, see . use super::{TypeChecker, TypingContext}; -use crate::vm::analysis::errors::{check_argument_count, CheckError, CheckErrors}; +use crate::vm::analysis::errors::{check_argument_count, CheckErrorKind, StaticCheckError}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::representations::SymbolicExpression; @@ -25,16 +25,16 @@ pub fn check_special_get_owner( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) .cloned() - .ok_or_else(|| CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or_else(|| CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -53,13 +53,13 @@ pub fn check_special_get_balance( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -74,16 +74,16 @@ pub fn check_special_mint_asset( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))? + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? .clone(); // this clone shouldn't be strictly necessary, but to use `type_check_expects` with this, it would have to be. runtime_cost( @@ -105,10 +105,10 @@ pub fn check_special_mint_token( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -119,7 +119,7 @@ pub fn check_special_mint_token( checker.type_check_expects(&args[2], context, &expected_owner_type)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -132,16 +132,16 @@ pub fn check_special_transfer_asset( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(token_name) - .ok_or(CheckErrors::NoSuchNFT(token_name.to_string()))? + .ok_or(CheckErrorKind::NoSuchNFT(token_name.to_string()))? .clone(); runtime_cost( @@ -164,10 +164,10 @@ pub fn check_special_transfer_token( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -179,7 +179,7 @@ pub fn check_special_transfer_token( checker.type_check_expects(&args[3], context, &expected_owner_type)?; // recipient if !checker.contract_context.ft_exists(token_name) { - return Err(CheckErrors::NoSuchFT(token_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(token_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -192,13 +192,13 @@ pub fn check_special_get_token_supply( checker: &mut TypeChecker, args: &[SymbolicExpression], _context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -210,16 +210,16 @@ pub fn check_special_burn_asset( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))? + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? .clone(); // this clone shouldn't be strictly necessary, but to use `type_check_expects` with this, it would have to be. runtime_cost( @@ -241,10 +241,10 @@ pub fn check_special_burn_token( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -255,7 +255,7 @@ pub fn check_special_burn_token( checker.type_check_expects(&args[2], context, &expected_owner_type)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/maps.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/maps.rs index ccbf880e179..e454e424f10 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/maps.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/maps.rs @@ -17,7 +17,7 @@ use stacks_common::types::StacksEpochId; use crate::vm::analysis::type_checker::v2_05::{ - check_arguments_at_least, CheckError, CheckErrors, TypeChecker, TypingContext, + check_arguments_at_least, CheckErrorKind, StaticCheckError, TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; @@ -28,17 +28,17 @@ pub fn check_special_fetch_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let (expected_key_type, value_type) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -55,7 +55,7 @@ pub fn check_special_fetch_entry( let option_type = TypeSignature::new_option(value_type.clone())?; if !expected_key_type.admits_type(&StacksEpochId::Epoch2_05, &key_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -68,17 +68,17 @@ pub fn check_special_delete_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let (expected_key_type, _) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -88,7 +88,7 @@ pub fn check_special_delete_entry( analysis_typecheck_cost(&mut checker.cost_track, expected_key_type, &key_type)?; if !expected_key_type.admits_type(&StacksEpochId::Epoch2_05, &key_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -101,10 +101,10 @@ fn check_set_or_insert_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(3, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let value_type = checker.type_check(&args[2], context)?; @@ -112,7 +112,7 @@ fn check_set_or_insert_entry( let (expected_key_type, expected_value_type) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -129,12 +129,12 @@ fn check_set_or_insert_entry( analysis_typecheck_cost(&mut checker.cost_track, expected_value_type, &value_type)?; if !expected_key_type.admits_type(&StacksEpochId::Epoch2_05, &key_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) } else if !expected_value_type.admits_type(&StacksEpochId::Epoch2_05, &value_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) @@ -147,7 +147,7 @@ pub fn check_special_set_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_set_or_insert_entry(checker, args, context) } @@ -155,6 +155,6 @@ pub fn check_special_insert_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_set_or_insert_entry(checker, args, context) } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs index 08297f7440f..45ad3f529e4 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs @@ -17,7 +17,7 @@ use stacks_common::types::StacksEpochId; use super::{check_argument_count, check_arguments_at_least, no_type, TypeChecker, TypingContext}; -use crate::vm::analysis::errors::{CheckError, CheckErrors, SyntaxBindingErrorType}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError, SyntaxBindingErrorType}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; use crate::vm::diagnostic::DiagnosableError; @@ -45,7 +45,7 @@ pub struct SpecialNativeFunction( &mut TypeChecker, &[SymbolicExpression], &TypingContext, - ) -> Result, + ) -> Result, ); pub struct SimpleNativeFunction(pub FunctionType); @@ -53,7 +53,7 @@ fn check_special_list_cons( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { let typed_args = checker.type_check_all(args, context)?; for type_arg in typed_args.iter() { runtime_cost( @@ -70,7 +70,7 @@ fn check_special_print( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; checker.type_check(&args[0], context) } @@ -79,7 +79,7 @@ fn check_special_as_contract( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; checker.type_check(&args[0], context) } @@ -88,7 +88,7 @@ fn check_special_at_block( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; checker.type_check_expects(&args[0], context, &BUFF_32)?; checker.type_check(&args[1], context) @@ -98,7 +98,7 @@ fn check_special_begin( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; checker.type_check_consecutive_statements(args, context) @@ -108,7 +108,7 @@ fn inner_handle_tuple_get( tuple_type_sig: &TupleTypeSignature, field_to_get: &str, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost( ClarityCostFunction::AnalysisCheckTupleGet, checker, @@ -117,7 +117,7 @@ fn inner_handle_tuple_get( let return_type = tuple_type_sig .field_type(field_to_get) - .ok_or(CheckError::new(CheckErrors::NoSuchTupleField( + .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchTupleField( field_to_get.to_string(), tuple_type_sig.clone(), )))? @@ -129,10 +129,12 @@ fn check_special_get( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let field_to_get = args[0].match_atom().ok_or(CheckErrors::BadTupleFieldName)?; + let field_to_get = args[0] + .match_atom() + .ok_or(CheckErrorKind::BadTupleFieldName)?; let argument_type = checker.type_check(&args[1], context)?; @@ -144,10 +146,10 @@ fn check_special_get( let option_type = TypeSignature::new_option(inner_type)?; Ok(option_type) } else { - Err(CheckErrors::ExpectedTuple(value_type_sig).into()) + Err(CheckErrorKind::ExpectedTuple(value_type_sig).into()) } } else { - Err(CheckErrors::ExpectedTuple(Box::new(argument_type)).into()) + Err(CheckErrorKind::ExpectedTuple(Box::new(argument_type)).into()) } } @@ -155,19 +157,19 @@ fn check_special_merge( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let res = checker.type_check(&args[0], context)?; let mut base = match res { TypeSignature::TupleType(tuple_sig) => Ok(tuple_sig), - _ => Err(CheckErrors::ExpectedTuple(Box::new(res.clone()))), + _ => Err(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), }?; let res = checker.type_check(&args[1], context)?; let mut update = match res { TypeSignature::TupleType(tuple_sig) => Ok(tuple_sig), - _ => Err(CheckErrors::ExpectedTuple(Box::new(res.clone()))), + _ => Err(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), }?; runtime_cost( ClarityCostFunction::AnalysisCheckTupleMerge, @@ -183,7 +185,7 @@ pub fn check_special_tuple_cons( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; let len = args.len(); @@ -208,7 +210,7 @@ pub fn check_special_tuple_cons( )?; let tuple_signature = TupleTypeSignature::try_from(tuple_type_data) - .map_err(|e| CheckErrors::BadTupleConstruction(e.message()))?; + .map_err(|e| CheckErrorKind::BadTupleConstruction(e.message()))?; Ok(TypeSignature::TupleType(tuple_signature)) } @@ -217,12 +219,12 @@ fn check_special_let( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; let binding_list = args[0] .match_list() - .ok_or(CheckError::new(CheckErrors::BadLetSyntax))?; + .ok_or(StaticCheckError::new(CheckErrorKind::BadLetSyntax))?; let mut out_context = context.extend()?; @@ -234,7 +236,7 @@ fn check_special_let( |var_name, var_sexp| { checker.contract_context.check_name_used(var_name)?; if out_context.lookup_variable_type(var_name).is_some() { - return Err(CheckError::new(CheckErrors::NameAlreadyUsed( + return Err(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( var_name.to_string(), ))); } @@ -260,17 +262,17 @@ fn check_special_fetch_var( checker: &mut TypeChecker, args: &[SymbolicExpression], _context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let var_name = args[0] .match_atom() - .ok_or(CheckError::new(CheckErrors::BadMapName))?; + .ok_or(StaticCheckError::new(CheckErrorKind::BadMapName))?; let value_type = checker .contract_context .get_persisted_variable_type(var_name) - .ok_or(CheckError::new(CheckErrors::NoSuchDataVariable( + .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchDataVariable( var_name.to_string(), )))?; @@ -287,17 +289,17 @@ fn check_special_set_var( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let var_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let var_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let value_type = checker.type_check(&args[1], context)?; let expected_value_type = checker .contract_context .get_persisted_variable_type(var_name) - .ok_or(CheckErrors::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -307,7 +309,7 @@ fn check_special_set_var( analysis_typecheck_cost(&mut checker.cost_track, &value_type, expected_value_type)?; if !expected_value_type.admits_type(&StacksEpochId::Epoch2_05, &value_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) @@ -320,7 +322,7 @@ fn check_special_equals( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; let arg_types = checker.type_check_all(args, context)?; @@ -329,7 +331,7 @@ fn check_special_equals( for x_type in arg_types.into_iter() { analysis_typecheck_cost(checker, &x_type, &arg_type)?; arg_type = TypeSignature::least_supertype(&StacksEpochId::Epoch2_05, &x_type, &arg_type) - .map_err(|_| CheckErrors::TypeError(Box::new(x_type), Box::new(arg_type)))?; + .map_err(|_| CheckErrorKind::TypeError(Box::new(x_type), Box::new(arg_type)))?; } Ok(TypeSignature::BoolType) @@ -339,7 +341,7 @@ fn check_special_if( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; checker.type_check_expects(&args[0], context, &TypeSignature::BoolType)?; @@ -352,7 +354,7 @@ fn check_special_if( analysis_typecheck_cost(checker, expr1, expr2)?; TypeSignature::least_supertype(&StacksEpochId::Epoch2_05, expr1, expr2).map_err(|_| { - CheckErrors::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())).into() + CheckErrorKind::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())).into() }) } @@ -360,12 +362,12 @@ fn check_contract_call( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let func_name = args[1] - .match_atom() - .ok_or(CheckError::new(CheckErrors::ContractCallExpectName))?; + let func_name = args[1].match_atom().ok_or(StaticCheckError::new( + CheckErrorKind::ContractCallExpectName, + ))?; checker.type_map.set_type(&args[1], no_type())?; let expected_sig = match &args[0].expr { @@ -389,7 +391,7 @@ fn check_contract_call( { Ok(function) } else { - Err(CheckError::new(CheckErrors::NoSuchPublicFunction( + Err(StaticCheckError::new(CheckErrorKind::NoSuchPublicFunction( contract_identifier.to_string(), func_name.to_string(), ))) @@ -412,7 +414,7 @@ fn check_contract_call( Some(trait_id) => trait_id, _ => { return Err( - CheckErrors::TraitReferenceUnknown(trait_instance.to_string()).into(), + CheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into(), ); } }; @@ -420,12 +422,12 @@ fn check_contract_call( runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; let trait_signature = checker.contract_context.get_trait(&trait_id.name).ok_or( - CheckErrors::TraitReferenceUnknown(trait_id.name.to_string()), + CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), )?; let func_signature = trait_signature .get(func_name) - .ok_or(CheckErrors::TraitMethodUnknown( + .ok_or(CheckErrorKind::TraitMethodUnknown( trait_id.name.to_string(), func_name.to_string(), ))?; @@ -438,7 +440,11 @@ fn check_contract_call( func_signature.clone() } - _ => return Err(CheckError::new(CheckErrors::ContractCallExpectName)), + _ => { + return Err(StaticCheckError::new( + CheckErrorKind::ContractCallExpectName, + )) + } }; check_argument_count(expected_sig.args.len(), &args[2..])?; @@ -453,17 +459,21 @@ fn check_contract_of( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let trait_instance = match &args[0].expr { SymbolicExpressionType::Atom(trait_instance) => trait_instance, - _ => return Err(CheckError::new(CheckErrors::ContractOfExpectsTrait)), + _ => { + return Err(StaticCheckError::new( + CheckErrorKind::ContractOfExpectsTrait, + )) + } }; let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, - _ => return Err(CheckErrors::TraitReferenceUnknown(trait_instance.to_string()).into()), + _ => return Err(CheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into()), }; runtime_cost(ClarityCostFunction::ContractOf, checker, 1)?; @@ -471,7 +481,7 @@ fn check_contract_of( checker .contract_context .get_trait(&trait_id.name) - .ok_or_else(|| CheckErrors::TraitReferenceUnknown(trait_id.name.to_string()))?; + .ok_or_else(|| CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()))?; Ok(TypeSignature::PrincipalType) } @@ -480,12 +490,12 @@ fn check_principal_of( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; checker.type_check_expects(&args[0], context, &BUFF_33)?; Ok( TypeSignature::new_response(TypeSignature::PrincipalType, TypeSignature::UIntType) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -493,13 +503,13 @@ fn check_secp256k1_recover( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; checker.type_check_expects(&args[0], context, &BUFF_32)?; checker.type_check_expects(&args[1], context, &BUFF_65)?; Ok( TypeSignature::new_response(BUFF_33.clone(), TypeSignature::UIntType) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -507,7 +517,7 @@ fn check_secp256k1_verify( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; checker.type_check_expects(&args[0], context, &BUFF_32)?; checker.type_check_expects(&args[1], context, &BUFF_65)?; @@ -519,20 +529,20 @@ fn check_get_block_info( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let block_info_prop_str = args[0] - .match_atom() - .ok_or(CheckError::new(CheckErrors::GetBlockInfoExpectPropertyName))?; + let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( + CheckErrorKind::GetBlockInfoExpectPropertyName, + ))?; let block_info_prop = BlockInfoProperty::lookup_by_name_at_version( block_info_prop_str, &ClarityVersion::Clarity1, ) - .ok_or(CheckError::new(CheckErrors::NoSuchBlockInfoProperty( - block_info_prop_str.to_string(), - )))?; + .ok_or(StaticCheckError::new( + CheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), + ))?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -545,7 +555,7 @@ impl TypedNativeFunction { checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, - ) -> Result { + ) -> Result { use self::TypedNativeFunction::{Simple, Special}; match self { Special(SpecialNativeFunction(check)) => check(checker, args, context), @@ -557,7 +567,7 @@ impl TypedNativeFunction { pub fn type_native_function( function: &NativeFunctions, - ) -> Result { + ) -> Result { use self::TypedNativeFunction::{Simple, Special}; use crate::vm::functions::NativeFunctions::*; let out = match function { @@ -579,7 +589,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::IntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -590,7 +600,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -601,7 +611,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::BoolType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -654,7 +664,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("owner".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -666,7 +676,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("amount".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -674,7 +684,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("sender".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -682,7 +692,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("recipient".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -692,14 +702,14 @@ impl TypedNativeFunction { TypeSignature::BoolType, TypeSignature::UIntType, ) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, }))), StxBurn => Simple(SimpleNativeFunction(FunctionType::Fixed(FixedFunction { args: vec![ FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("amount".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -707,7 +717,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("sender".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -717,7 +727,7 @@ impl TypedNativeFunction { TypeSignature::BoolType, TypeSignature::UIntType, ) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, }))), GetTokenBalance => Special(SpecialNativeFunction(&assets::check_special_get_balance)), GetAssetOwner => Special(SpecialNativeFunction(&assets::check_special_get_owner)), @@ -783,7 +793,7 @@ impl TypedNativeFunction { | StxGetAccount | BitwiseAnd | BitwiseOr | BitwiseNot | BitwiseLShift | BitwiseRShift | BitwiseXor2 | Slice | ToConsensusBuff | FromConsensusBuff | ReplaceAt | GetStacksBlockInfo | GetTenureInfo | ContractHash | ToAscii => { - return Err(CheckErrors::Expects( + return Err(CheckErrorKind::Expects( "Clarity 2+ keywords should not show up in 2.05".into(), )); } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/options.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/options.rs index 1cf9b301a7d..73a4d87f649 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/options.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/options.rs @@ -19,8 +19,8 @@ use clarity_types::types::TypeSignature; use stacks_common::types::StacksEpochId; use crate::vm::analysis::type_checker::v2_05::{ - check_argument_count, check_arguments_at_least, no_type, CheckError, CheckErrors, TypeChecker, - TypingContext, + check_argument_count, check_arguments_at_least, no_type, CheckErrorKind, StaticCheckError, + TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; @@ -30,7 +30,7 @@ pub fn check_special_okay( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; runtime_cost(ClarityCostFunction::AnalysisOptionCons, checker, 0)?; @@ -44,7 +44,7 @@ pub fn check_special_some( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; runtime_cost(ClarityCostFunction::AnalysisOptionCons, checker, 0)?; @@ -58,7 +58,7 @@ pub fn check_special_error( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; runtime_cost(ClarityCostFunction::AnalysisOptionCons, checker, 0)?; @@ -72,7 +72,7 @@ pub fn check_special_is_response( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -82,7 +82,7 @@ pub fn check_special_is_response( if let TypeSignature::ResponseType(_types) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrors::ExpectedResponseType(Box::new(input)).into()) + Err(CheckErrorKind::ExpectedResponseType(Box::new(input)).into()) } } @@ -90,7 +90,7 @@ pub fn check_special_is_optional( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -100,7 +100,7 @@ pub fn check_special_is_optional( if let TypeSignature::OptionalType(_type) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrors::ExpectedOptionalType(Box::new(input)).into()) + Err(CheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) } } @@ -108,7 +108,7 @@ pub fn check_special_default_to( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let default = checker.type_check(&args[0], context)?; @@ -120,11 +120,11 @@ pub fn check_special_default_to( let contained_type = *input_type; TypeSignature::least_supertype(&StacksEpochId::Epoch2_05, &default, &contained_type) .map_err(|_| { - CheckErrors::DefaultTypesMustMatch(Box::new(default), Box::new(contained_type)) + CheckErrorKind::DefaultTypesMustMatch(Box::new(default), Box::new(contained_type)) .into() }) } else { - Err(CheckErrors::ExpectedOptionalType(Box::new(input)).into()) + Err(CheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) } } @@ -132,7 +132,7 @@ pub fn check_special_asserts( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; checker.type_check_expects(&args[0], context, &TypeSignature::BoolType)?; @@ -146,13 +146,13 @@ pub fn check_special_asserts( fn inner_unwrap( input: TypeSignature, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost(ClarityCostFunction::AnalysisOptionCheck, checker, 0)?; match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(*input_type) } @@ -160,30 +160,30 @@ fn inner_unwrap( TypeSignature::ResponseType(response_type) => { let ok_type = response_type.0; if ok_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(ok_type) } } - _ => Err(CheckErrors::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } fn inner_unwrap_err( input: TypeSignature, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost(ClarityCostFunction::AnalysisOptionCheck, checker, 0)?; if let TypeSignature::ResponseType(response_type) = input { let err_type = response_type.1; if err_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseErrType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { Ok(err_type) } } else { - Err(CheckErrors::ExpectedResponseType(Box::new(input)).into()) + Err(CheckErrorKind::ExpectedResponseType(Box::new(input)).into()) } } @@ -191,7 +191,7 @@ pub fn check_special_unwrap_or_ret( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let input = checker.type_check(&args[0], context)?; @@ -206,7 +206,7 @@ pub fn check_special_unwrap_err_or_ret( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let input = checker.type_check(&args[0], context)?; @@ -221,7 +221,7 @@ pub fn check_special_try_ret( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -231,7 +231,7 @@ pub fn check_special_try_ret( match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { checker.track_return_type(TypeSignature::new_option(TypeSignature::NoType)?)?; Ok(*input_type) @@ -240,9 +240,9 @@ pub fn check_special_try_ret( TypeSignature::ResponseType(response_type) => { let (ok_type, err_type) = *response_type; if ok_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else if err_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseErrType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { checker.track_return_type(TypeSignature::new_response( TypeSignature::NoType, @@ -251,7 +251,7 @@ pub fn check_special_try_ret( Ok(ok_type) } } - _ => Err(CheckErrors::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } @@ -259,7 +259,7 @@ pub fn check_special_unwrap( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -271,7 +271,7 @@ pub fn check_special_unwrap_err( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -285,7 +285,7 @@ fn eval_with_new_binding( bind_type: TypeSignature, checker: &mut TypeChecker, context: &TypingContext, -) -> Result { +) -> Result { let mut inner_context = context.extend()?; runtime_cost( @@ -297,7 +297,7 @@ fn eval_with_new_binding( checker.contract_context.check_name_used(&bind_name)?; if inner_context.lookup_variable_type(&bind_name).is_some() { - return Err(CheckErrors::NameAlreadyUsed(bind_name.into()).into()); + return Err(CheckErrorKind::NameAlreadyUsed(bind_name.into()).into()); } inner_context.variable_types.insert(bind_name, bind_type); @@ -310,22 +310,24 @@ fn check_special_match_opt( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { if args.len() != 3 { - Err(CheckErrors::BadMatchOptionSyntax(Box::new( - CheckErrors::IncorrectArgumentCount(4, args.len() + 1), + Err(CheckErrorKind::BadMatchOptionSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(4, args.len() + 1), )))?; } let bind_name = args[0] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchOptionSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let some_branch = &args[1]; let none_branch = &args[2]; if option_type.is_no_type() { - return Err(CheckErrors::CouldNotDetermineMatchTypes.into()); + return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); } let some_branch_type = @@ -340,7 +342,7 @@ fn check_special_match_opt( &none_branch_type, ) .map_err(|_| { - CheckErrors::MatchArmsMustMatch(Box::new(some_branch_type), Box::new(none_branch_type)) + CheckErrorKind::MatchArmsMustMatch(Box::new(some_branch_type), Box::new(none_branch_type)) .into() }) } @@ -350,28 +352,32 @@ fn check_special_match_resp( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { if args.len() != 4 { - Err(CheckErrors::BadMatchResponseSyntax(Box::new( - CheckErrors::IncorrectArgumentCount(5, args.len() + 1), + Err(CheckErrorKind::BadMatchResponseSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(5, args.len() + 1), )))?; } let ok_bind_name = args[0] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let ok_branch = &args[1]; let err_bind_name = args[2] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let err_branch = &args[3]; let (ok_type, err_type) = resp_type; if ok_type.is_no_type() || err_type.is_no_type() { - return Err(CheckErrors::CouldNotDetermineMatchTypes.into()); + return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); } let ok_branch_type = eval_with_new_binding(ok_branch, ok_bind_name, ok_type, checker, context)?; @@ -382,7 +388,7 @@ fn check_special_match_resp( TypeSignature::least_supertype(&StacksEpochId::Epoch2_05, &ok_branch_type, &err_branch_type) .map_err(|_| { - CheckErrors::MatchArmsMustMatch(Box::new(ok_branch_type), Box::new(err_branch_type)) + CheckErrorKind::MatchArmsMustMatch(Box::new(ok_branch_type), Box::new(err_branch_type)) .into() }) } @@ -391,7 +397,7 @@ pub fn check_special_match( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -403,6 +409,6 @@ pub fn check_special_match( TypeSignature::ResponseType(resp_type) => { check_special_match_resp(*resp_type, checker, &args[1..], context) } - _ => Err(CheckErrors::BadMatchInput(Box::new(input)).into()), + _ => Err(CheckErrorKind::BadMatchInput(Box::new(input)).into()), } } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs index 00904bfe493..44878db720f 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs @@ -18,7 +18,7 @@ use stacks_common::types::StacksEpochId; use super::{SimpleNativeFunction, TypedNativeFunction}; use crate::vm::analysis::type_checker::v2_05::{ - check_argument_count, check_arguments_at_least, CheckError, CheckErrors, TypeChecker, + check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -34,7 +34,7 @@ use crate::vm::ClarityVersion; fn get_simple_native_or_user_define( function_name: &str, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; if let Some(ref native_function) = NativeFunctions::lookup_by_name_at_version(function_name, &ClarityVersion::Clarity1) @@ -44,11 +44,14 @@ fn get_simple_native_or_user_define( { Ok(function_type) } else { - Err(CheckErrors::IllegalOrUnknownFunctionApplication(function_name.to_string()).into()) + Err( + CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()) + .into(), + ) } } else { checker.get_function_type(function_name).ok_or( - CheckErrors::IllegalOrUnknownFunctionApplication(function_name.to_string()).into(), + CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()).into(), ) } } @@ -57,12 +60,12 @@ pub fn check_special_map( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; let function_name = args[0] .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; // we will only lookup native or defined functions here. // you _cannot_ map a special function. let function_type = get_simple_native_or_user_define(function_name, checker)?; @@ -98,7 +101,7 @@ pub fn check_special_map( // However that could lead to confusions when combining certain types: // ex: (map concat (list "hello " "hi ") "world") would fail, because // strings are handled as sequences. - return Err(CheckErrors::ExpectedSequence(Box::new(argument_type)).into()); + return Err(CheckErrorKind::ExpectedSequence(Box::new(argument_type)).into()); } }; func_args.push(entry_type); @@ -107,19 +110,19 @@ pub fn check_special_map( let mapped_type = function_type.check_args(checker, &func_args, context.epoch, context.clarity_version)?; TypeSignature::list_of(mapped_type, min_args) - .map_err(|_| CheckErrors::ConstructedListTooLarge.into()) + .map_err(|_| CheckErrorKind::ConstructedListTooLarge.into()) } pub fn check_special_filter( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let function_name = args[0] .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; // we will only lookup native or defined functions here. // you _cannot_ map a special function. let function_type = get_simple_native_or_user_define(function_name, checker)?; @@ -130,7 +133,7 @@ pub fn check_special_filter( { let input_type = match argument_type { TypeSignature::SequenceType(ref sequence_type) => Ok(sequence_type.unit_type()?), - _ => Err(CheckErrors::ExpectedSequence(Box::new( + _ => Err(CheckErrorKind::ExpectedSequence(Box::new( argument_type.clone(), ))), }?; @@ -143,7 +146,7 @@ pub fn check_special_filter( )?; if TypeSignature::BoolType != filter_type { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(TypeSignature::BoolType), Box::new(filter_type), ) @@ -158,12 +161,12 @@ pub fn check_special_fold( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; let function_name = args[0] .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; // we will only lookup native or defined functions here. // you _cannot_ fold a special function. let function_type = get_simple_native_or_user_define(function_name, checker)?; @@ -173,7 +176,7 @@ pub fn check_special_fold( let input_type = match argument_type { TypeSignature::SequenceType(sequence_type) => Ok(sequence_type.unit_type()?), - _ => Err(CheckErrors::ExpectedSequence(Box::new(argument_type))), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(argument_type))), }?; let initial_value_type = checker.type_check(&args[2], context)?; @@ -205,7 +208,7 @@ pub fn check_special_concat( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let lhs_type = checker.type_check(&args[0], context)?; @@ -231,29 +234,29 @@ pub fn check_special_concat( )?; let new_len = lhs_max_len .checked_add(rhs_max_len) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::list_of(list_entry_type, new_len)? } (BufferType(lhs_len), BufferType(rhs_len)) => { let size: u32 = u32::from(lhs_len) .checked_add(u32::from(rhs_len)) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(BufferType(size.try_into()?)) } (StringType(ASCII(lhs_len)), StringType(ASCII(rhs_len))) => { let size: u32 = u32::from(lhs_len) .checked_add(u32::from(rhs_len)) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(StringType(ASCII(size.try_into()?))) } (StringType(UTF8(lhs_len)), StringType(UTF8(rhs_len))) => { let size: u32 = u32::from(lhs_len) .checked_add(u32::from(rhs_len)) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(StringType(UTF8(size.try_into()?))) } (_, _) => { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(lhs_type.clone()), Box::new(rhs_type.clone()), ) @@ -261,7 +264,7 @@ pub fn check_special_concat( } } } - _ => return Err(CheckErrors::ExpectedSequence(Box::new(lhs_type.clone())).into()), + _ => return Err(CheckErrorKind::ExpectedSequence(Box::new(lhs_type.clone())).into()), }; Ok(res) } @@ -270,7 +273,7 @@ pub fn check_special_append( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -290,11 +293,11 @@ pub fn check_special_append( )?; let new_len = lhs_max_len .checked_add(1) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; let return_type = TypeSignature::list_of(list_entry_type, new_len)?; Ok(return_type) } - _ => Err(CheckErrors::ExpectedListApplication.into()), + _ => Err(CheckErrorKind::ExpectedListApplication.into()), } } @@ -302,14 +305,14 @@ pub fn check_special_as_max_len( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let expected_len = match args[1].expr { SymbolicExpressionType::LiteralValue(Value::UInt(expected_len)) => expected_len, _ => { let expected_len_type = checker.type_check(&args[1], context)?; - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(expected_len_type), ) @@ -325,7 +328,8 @@ pub fn check_special_as_max_len( .type_map .set_type(&args[1], TypeSignature::UIntType)?; - let expected_len = u32::try_from(expected_len).map_err(|_e| CheckErrors::MaxLengthOverflow)?; + let expected_len = + u32::try_from(expected_len).map_err(|_e| CheckErrorKind::MaxLengthOverflow)?; let sequence = checker.type_check(&args[0], context)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -351,7 +355,7 @@ pub fn check_special_as_max_len( StringUTF8Length::try_from(expected_len)?, )))), )), - _ => Err(CheckErrors::ExpectedSequence(Box::new(sequence)).into()), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(sequence)).into()), } } @@ -359,7 +363,7 @@ pub fn check_special_len( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let collection_type = checker.type_check(&args[0], context)?; @@ -367,7 +371,7 @@ pub fn check_special_len( match collection_type { TypeSignature::SequenceType(_) => Ok(()), - _ => Err(CheckErrors::ExpectedSequence(Box::new(collection_type))), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type))), }?; Ok(TypeSignature::UIntType) @@ -377,7 +381,7 @@ pub fn check_special_element_at( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let _index_type = checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -396,16 +400,16 @@ pub fn check_special_element_at( TypeSignature::SequenceType(StringType(ASCII(_))) => Ok(TypeSignature::OptionalType( Box::new(TypeSignature::SequenceType(StringType(ASCII( BufferLength::try_from(1u32) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, )))), )), TypeSignature::SequenceType(StringType(UTF8(_))) => Ok(TypeSignature::OptionalType( Box::new(TypeSignature::SequenceType(StringType(UTF8( StringUTF8Length::try_from(1u32) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, )))), )), - _ => Err(CheckErrors::ExpectedSequence(Box::new(collection_type)).into()), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type)).into()), } } @@ -413,7 +417,7 @@ pub fn check_special_index_of( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -421,7 +425,7 @@ pub fn check_special_index_of( let expected_input_type = match list_type { TypeSignature::SequenceType(ref sequence_type) => Ok(sequence_type.unit_type()?), - _ => Err(CheckErrors::ExpectedSequence(Box::new(list_type))), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(list_type))), }?; checker.type_check_expects(&args[1], context, &expected_input_type)?; diff --git a/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs b/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs index 75dbc4928f5..39e52b274d2 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs @@ -16,7 +16,7 @@ use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::CheckErrors; +use crate::vm::analysis::errors::CheckErrorKind; use crate::vm::ast::parse; use crate::vm::database::MemoryBackingStore; use crate::vm::tooling::mem_type_check; @@ -193,108 +193,108 @@ fn test_bad_asset_usage() { ]; let expected = [ - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::BadTokenName, - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::BadTokenName, + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), ), - CheckErrors::BadTokenName, - CheckErrors::NoSuchNFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::NoSuchNFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrors::BadTokenName, - CheckErrors::NoSuchNFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::NoSuchNFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrors::BadTokenName, - CheckErrors::NoSuchNFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::NoSuchNFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrors::DefineNFTBadSignature, - CheckErrors::TypeError( + CheckErrorKind::DefineNFTBadSignature, + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), ), diff --git a/clarity/src/vm/analysis/type_checker/v2_05/tests/contracts.rs b/clarity/src/vm/analysis/type_checker/v2_05/tests/contracts.rs index 6d37d068376..6b6c5137276 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/tests/contracts.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/tests/contracts.rs @@ -19,7 +19,7 @@ use stacks_common::types::StacksEpochId; use {assert_json_diff, serde_json}; use crate::vm::analysis::contract_interface_builder::build_contract_interface; -use crate::vm::analysis::errors::CheckErrors; +use crate::vm::analysis::errors::CheckErrorKind; use crate::vm::analysis::{mem_type_check, type_check}; use crate::vm::ast::parse; use crate::vm::database::MemoryBackingStore; @@ -492,7 +492,7 @@ fn test_names_tokens_contracts_bad() { ) }) .unwrap_err(); - assert!(matches!(*err.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*err.err, CheckErrorKind::TypeError(_, _))); } #[test] @@ -534,7 +534,7 @@ fn test_bad_map_usage() { for contract in tests.iter() { let err = mem_type_check(contract, ClarityVersion::Clarity1, StacksEpochId::Epoch2_05) .unwrap_err(); - assert!(matches!(*err.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*err.err, CheckErrorKind::TypeError(_, _))); } assert!(matches!( @@ -545,7 +545,7 @@ fn test_bad_map_usage() { ) .unwrap_err() .err, - CheckErrors::UnionTypeError(_, _) + CheckErrorKind::UnionTypeError(_, _) )); } @@ -663,7 +663,10 @@ fn test_expects() { ) .unwrap_err(); eprintln!("unmatched_return_types returned check error: {err}"); - assert!(matches!(*err.err, CheckErrors::ReturnTypesMustMatch(_, _))); + assert!(matches!( + *err.err, + CheckErrorKind::ReturnTypesMustMatch(_, _) + )); } let err = mem_type_check( @@ -673,7 +676,10 @@ fn test_expects() { ) .unwrap_err(); eprintln!("bad_default_types returned check error: {err}"); - assert!(matches!(*err.err, CheckErrors::DefaultTypesMustMatch(_, _))); + assert!(matches!( + *err.err, + CheckErrorKind::DefaultTypesMustMatch(_, _) + )); let err = mem_type_check( notype_response_type, @@ -684,7 +690,7 @@ fn test_expects() { eprintln!("notype_response_type returned check error: {err}"); assert!(matches!( *err.err, - CheckErrors::CouldNotDetermineResponseErrType + CheckErrorKind::CouldNotDetermineResponseErrType )); let err = mem_type_check( @@ -696,6 +702,6 @@ fn test_expects() { eprintln!("notype_response_type_2 returned check error: {err}"); assert!(matches!( *err.err, - CheckErrors::CouldNotDetermineResponseOkType + CheckErrorKind::CouldNotDetermineResponseOkType )); } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs index 99fd0191cea..ffb6cc9d25b 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs @@ -16,10 +16,10 @@ use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::{CheckError, CheckErrors, SyntaxBindingError}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError, SyntaxBindingError}; use crate::vm::analysis::mem_type_check; use crate::vm::ast::build_ast; -use crate::vm::ast::errors::ParseErrors; +use crate::vm::ast::errors::ParseErrorKind; use crate::vm::types::SequenceSubtype::*; use crate::vm::types::StringSubtype::*; use crate::vm::types::TypeSignature::{BoolType, IntType, PrincipalType, UIntType}; @@ -31,7 +31,7 @@ use crate::vm::ClarityVersion; mod assets; mod contracts; -fn type_check_helper(exp: &str) -> Result { +fn type_check_helper(exp: &str) -> Result { mem_type_check(exp, ClarityVersion::Clarity1, StacksEpochId::Epoch2_05) .map(|(type_sig_opt, _)| type_sig_opt.unwrap()) } @@ -70,10 +70,10 @@ fn test_get_block_info() { "(get-block-info? time)", ]; let bad_expected = [ - CheckErrors::NoSuchBlockInfoProperty("none".to_string()), - CheckErrors::TypeError(Box::new(UIntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::RequiresAtLeastArguments(2, 1), + CheckErrorKind::NoSuchBlockInfoProperty("none".to_string()), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::RequiresAtLeastArguments(2, 1), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -114,10 +114,10 @@ fn test_define_trait() { "(define-trait)", ]; let bad_expected = [ - CheckErrors::InvalidTypeDescription, - CheckErrors::DefineTraitBadSignature, - CheckErrors::DefineTraitBadSignature, - CheckErrors::InvalidTypeDescription, + CheckErrorKind::InvalidTypeDescription, + CheckErrorKind::DefineTraitBadSignature, + CheckErrorKind::DefineTraitBadSignature, + CheckErrorKind::InvalidTypeDescription, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -126,8 +126,8 @@ fn test_define_trait() { let bad = ["(define-trait trait-1)", "(define-trait)"]; let bad_expected = [ - ParseErrors::DefineTraitBadSignature, - ParseErrors::DefineTraitBadSignature, + ParseErrorKind::DefineTraitBadSignature, + ParseErrorKind::DefineTraitBadSignature, ]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -153,10 +153,10 @@ fn test_use_trait() { "(use-trait)", ]; let bad_expected = [ - ParseErrors::ImportTraitBadSignature, - ParseErrors::ImportTraitBadSignature, - ParseErrors::ImportTraitBadSignature, - ParseErrors::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, ]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -177,8 +177,8 @@ fn test_use_trait() { fn test_impl_trait() { let bad = ["(impl-trait trait-1)", "(impl-trait)"]; let bad_expected = [ - ParseErrors::ImplTraitBadSignature, - ParseErrors::ImplTraitBadSignature, + ParseErrorKind::ImplTraitBadSignature, + ParseErrorKind::ImplTraitBadSignature, ]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -217,16 +217,16 @@ fn test_stx_ops() { "(stx-get-balance 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)" ]; let bad_expected = [ - CheckErrors::IncorrectArgumentCount(3, 2), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(BoolType)), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(BoolType)), - CheckErrors::IncorrectArgumentCount(2, 3), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(BoolType)), - CheckErrors::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + CheckErrorKind::IncorrectArgumentCount(1, 2), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -292,7 +292,7 @@ fn test_destructuring_opts() { let bad = [ ( "(unwrap-err! (some 2) 2)", - CheckErrors::ExpectedResponseType(Box::new(TypeSignature::from_string( + CheckErrorKind::ExpectedResponseType(Box::new(TypeSignature::from_string( "(optional int)", ClarityVersion::Clarity1, StacksEpochId::Epoch2_05, @@ -300,88 +300,90 @@ fn test_destructuring_opts() { ), ( "(unwrap! (err 3) 2)", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-err-panic (ok 3))", - CheckErrors::CouldNotDetermineResponseErrType, + CheckErrorKind::CouldNotDetermineResponseErrType, ), ( "(unwrap-panic none)", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(define-private (foo) (if (> 1 0) none none)) (unwrap-panic (foo))", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-panic (err 3))", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(match none inner-value (/ 1 0) (+ 1 8))", - CheckErrors::CouldNotDetermineMatchTypes, + CheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (ok 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrors::CouldNotDetermineMatchTypes, + CheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (err 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrors::CouldNotDetermineMatchTypes, + CheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(define-private (foo) (if (> 1 0) (ok 1) (err u8))) (match (foo) ok-val (+ 1 ok-val) err-val (/ err-val u0))", - CheckErrors::MatchArmsMustMatch( + CheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value) (> 1 28))", - CheckErrors::MatchArmsMustMatch( + CheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::BoolType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value))", - CheckErrors::BadMatchOptionSyntax(Box::new(CheckErrors::IncorrectArgumentCount(4, 3))), + CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::IncorrectArgumentCount( + 4, 3, + ))), ), ( "(match (ok 1) inner-value (+ 1 inner-value))", - CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::IncorrectArgumentCount( - 5, 3, - ))), + CheckErrorKind::BadMatchResponseSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(5, 3), + )), ), ( "(match (ok 1) 1 (+ 1 1) err-val (+ 2 err-val))", - CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)), + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), ), ( "(match (ok 1) ok-val (+ 1 1) (+ 3 4) (+ 2 err-val))", - CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)), + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), ), ( "(match (some 1) 2 (+ 1 1) (+ 3 4))", - CheckErrors::BadMatchOptionSyntax(Box::new(CheckErrors::ExpectedName)), + CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)), ), - ("(match)", CheckErrors::RequiresAtLeastArguments(1, 0)), + ("(match)", CheckErrorKind::RequiresAtLeastArguments(1, 0)), ( "(match 1 ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrors::BadMatchInput(Box::new(TypeSignature::IntType)), + CheckErrorKind::BadMatchInput(Box::new(TypeSignature::IntType)), ), ( "(default-to 3 5)", - CheckErrors::ExpectedOptionalType(Box::new(TypeSignature::IntType)), + CheckErrorKind::ExpectedOptionalType(Box::new(TypeSignature::IntType)), ), ( "(define-private (foo (x int)) (match (some 3) x (+ x 2) 5))", - CheckErrors::NameAlreadyUsed("x".to_string()), + CheckErrorKind::NameAlreadyUsed("x".to_string()), ), ( "(define-private (t1 (x uint)) (if (> x u1) (ok x) (err false))) @@ -389,7 +391,7 @@ fn test_destructuring_opts() { (if (> x u4) (err u3) (ok (+ u2 (try! (t1 x))))))", - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -404,7 +406,7 @@ fn test_destructuring_opts() { "(define-private (t1 (x uint)) (if (> x u1) (ok x) (err false))) (define-private (t2 (x uint)) (> u2 (try! (t1 x))))", - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -414,18 +416,24 @@ fn test_destructuring_opts() { ), ( "(try! (ok 3))", - CheckErrors::CouldNotDetermineResponseErrType, + CheckErrorKind::CouldNotDetermineResponseErrType, + ), + ( + "(try! none)", + CheckErrorKind::CouldNotDetermineResponseOkType, ), - ("(try! none)", CheckErrors::CouldNotDetermineResponseOkType), ( "(try! (err 3))", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(try! 3)", - CheckErrors::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), + CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), + ), + ( + "(try! (ok 3) 4)", + CheckErrorKind::IncorrectArgumentCount(1, 2), ), - ("(try! (ok 3) 4)", CheckErrors::IncorrectArgumentCount(1, 2)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -452,11 +460,11 @@ fn test_at_block() { let bad = [ ( "(at-block (sha512 u0) u1)", - CheckErrors::TypeError(Box::new(BUFF_32.clone()), Box::new(BUFF_64.clone())), + CheckErrorKind::TypeError(Box::new(BUFF_32.clone()), Box::new(BUFF_64.clone())), ), ( "(at-block (sha256 u0) u1 u2)", - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), ), ]; @@ -476,7 +484,7 @@ fn test_at_block() { fn test_trait_reference_unknown() { let bad = [( "(+ 1 )", - ParseErrors::TraitReferenceUnknown("kvstore".to_string()), + ParseErrorKind::TraitReferenceUnknown("kvstore".to_string()), )]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -497,7 +505,7 @@ fn test_trait_reference_unknown() { fn test_unexpected_use_of_field_or_trait_reference() { let bad = [( "(+ 1 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.contract.field)", - CheckErrors::UnexpectedTraitOrFieldReference, + CheckErrorKind::UnexpectedTraitOrFieldReference, )]; for (bad_test, expected) in bad.iter() { @@ -522,12 +530,12 @@ fn test_simple_arithmetic_checks() { "(and (or true false) (+ 1 2 3))", ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::RequiresAtLeastArguments(1, 0), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::UndefinedVariable("x".to_string()), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::RequiresAtLeastArguments(1, 0), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::UndefinedVariable("x".to_string()), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -588,14 +596,14 @@ fn test_simple_hash_checks() { for bad_test in bad_types.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrors::UnionTypeError(_, _) + CheckErrorKind::UnionTypeError(_, _) )); } for bad_test in invalid_args.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrors::IncorrectArgumentCount(_, _) + CheckErrorKind::IncorrectArgumentCount(_, _) )); } } @@ -618,10 +626,10 @@ fn test_simple_ifs() { ]; let bad_expected = [ - CheckErrors::IfArmsMustMatch(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IfArmsMustMatch(Box::new(ascii_type(1)), Box::new(BoolType)), - CheckErrors::IncorrectArgumentCount(3, 0), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IfArmsMustMatch(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IfArmsMustMatch(Box::new(ascii_type(1)), Box::new(BoolType)), + CheckErrorKind::IncorrectArgumentCount(3, 0), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -654,9 +662,9 @@ fn test_simple_lets() { ]; let bad_expected = [ - CheckErrors::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), - CheckErrors::TypeError( + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), + CheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), @@ -711,26 +719,26 @@ fn test_index_of() { ]; let bad_expected = [ - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrors::TypeError( + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_buffer().unwrap()), Box::new(TypeSignature::min_string_ascii().unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_string_utf8().unwrap()), Box::new(TypeSignature::min_string_ascii().unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_string_ascii().unwrap()), Box::new(TypeSignature::min_string_utf8().unwrap()), ), - CheckErrors::CouldNotDetermineType, - CheckErrors::CouldNotDetermineType, - CheckErrors::CouldNotDetermineType, + CheckErrorKind::CouldNotDetermineType, + CheckErrorKind::CouldNotDetermineType, + CheckErrorKind::CouldNotDetermineType, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -759,11 +767,11 @@ fn test_element_at() { let bad = ["(element-at (list 1 2 3 4 5) 100)", "(element-at 3 u100)"]; let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -795,12 +803,12 @@ fn test_eqs() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::TypeError( Box::new(TypeSignature::list_of(IntType, 1).unwrap()), Box::new(IntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(optional bool)", ClarityVersion::Clarity1, @@ -842,9 +850,9 @@ fn test_asserts() { ]; let bad_expected = [ - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -908,23 +916,23 @@ fn test_lists() { "(map + (list 1 2 3 4 5) (list true true true true true))", ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(buff_type(20))), - CheckErrors::TypeError(Box::new(BoolType), Box::new(buff_type(20))), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 3), - CheckErrors::UnknownFunction("ynot".to_string()), - CheckErrors::IllegalOrUnknownFunctionApplication("if".to_string()), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), - CheckErrors::ExpectedSequence(Box::new(UIntType)), - CheckErrors::ExpectedSequence(Box::new(IntType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), + CheckErrorKind::UnknownFunction("ynot".to_string()), + CheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + CheckErrorKind::ExpectedSequence(Box::new(UIntType)), + CheckErrorKind::ExpectedSequence(Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -965,20 +973,20 @@ fn test_buff() { "(len 1)", ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(buff_type(20))), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 3), - CheckErrors::UnknownFunction("ynot".to_string()), - CheckErrors::IllegalOrUnknownFunctionApplication("if".to_string()), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), - CheckErrors::ExpectedSequence(Box::new(UIntType)), - CheckErrors::ExpectedSequence(Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), + CheckErrorKind::UnknownFunction("ynot".to_string()), + CheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + CheckErrorKind::ExpectedSequence(Box::new(UIntType)), + CheckErrorKind::ExpectedSequence(Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1053,9 +1061,9 @@ fn test_native_as_max_len() { "(as-max-len? 0x01 u1048577)", ]; let bad_expected = [ - CheckErrors::ValueTooLarge, - CheckErrors::ValueTooLarge, - CheckErrors::ValueTooLarge, + CheckErrorKind::ValueTooLarge, + CheckErrorKind::ValueTooLarge, + CheckErrorKind::ValueTooLarge, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1099,9 +1107,9 @@ fn test_native_append() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 1), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1127,9 +1135,9 @@ fn test_native_concat() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 1), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1225,8 +1233,8 @@ fn test_tuples() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1256,7 +1264,7 @@ fn test_empty_tuple_should_fail() { ) .unwrap_err() .err, - CheckErrors::EmptyTuplesNotAllowed + CheckErrorKind::EmptyTuplesNotAllowed ); } @@ -1352,9 +1360,9 @@ fn test_simple_uints() { let bad = ["(> u1 1)", "(to-uint true)", "(to-int false)"]; let bad_expected = [ - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1415,7 +1423,7 @@ fn test_response_inference() { ]; let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(response bool int)", ClarityVersion::Clarity1, @@ -1423,8 +1431,8 @@ fn test_response_inference() { )), Box::new(BoolType), ), - CheckErrors::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::CouldNotDetermineResponseOkType, ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1562,7 +1570,7 @@ fn test_options() { .unwrap_err() .err { - CheckErrors::TypeError(t1, t2) => { + CheckErrorKind::TypeError(t1, t2) => { *t1 == TypeSignature::from_string( "(optional bool)", ClarityVersion::Clarity1, @@ -1714,7 +1722,7 @@ fn test_missing_value_on_declaration_should_fail() { .unwrap_err(); assert!(matches!( *res.err, - CheckErrors::IncorrectArgumentCount(_, _) + CheckErrorKind::IncorrectArgumentCount(_, _) )); } @@ -1730,7 +1738,7 @@ fn test_mismatching_type_on_declaration_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } #[test] @@ -1751,7 +1759,7 @@ fn test_mismatching_type_on_update_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } #[test] @@ -1768,7 +1776,7 @@ fn test_direct_access_to_persisted_var_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } #[test] @@ -1788,7 +1796,7 @@ fn test_data_var_shadowed_by_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1806,7 +1814,7 @@ fn test_mutating_unknown_data_var_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NoSuchDataVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); } #[test] @@ -1822,7 +1830,7 @@ fn test_accessing_unknown_data_var_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NoSuchDataVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); } #[test] @@ -1838,7 +1846,7 @@ fn test_let_shadowed_by_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1855,7 +1863,7 @@ fn test_let_shadowed_by_nested_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1873,7 +1881,7 @@ fn test_define_constant_shadowed_by_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1890,7 +1898,7 @@ fn test_define_constant_shadowed_by_argument_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2112,7 +2120,7 @@ fn test_fetch_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -2132,7 +2140,7 @@ fn test_fetch_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -2184,7 +2192,7 @@ fn test_insert_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -2207,7 +2215,7 @@ fn test_insert_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -2257,7 +2265,7 @@ fn test_delete_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -2277,7 +2285,7 @@ fn test_delete_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -2331,7 +2339,7 @@ fn test_set_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -2354,7 +2362,7 @@ fn test_set_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -2489,7 +2497,7 @@ fn test_buff_negative_len() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert_eq!(*res.err, CheckErrors::ValueOutOfBounds); + assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); } #[test] @@ -2503,7 +2511,7 @@ fn test_string_ascii_negative_len() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert_eq!(*res.err, CheckErrors::ValueOutOfBounds); + assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); } #[test] @@ -2517,5 +2525,5 @@ fn test_string_utf8_negative_len() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert_eq!(*res.err, CheckErrors::ValueOutOfBounds); + assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); } diff --git a/clarity/src/vm/analysis/type_checker/v2_1/contexts.rs b/clarity/src/vm/analysis/type_checker/v2_1/contexts.rs index d226f33e074..7632ea305bb 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/contexts.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/contexts.rs @@ -16,7 +16,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; -use crate::vm::analysis::errors::{CheckError, CheckErrors}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError}; use crate::vm::analysis::type_checker::is_reserved_word; use crate::vm::analysis::types::ContractAnalysis; use crate::vm::representations::ClarityName; @@ -167,9 +167,11 @@ impl ContractContext { &self.contract_identifier == other } - pub fn check_name_used(&self, name: &str) -> Result<(), CheckError> { + pub fn check_name_used(&self, name: &str) -> Result<(), StaticCheckError> { if is_reserved_word(name, self.clarity_version) { - return Err(CheckError::new(CheckErrors::ReservedWord(name.to_string()))); + return Err(StaticCheckError::new(CheckErrorKind::ReservedWord( + name.to_string(), + ))); } if self.variable_types.contains_key(name) @@ -181,7 +183,7 @@ impl ContractContext { || self.traits.is_name_used(name) || self.map_types.contains_key(name) { - Err(CheckError::new(CheckErrors::NameAlreadyUsed( + Err(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( name.to_string(), ))) } else { @@ -189,7 +191,7 @@ impl ContractContext { } } - fn check_function_type(&mut self, f_name: &str) -> Result<(), CheckError> { + fn check_function_type(&mut self, f_name: &str) -> Result<(), StaticCheckError> { self.check_name_used(f_name)?; Ok(()) } @@ -206,7 +208,7 @@ impl ContractContext { &mut self, name: ClarityName, func_type: FunctionType, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_function_type(&name)?; self.public_function_types.insert(name, func_type); Ok(()) @@ -216,7 +218,7 @@ impl ContractContext { &mut self, name: ClarityName, func_type: FunctionType, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_function_type(&name)?; self.read_only_function_types.insert(name, func_type); Ok(()) @@ -226,7 +228,7 @@ impl ContractContext { &mut self, name: ClarityName, func_type: FunctionType, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_function_type(&name)?; self.private_function_types.insert(name, func_type); Ok(()) @@ -236,7 +238,7 @@ impl ContractContext { &mut self, map_name: ClarityName, map_type: (TypeSignature, TypeSignature), - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&map_name)?; self.map_types.insert(map_name, map_type); Ok(()) @@ -246,7 +248,7 @@ impl ContractContext { &mut self, const_name: ClarityName, var_type: TypeSignature, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&const_name)?; self.variable_types.insert(const_name, var_type); Ok(()) @@ -256,13 +258,13 @@ impl ContractContext { &mut self, var_name: ClarityName, var_type: TypeSignature, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&var_name)?; self.persisted_variable_types.insert(var_name, var_type); Ok(()) } - pub fn add_ft(&mut self, token_name: ClarityName) -> Result<(), CheckError> { + pub fn add_ft(&mut self, token_name: ClarityName) -> Result<(), StaticCheckError> { self.check_name_used(&token_name)?; self.fungible_tokens.insert(token_name); Ok(()) @@ -272,7 +274,7 @@ impl ContractContext { &mut self, token_name: ClarityName, token_type: TypeSignature, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.check_name_used(&token_name)?; self.non_fungible_tokens.insert(token_name, token_type); Ok(()) @@ -282,7 +284,7 @@ impl ContractContext { &mut self, trait_name: ClarityName, trait_signature: BTreeMap, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { if self.clarity_version >= ClarityVersion::Clarity3 { self.check_name_used(&trait_name)?; } @@ -300,7 +302,7 @@ impl ContractContext { alias: ClarityName, trait_id: TraitIdentifier, trait_signature: BTreeMap, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { if self.clarity_version >= ClarityVersion::Clarity3 { self.check_name_used(&alias)?; } diff --git a/clarity/src/vm/analysis/type_checker/v2_1/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/mod.rs index b3f1386a725..d70e5af87b5 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/mod.rs @@ -26,8 +26,8 @@ pub use self::natives::{SimpleNativeFunction, TypedNativeFunction}; use super::contexts::{TypeMap, TypingContext}; use super::ContractAnalysis; pub use crate::vm::analysis::errors::{ - check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckError, - CheckErrors, SyntaxBindingErrorType, + check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, + StaticCheckError, SyntaxBindingErrorType, }; use crate::vm::analysis::AnalysisDatabase; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -121,7 +121,7 @@ impl TypeChecker<'_, '_> { contract_analysis: &mut ContractAnalysis, analysis_db: &mut AnalysisDatabase, build_type_map: bool, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { let cost_track = contract_analysis.take_contract_cost_tracker(); let mut command = TypeChecker::new( epoch, @@ -161,9 +161,9 @@ pub fn compute_typecheck_cost( ) } -pub fn check_argument_len(expected: usize, args_len: usize) -> Result<(), CheckErrors> { +pub fn check_argument_len(expected: usize, args_len: usize) -> Result<(), CheckErrorKind> { if args_len != expected { - Err(CheckErrors::IncorrectArgumentCount(expected, args_len)) + Err(CheckErrorKind::IncorrectArgumentCount(expected, args_len)) } else { Ok(()) } @@ -179,7 +179,7 @@ impl FunctionType { accumulated_type: Option<&TypeSignature>, ) -> ( Option>, - Result, CheckError>, + Result, StaticCheckError>, ) { match self { // variadic stops checking cost at the first error... @@ -192,7 +192,7 @@ impl FunctionType { if !admitted { return ( cost, - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(arg_type.clone()), ) @@ -211,7 +211,7 @@ impl FunctionType { let return_type = match arg_type { TypeSignature::IntType => Ok(Some(TypeSignature::IntType)), TypeSignature::UIntType => Ok(Some(TypeSignature::UIntType)), - _ => Err(CheckErrors::UnionTypeError( + _ => Err(CheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(arg_type.clone()), ) @@ -220,10 +220,10 @@ impl FunctionType { (cost, return_type) } else { let return_type = accumulated_type - .ok_or_else(|| CheckErrors::Expects("Failed to set accumulated type for arg indices >= 1 in variadic arithmetic".into()).into()); + .ok_or_else(|| CheckErrorKind::Expects("Failed to set accumulated type for arg indices >= 1 in variadic arithmetic".into()).into()); let check_result = return_type.and_then(|return_type| { if arg_type != return_type { - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(return_type.clone()), Box::new(arg_type.clone()), ) @@ -246,7 +246,10 @@ impl FunctionType { // note: argument count will be wrong? return ( None, - Err(CheckErrors::IncorrectArgumentCount(arg_types.len(), arg_index).into()), + Err( + CheckErrorKind::IncorrectArgumentCount(arg_types.len(), arg_index) + .into(), + ), ); } (None, Ok(None)) @@ -259,7 +262,7 @@ impl FunctionType { if arg_index >= 1 { return ( None, - Err(CheckErrors::IncorrectArgumentCount(1, arg_index).into()), + Err(CheckErrorKind::IncorrectArgumentCount(1, arg_index).into()), ); } (None, Ok(None)) @@ -270,7 +273,7 @@ impl FunctionType { if arg_index >= 2 { return ( None, - Err(CheckErrors::IncorrectArgumentCount(2, arg_index).into()), + Err(CheckErrorKind::IncorrectArgumentCount(2, arg_index).into()), ); } (None, Ok(None)) @@ -283,14 +286,14 @@ impl FunctionType { accounting: &mut T, args: &[TypeSignature], clarity_version: ClarityVersion, - ) -> Result { + ) -> Result { match self { FunctionType::Variadic(expected_type, return_type) => { check_arguments_at_least(1, args)?; for found_type in args.iter() { analysis_typecheck_cost(accounting, expected_type, found_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch21, found_type)? { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -308,7 +311,7 @@ impl FunctionType { { analysis_typecheck_cost(accounting, expected_type, found_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch21, found_type)? { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -327,7 +330,7 @@ impl FunctionType { } } Err( - CheckErrors::UnionTypeError(arg_types.clone(), Box::new(found_type.clone())) + CheckErrorKind::UnionTypeError(arg_types.clone(), Box::new(found_type.clone())) .into(), ) } @@ -356,12 +359,12 @@ impl FunctionType { } let (first, rest) = args .split_first() - .ok_or(CheckErrors::RequiresAtLeastArguments(1, args.len()))?; + .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, args.len()))?; analysis_typecheck_cost(accounting, &TypeSignature::IntType, first)?; let return_type = match first { TypeSignature::IntType => Ok(TypeSignature::IntType), TypeSignature::UIntType => Ok(TypeSignature::UIntType), - _ => Err(CheckErrors::UnionTypeError( + _ => Err(CheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(first.clone()), )), @@ -369,7 +372,7 @@ impl FunctionType { for found_type in rest.iter() { analysis_typecheck_cost(accounting, &TypeSignature::IntType, found_type)?; if found_type != &return_type { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(return_type.clone()), Box::new(found_type.clone()), ) @@ -403,7 +406,7 @@ impl FunctionType { }; if !first_type_supported { - return Err(CheckErrors::UnionTypeError( + return Err(CheckErrorKind::UnionTypeError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -445,7 +448,7 @@ impl FunctionType { }; if !pair_of_types_matches { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(first.clone()), Box::new(second.clone()), ) @@ -466,7 +469,7 @@ impl FunctionType { value: &Value, depth: u8, clarity_version: ClarityVersion, - ) -> Result { + ) -> Result { if clarity_version >= ClarityVersion::Clarity2 { // In Clarity2, we recurse into complex data types self.clarity2_principal_to_callable_type(value, depth) @@ -488,9 +491,9 @@ impl FunctionType { &self, value: &Value, depth: u8, - ) -> Result { + ) -> Result { if depth > MAX_TYPE_DEPTH { - return Err(CheckErrors::TypeSignatureTooDeep.into()); + return Err(CheckErrorKind::TypeSignatureTooDeep.into()); } Ok(match value { @@ -557,10 +560,10 @@ impl FunctionType { db: &mut AnalysisDatabase, clarity_version: ClarityVersion, func_args: &[Value], - ) -> Result { + ) -> Result { let (expected_args, returns) = match self { FunctionType::Fixed(FixedFunction { args, returns }) => (args, returns), - _ => return Err(CheckErrors::Expects("Unexpected function type".into()).into()), + _ => return Err(CheckErrorKind::Expects("Unexpected function type".into()).into()), }; check_argument_count(expected_args.len(), func_args)?; @@ -574,7 +577,7 @@ impl FunctionType { let contract_to_check = db .load_contract(contract, &StacksEpochId::Epoch21)? .ok_or_else(|| { - CheckErrors::NoSuchContract(contract.name.to_string()) + CheckErrorKind::NoSuchContract(contract.name.to_string()) })?; let trait_definition = db .get_defined_trait( @@ -582,8 +585,8 @@ impl FunctionType { &trait_id.name, &StacksEpochId::Epoch21, ) - .map_err(|_| CheckErrors::Expects("Failed to get trait".into()))? - .ok_or(CheckErrors::NoSuchContract( + .map_err(|_| CheckErrorKind::Expects("Failed to get trait".into()))? + .ok_or(CheckErrorKind::NoSuchContract( trait_id.contract_identifier.to_string(), ))?; contract_to_check.check_trait_compliance( @@ -595,7 +598,7 @@ impl FunctionType { (expected_type, value) => { if !expected_type.admits(&StacksEpochId::Epoch21, value)? { let actual_type = TypeSignature::type_of(value)?; - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -629,12 +632,12 @@ fn check_function_arg_signature( cost_tracker: &mut T, expected_sig: &FunctionArgSignature, actual_type: &TypeSignature, -) -> Result<(), CheckError> { +) -> Result<(), StaticCheckError> { match expected_sig { FunctionArgSignature::Single(expected_type) => { analysis_typecheck_cost(cost_tracker, expected_type, actual_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch21, actual_type)? { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -651,7 +654,7 @@ fn check_function_arg_signature( } } if !admitted { - return Err(CheckErrors::UnionTypeError( + return Err(CheckErrorKind::UnionTypeError( expected_types.clone(), Box::new(actual_type.clone()), ) @@ -717,7 +720,7 @@ pub fn clarity2_trait_check_trait_compliance( expected_trait_identifier: &TraitIdentifier, expected_trait: &BTreeMap, tracker: &mut T, -) -> Result<(), CheckError> { +) -> Result<(), StaticCheckError> { // Shortcut for the simple case when the two traits are the same. if actual_trait_identifier == expected_trait_identifier { return Ok(()); @@ -732,14 +735,14 @@ pub fn clarity2_trait_check_trait_compliance( func, tracker, ) { - return Err(CheckErrors::IncompatibleTrait( + return Err(CheckErrorKind::IncompatibleTrait( Box::new(expected_trait_identifier.clone()), Box::new(actual_trait_identifier.clone()), ) .into()); } } else { - return Err(CheckErrors::IncompatibleTrait( + return Err(CheckErrorKind::IncompatibleTrait( Box::new(expected_trait_identifier.clone()), Box::new(actual_trait_identifier.clone()), ) @@ -758,9 +761,9 @@ fn clarity2_inner_type_check_type( expected_type: &TypeSignature, depth: u8, tracker: &mut T, -) -> Result { +) -> Result { if depth > MAX_TYPE_DEPTH { - return Err(CheckErrors::TypeSignatureTooDeep.into()); + return Err(CheckErrorKind::TypeSignatureTooDeep.into()); } // Recurse into values to check embedded traits properly @@ -813,7 +816,7 @@ fn clarity2_inner_type_check_type( tracker, )?; } else { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -825,7 +828,7 @@ fn clarity2_inner_type_check_type( TypeSignature::TupleType(expected_tuple_type), ) => { if expected_tuple_type.get_type_map().len() != atom_tuple_type.get_type_map().len() { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -845,7 +848,7 @@ fn clarity2_inner_type_check_type( )?; } None => { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -891,7 +894,9 @@ fn clarity2_inner_type_check_type( } None => { runtime_cost(ClarityCostFunction::AnalysisFetchContractEntry, tracker, 1)?; - return Err(CheckErrors::NoSuchContract(contract_identifier.to_string()).into()); + return Err( + CheckErrorKind::NoSuchContract(contract_identifier.to_string()).into(), + ); } }; let expected_trait = @@ -921,7 +926,7 @@ fn clarity2_inner_type_check_type( (TypeSignature::NoType, _) => (), (_, _) => { if !expected_type.admits_type(&StacksEpochId::Epoch21, actual_type)? { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -937,13 +942,13 @@ fn clarity2_lookup_trait( contract_context: Option<&ContractContext>, trait_id: &TraitIdentifier, tracker: &mut T, -) -> Result, CheckError> { +) -> Result, StaticCheckError> { if let Some(contract_context) = contract_context { // If the trait is from this contract, then it must be in the context or it doesn't exist. if contract_context.is_contract(&trait_id.contract_identifier) { return Ok(contract_context .get_trait(trait_id) - .ok_or(CheckErrors::NoSuchTrait( + .ok_or(CheckErrorKind::NoSuchTrait( trait_id.contract_identifier.to_string(), trait_id.name.to_string(), ))? @@ -970,7 +975,7 @@ fn clarity2_lookup_trait( } Ok(None) => { runtime_cost(ClarityCostFunction::AnalysisUseTraitEntry, tracker, 1)?; - Err(CheckErrors::NoSuchTrait( + Err(CheckErrorKind::NoSuchTrait( trait_id.contract_identifier.to_string(), trait_id.name.to_string(), ) @@ -985,7 +990,7 @@ fn clarity2_lookup_trait( fn trait_type_size( trait_sig: &BTreeMap, -) -> Result { +) -> Result { let mut total_size = 0; for (_func_name, value) in trait_sig.iter() { total_size = total_size.cost_overflow_add(value.total_type_size()?)?; @@ -993,7 +998,7 @@ fn trait_type_size( Ok(total_size) } -fn contract_analysis_size(contract: &ContractAnalysis) -> Result { +fn contract_analysis_size(contract: &ContractAnalysis) -> Result { let mut total_size = contract.public_function_types.len() as u64; total_size = total_size.cost_overflow_add(contract.read_only_function_types.len() as u64)?; Ok(total_size) @@ -1002,20 +1007,20 @@ fn contract_analysis_size(contract: &ContractAnalysis) -> Result Result, CheckError> { +) -> Result, StaticCheckError> { if let Some(variable) = NativeVariables::lookup_by_name_at_version(variable_name, version) { use crate::vm::variables::NativeVariables::*; let var_type = match variable { TxSender => TypeSignature::PrincipalType, TxSponsor => TypeSignature::new_option(TypeSignature::PrincipalType) - .map_err(|_| CheckErrors::Expects("Bad construction".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad construction".into()))?, ContractCaller => TypeSignature::PrincipalType, BlockHeight => TypeSignature::UIntType, StacksBlockHeight => TypeSignature::UIntType, TenureHeight => TypeSignature::UIntType, BurnBlockHeight => TypeSignature::UIntType, NativeNone => TypeSignature::new_option(no_type()) - .map_err(|_| CheckErrors::Expects("Bad construction".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad construction".into()))?, NativeTrue => TypeSignature::BoolType, NativeFalse => TypeSignature::BoolType, TotalLiquidMicroSTX => TypeSignature::UIntType, @@ -1065,7 +1070,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { self.cost_track } - pub fn track_return_type(&mut self, return_type: TypeSignature) -> Result<(), CheckError> { + pub fn track_return_type( + &mut self, + return_type: TypeSignature, + ) -> Result<(), StaticCheckError> { runtime_cost( ClarityCostFunction::AnalysisTypeCheck, self, @@ -1081,7 +1089,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new(expected_type), Box::new(return_type), ) @@ -1100,7 +1108,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } } - pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), CheckError> { + pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), StaticCheckError> { // charge for the eventual storage cost of the analysis -- // it is linear in the size of the AST. let mut size: u64 = 0; @@ -1112,7 +1120,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } Err(e) => Err(e), })? - .ok_or_else(|| CheckErrors::Expects("Expected a depth result".into()))?; + .ok_or_else(|| CheckErrorKind::Expects("Expected a depth result".into()))?; } runtime_cost(ClarityCostFunction::AnalysisStorage, self, size)?; @@ -1141,7 +1149,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { expr: &SymbolicExpression, context: &TypingContext, expected_type: &TypeSignature, - ) -> Result { + ) -> Result { // Clarity 2 allows traits embedded in compound types and allows // implicit casts between compatible traits, while Clarity 1 does not. if self.clarity_version >= ClarityVersion::Clarity2 { @@ -1162,7 +1170,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expr: &SymbolicExpression, context: &TypingContext, - ) -> Result { + ) -> Result { runtime_cost(ClarityCostFunction::AnalysisVisit, self, 0)?; let mut result = self.inner_type_check(expr, context); @@ -1180,14 +1188,14 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, args: &[SymbolicExpression], context: &TypingContext, - ) -> Result { + ) -> Result { let mut last_return = None; let mut return_failure = Ok(()); for ix in 0..args.len() { let type_return = self.type_check(&args[ix], context)?; if ix + 1 < args.len() { if type_return.is_response_type() { - return_failure = Err(CheckErrors::UncheckedIntermediaryResponses); + return_failure = Err(CheckErrorKind::UncheckedIntermediaryResponses); } } else { last_return = Some(type_return); @@ -1195,7 +1203,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } let last_return = last_return - .ok_or_else(|| CheckError::new(CheckErrors::CheckerImplementationFailure))?; + .ok_or_else(|| StaticCheckError::new(CheckErrorKind::CheckerImplementationFailure))?; return_failure?; Ok(last_return) @@ -1205,7 +1213,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, args: &[SymbolicExpression], context: &TypingContext, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { let mut result = Vec::with_capacity(args.len()); for arg in args.iter() { // don't use map here, since type_check has side-effects. @@ -1221,7 +1229,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { context: &TypingContext, epoch: StacksEpochId, clarity_version: ClarityVersion, - ) -> Result { + ) -> Result { if epoch <= StacksEpochId::Epoch2_05 { let typed_args = self.type_check_all(args, context)?; return func_type.check_args(self, &typed_args, epoch, clarity_version); @@ -1258,9 +1266,9 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } } if let Err(mut check_error) = check_result { - if let CheckErrors::IncorrectArgumentCount(expected, _actual) = *check_error.err { + if let CheckErrorKind::IncorrectArgumentCount(expected, _actual) = *check_error.err { check_error.err = - Box::new(CheckErrors::IncorrectArgumentCount(expected, args.len())); + Box::new(CheckErrorKind::IncorrectArgumentCount(expected, args.len())); check_error.diagnostic = Diagnostic::err(check_error.err.as_ref()); } // accumulate the checking costs @@ -1287,14 +1295,14 @@ impl<'a, 'b> TypeChecker<'a, 'b> { signature: &[SymbolicExpression], body: &SymbolicExpression, context: &TypingContext, - ) -> Result<(ClarityName, FixedFunction), CheckError> { + ) -> Result<(ClarityName, FixedFunction), StaticCheckError> { let (function_name, args) = signature .split_first() - .ok_or(CheckErrors::RequiresAtLeastArguments(1, 0))?; + .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, 0))?; let function_name = function_name .match_atom() - .ok_or(CheckErrors::BadFunctionName)?; - let args = parse_name_type_pairs::<(), CheckError>( + .ok_or(CheckErrorKind::BadFunctionName)?; + let args = parse_name_type_pairs::<(), StaticCheckError>( StacksEpochId::Epoch21, args, SyntaxBindingErrorType::Eval, @@ -1302,7 +1310,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { )?; if self.function_return_tracker.is_some() { - return Err(CheckErrors::Expects( + return Err(CheckErrorKind::Expects( "Interpreter error: Previous function define left dirty typecheck state.".into(), ) .into()); @@ -1358,7 +1366,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new(expected.clone()), Box::new(return_type), ) @@ -1392,16 +1400,16 @@ impl<'a, 'b> TypeChecker<'a, 'b> { map_name: &ClarityName, key_type: &SymbolicExpression, value_type: &SymbolicExpression, - ) -> Result<(ClarityName, (TypeSignature, TypeSignature)), CheckError> { + ) -> Result<(ClarityName, (TypeSignature, TypeSignature)), StaticCheckError> { self.type_map.set_type(key_type, no_type())?; self.type_map.set_type(value_type, no_type())?; // should we set the type of the subexpressions of the signature to no-type as well? let key_type = TypeSignature::parse_type_repr(StacksEpochId::Epoch21, key_type, &mut ()) - .map_err(|_| CheckErrors::BadMapTypeDefinition)?; + .map_err(|_| CheckErrorKind::BadMapTypeDefinition)?; let value_type = TypeSignature::parse_type_repr(StacksEpochId::Epoch21, value_type, &mut ()) - .map_err(|_| CheckErrors::BadMapTypeDefinition)?; + .map_err(|_| CheckErrorKind::BadMapTypeDefinition)?; Ok((map_name.clone(), (key_type, value_type))) } @@ -1412,7 +1420,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { function: &str, args: &[SymbolicExpression], context: &TypingContext, - ) -> Option> { + ) -> Option> { if let Some(ref native_function) = NativeFunctions::lookup_by_name_at_version(function, &self.clarity_version) { @@ -1430,22 +1438,22 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expression: &[SymbolicExpression], context: &TypingContext, - ) -> Result { + ) -> Result { let (function_name, args) = expression .split_first() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; self.type_map.set_type(function_name, no_type())?; let function_name = function_name .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; if let Some(type_result) = self.try_native_function_check(function_name, args, context) { type_result } else { let function = match self.get_function_type(function_name) { Some(FunctionType::Fixed(function)) => Ok(function), - _ => Err(CheckErrors::UnknownFunction(function_name.to_string())), + _ => Err(CheckErrorKind::UnknownFunction(function_name.to_string())), }?; for (expected_type, found_type) in function.args.iter().map(|x| &x.signature).zip(args) @@ -1461,7 +1469,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, name: &str, context: &TypingContext, - ) -> Result { + ) -> Result { runtime_cost(ClarityCostFunction::AnalysisLookupVariableConst, self, 0)?; if let Some(type_result) = type_reserved_variable(name, &self.clarity_version)? { @@ -1477,7 +1485,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { // be undefined. This early error prevents a cost function error // due to `context.depth` being 0. if context.depth == 0 { - return Err(CheckErrors::UndefinedVariable(name.to_string()).into()); + return Err(CheckErrorKind::UndefinedVariable(name.to_string()).into()); } runtime_cost( @@ -1489,7 +1497,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { if let Some(type_result) = context.lookup_variable_type(name) { Ok(type_result.clone()) } else { - Err(CheckErrors::UndefinedVariable(name.to_string()).into()) + Err(CheckErrorKind::UndefinedVariable(name.to_string()).into()) } } } @@ -1499,7 +1507,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { expr: &SymbolicExpression, context: &TypingContext, expected_type: &TypeSignature, - ) -> Result { + ) -> Result { if let ( LiteralValue(Value::Principal(PrincipalData::Contract(ref contract_identifier))), TypeSignature::CallableType(CallableSubtype::Trait(trait_identifier)), @@ -1508,7 +1516,9 @@ impl<'a, 'b> TypeChecker<'a, 'b> { let contract_to_check = self .db .load_contract(contract_identifier, &StacksEpochId::Epoch21)? - .ok_or(CheckErrors::NoSuchContract(contract_identifier.to_string()))?; + .ok_or(CheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ))?; let contract_defining_trait = self .db @@ -1516,13 +1526,13 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &trait_identifier.contract_identifier, &StacksEpochId::Epoch21, )? - .ok_or(CheckErrors::NoSuchContract( + .ok_or(CheckErrorKind::NoSuchContract( trait_identifier.contract_identifier.to_string(), ))?; let trait_definition = contract_defining_trait .get_defined_trait(&trait_identifier.name) - .ok_or(CheckErrors::NoSuchTrait( + .ok_or(CheckErrorKind::NoSuchTrait( trait_identifier.contract_identifier.to_string(), trait_identifier.name.to_string(), ))?; @@ -1539,7 +1549,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { analysis_typecheck_cost(self, expected_type, &actual_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch21, &actual_type)? { - let mut err: CheckError = CheckErrors::TypeError( + let mut err: StaticCheckError = CheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -1556,14 +1566,14 @@ impl<'a, 'b> TypeChecker<'a, 'b> { expr: &SymbolicExpression, context: &TypingContext, expected_type: &TypeSignature, - ) -> Result { + ) -> Result { let mut expr_type = match expr.expr { AtomValue(ref value) => TypeSignature::type_of(value)?, LiteralValue(ref value) => TypeSignature::literal_type_of(value)?, Atom(ref name) => self.lookup_variable(name, context)?, List(ref expression) => self.type_check_function_application(expression, context)?, TraitReference(_, _) | Field(_) => { - return Err(CheckErrors::UnexpectedTraitOrFieldReference.into()); + return Err(CheckErrorKind::UnexpectedTraitOrFieldReference.into()); } }; @@ -1594,14 +1604,14 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expr: &SymbolicExpression, context: &TypingContext, - ) -> Result { + ) -> Result { let expr_type = match expr.expr { AtomValue(ref value) => TypeSignature::type_of(value)?, LiteralValue(ref value) => TypeSignature::literal_type_of(value)?, Atom(ref name) => self.lookup_variable(name, context)?, List(ref expression) => self.type_check_function_application(expression, context)?, TraitReference(_, _) | Field(_) => { - return Err(CheckErrors::UnexpectedTraitOrFieldReference.into()); + return Err(CheckErrorKind::UnexpectedTraitOrFieldReference.into()); } }; @@ -1619,7 +1629,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { var_name: &ClarityName, var_type: &SymbolicExpression, context: &mut TypingContext, - ) -> Result<(ClarityName, TypeSignature), CheckError> { + ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let var_type = self.type_check(var_type, context)?; Ok((var_name.clone(), var_type)) } @@ -1630,10 +1640,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { var_type: &SymbolicExpression, initial: &SymbolicExpression, context: &mut TypingContext, - ) -> Result<(ClarityName, TypeSignature), CheckError> { + ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let expected_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch21, var_type, &mut ()) - .map_err(|_e| CheckErrors::DefineVariableBadSignature)?; + .map_err(|_e| CheckErrorKind::DefineVariableBadSignature)?; self.type_check_expects(initial, context, &expected_type)?; @@ -1645,7 +1655,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { token_name: &ClarityName, bound: Option<&SymbolicExpression>, context: &mut TypingContext, - ) -> Result { + ) -> Result { if let Some(bound) = bound { self.type_check_expects(bound, context, &TypeSignature::UIntType)?; } @@ -1658,10 +1668,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { asset_name: &ClarityName, nft_type: &SymbolicExpression, _context: &mut TypingContext, - ) -> Result<(ClarityName, TypeSignature), CheckError> { + ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let asset_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch21, nft_type, &mut ()) - .map_err(|_| CheckErrors::DefineNFTBadSignature)?; + .map_err(|_| CheckErrorKind::DefineNFTBadSignature)?; Ok((asset_name.clone(), asset_type)) } @@ -1671,7 +1681,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { trait_name: &ClarityName, function_types: &[SymbolicExpression], _context: &mut TypingContext, - ) -> Result<(ClarityName, BTreeMap), CheckError> { + ) -> Result<(ClarityName, BTreeMap), StaticCheckError> { let trait_signature = TypeSignature::parse_trait_type_repr( function_types, &mut (), @@ -1687,7 +1697,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &mut self, expression: &SymbolicExpression, context: &mut TypingContext, - ) -> Result, CheckError> { + ) -> Result, StaticCheckError> { if let Some(define_type) = DefineFunctionsParsed::try_parse(expression)? { match define_type { DefineFunctionsParsed::Constant { name, value } => { @@ -1736,7 +1746,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { .add_public_function_type(f_name, FunctionType::Fixed(f_type))?; return Ok(Some(())); } else { - return Err(CheckErrors::PublicFunctionMustReturnResponse(Box::new( + return Err(CheckErrorKind::PublicFunctionMustReturnResponse(Box::new( f_type.returns, )) .into()); @@ -1879,7 +1889,9 @@ impl<'a, 'b> TypeChecker<'a, 'b> { None => { // still had to do a db read, even if it didn't exist! runtime_cost(ClarityCostFunction::AnalysisUseTraitEntry, self, 1)?; - return Err(CheckErrors::TraitReferenceUnknown(name.to_string()).into()); + return Err( + CheckErrorKind::TraitReferenceUnknown(name.to_string()).into() + ); } } } diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/assets.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/assets.rs index fbd2e251c49..098300af775 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/assets.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/assets.rs @@ -17,7 +17,7 @@ use stacks_common::consts::TOKEN_TRANSFER_MEMO_LENGTH; use super::{TypeChecker, TypingContext}; -use crate::vm::analysis::errors::{check_argument_count, CheckError, CheckErrors}; +use crate::vm::analysis::errors::{check_argument_count, CheckErrorKind, StaticCheckError}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::representations::SymbolicExpression; @@ -27,16 +27,16 @@ pub fn check_special_get_owner( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) .cloned() - .ok_or_else(|| CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or_else(|| CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -55,13 +55,13 @@ pub fn check_special_get_balance( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -76,16 +76,16 @@ pub fn check_special_mint_asset( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))? + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? .clone(); // this clone shouldn't be strictly necessary, but to use `type_check_expects` with this, it would have to be. runtime_cost( @@ -107,10 +107,10 @@ pub fn check_special_mint_token( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -121,7 +121,7 @@ pub fn check_special_mint_token( checker.type_check_expects(&args[2], context, &expected_owner_type)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -134,16 +134,16 @@ pub fn check_special_transfer_asset( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(token_name) - .ok_or(CheckErrors::NoSuchNFT(token_name.to_string()))? + .ok_or(CheckErrorKind::NoSuchNFT(token_name.to_string()))? .clone(); runtime_cost( @@ -166,10 +166,10 @@ pub fn check_special_transfer_token( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -181,7 +181,7 @@ pub fn check_special_transfer_token( checker.type_check_expects(&args[3], context, &expected_owner_type)?; // recipient if !checker.contract_context.ft_exists(token_name) { - return Err(CheckErrors::NoSuchFT(token_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(token_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -194,7 +194,7 @@ pub fn check_special_stx_transfer( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; let amount_type: TypeSignature = TypeSignature::UIntType; @@ -217,7 +217,7 @@ pub fn check_special_stx_transfer_memo( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(4, args)?; let amount_type: TypeSignature = TypeSignature::UIntType; @@ -225,7 +225,7 @@ pub fn check_special_stx_transfer_memo( let to_type: TypeSignature = TypeSignature::PrincipalType; let memo_type: TypeSignature = TypeSignature::SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(TOKEN_TRANSFER_MEMO_LENGTH as u32) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, )); runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 0)?; @@ -245,13 +245,13 @@ pub fn check_special_get_token_supply( checker: &mut TypeChecker, args: &[SymbolicExpression], _context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -263,16 +263,16 @@ pub fn check_special_burn_asset( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))? + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? .clone(); // this clone shouldn't be strictly necessary, but to use `type_check_expects` with this, it would have to be. runtime_cost( @@ -294,10 +294,10 @@ pub fn check_special_burn_token( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -308,7 +308,7 @@ pub fn check_special_burn_token( checker.type_check_expects(&args[2], context, &expected_owner_type)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrors::NoSuchFT(asset_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/conversions.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/conversions.rs index 88f5470d530..f41702d56c7 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/conversions.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/conversions.rs @@ -3,7 +3,7 @@ use stacks_common::types::StacksEpochId; use super::TypeChecker; use crate::vm::analysis::read_only_checker::check_argument_count; use crate::vm::analysis::type_checker::contexts::TypingContext; -use crate::vm::analysis::CheckError; +use crate::vm::analysis::StaticCheckError; use crate::vm::types::{BufferLength, SequenceSubtype, TypeSignature, TypeSignatureExt as _}; use crate::vm::SymbolicExpression; @@ -16,14 +16,14 @@ pub fn check_special_to_consensus_buff( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input_type = checker.type_check(&args[0], context)?; let buffer_max_len = BufferLength::try_from(input_type.max_serialized_size()?)?; TypeSignature::new_option(TypeSignature::SequenceType(SequenceSubtype::BufferType( buffer_max_len, ))) - .map_err(CheckError::from) + .map_err(StaticCheckError::from) } /// `from-consensus-buff?` admits exactly two arguments: @@ -35,9 +35,9 @@ pub fn check_special_from_consensus_buff( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let result_type = TypeSignature::parse_type_repr(StacksEpochId::Epoch21, &args[0], checker)?; checker.type_check_expects(&args[1], context, &TypeSignature::max_buffer()?)?; - TypeSignature::new_option(result_type).map_err(CheckError::from) + TypeSignature::new_option(result_type).map_err(StaticCheckError::from) } diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/maps.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/maps.rs index 2dbc2407983..0b95c44f86c 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/maps.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/maps.rs @@ -17,7 +17,7 @@ use stacks_common::types::StacksEpochId; use crate::vm::analysis::type_checker::v2_1::{ - check_arguments_at_least, CheckError, CheckErrors, TypeChecker, TypingContext, + check_arguments_at_least, CheckErrorKind, StaticCheckError, TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; @@ -28,17 +28,17 @@ pub fn check_special_fetch_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let (expected_key_type, value_type) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -55,7 +55,7 @@ pub fn check_special_fetch_entry( let option_type = TypeSignature::new_option(value_type.clone())?; if !expected_key_type.admits_type(&StacksEpochId::Epoch21, &key_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -68,17 +68,17 @@ pub fn check_special_delete_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let (expected_key_type, _) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -88,7 +88,7 @@ pub fn check_special_delete_entry( analysis_typecheck_cost(&mut checker.cost_track, expected_key_type, &key_type)?; if !expected_key_type.admits_type(&StacksEpochId::Epoch21, &key_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -101,10 +101,10 @@ fn check_set_or_insert_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(3, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let value_type = checker.type_check(&args[2], context)?; @@ -112,7 +112,7 @@ fn check_set_or_insert_entry( let (expected_key_type, expected_value_type) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -129,12 +129,12 @@ fn check_set_or_insert_entry( analysis_typecheck_cost(&mut checker.cost_track, expected_value_type, &value_type)?; if !expected_key_type.admits_type(&StacksEpochId::Epoch21, &key_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) } else if !expected_value_type.admits_type(&StacksEpochId::Epoch21, &value_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) @@ -147,7 +147,7 @@ pub fn check_special_set_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_set_or_insert_entry(checker, args, context) } @@ -155,6 +155,6 @@ pub fn check_special_insert_entry( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_set_or_insert_entry(checker, args, context) } diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs index 161e6a5689d..ee68c359c7b 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs @@ -20,7 +20,7 @@ use super::{ check_argument_count, check_arguments_at_least, check_arguments_at_most, compute_typecheck_cost, no_type, TypeChecker, TypingContext, }; -use crate::vm::analysis::errors::{CheckError, CheckErrors, SyntaxBindingErrorType}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError, SyntaxBindingErrorType}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost, CostErrors, CostTracker}; use crate::vm::diagnostic::DiagnosableError; @@ -55,7 +55,7 @@ pub struct SpecialNativeFunction( &mut TypeChecker, &[SymbolicExpression], &TypingContext, - ) -> Result, + ) -> Result, ); pub struct SimpleNativeFunction(pub FunctionType); @@ -63,7 +63,7 @@ fn check_special_list_cons( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { let mut result = Vec::with_capacity(args.len()); let mut entries_size: Option = Some(0); let mut costs = Vec::with_capacity(args.len()); @@ -77,7 +77,7 @@ fn check_special_list_cons( ClarityCostFunction::AnalysisListItemsCheck, &[ty_size.into()], ) - .map_err(CheckErrors::from) + .map_err(CheckErrorKind::from) }); costs.push(cost); @@ -98,7 +98,7 @@ fn check_special_list_cons( checker.add_cost(cost?)?; } if entries_size.is_none() { - return Err(CheckErrors::ValueTooLarge.into()); + return Err(CheckErrorKind::ValueTooLarge.into()); } let typed_args = result; TypeSignature::parent_list_type(&typed_args) @@ -110,7 +110,7 @@ fn check_special_print( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; checker.type_check(&args[0], context) } @@ -119,7 +119,7 @@ fn check_special_as_contract( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; checker.type_check(&args[0], context) } @@ -128,7 +128,7 @@ fn check_special_at_block( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; checker.type_check_expects(&args[0], context, &BUFF_32)?; checker.type_check(&args[1], context) @@ -138,7 +138,7 @@ fn check_special_begin( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; checker.type_check_consecutive_statements(args, context) @@ -148,7 +148,7 @@ fn inner_handle_tuple_get( tuple_type_sig: &TupleTypeSignature, field_to_get: &str, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost( ClarityCostFunction::AnalysisCheckTupleGet, checker, @@ -157,7 +157,7 @@ fn inner_handle_tuple_get( let return_type = tuple_type_sig .field_type(field_to_get) - .ok_or(CheckError::new(CheckErrors::NoSuchTupleField( + .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchTupleField( field_to_get.to_string(), tuple_type_sig.clone(), )))? @@ -169,10 +169,12 @@ fn check_special_get( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let field_to_get = args[0].match_atom().ok_or(CheckErrors::BadTupleFieldName)?; + let field_to_get = args[0] + .match_atom() + .ok_or(CheckErrorKind::BadTupleFieldName)?; let argument_type = checker.type_check(&args[1], context)?; @@ -184,10 +186,10 @@ fn check_special_get( let option_type = TypeSignature::new_option(inner_type)?; Ok(option_type) } else { - Err(CheckErrors::ExpectedTuple(value_type_sig).into()) + Err(CheckErrorKind::ExpectedTuple(value_type_sig).into()) } } else { - Err(CheckErrors::ExpectedTuple(Box::new(argument_type)).into()) + Err(CheckErrorKind::ExpectedTuple(Box::new(argument_type)).into()) } } @@ -195,19 +197,19 @@ fn check_special_merge( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let res = checker.type_check(&args[0], context)?; let mut base = match res { TypeSignature::TupleType(tuple_sig) => Ok(tuple_sig), - _ => Err(CheckErrors::ExpectedTuple(Box::new(res.clone()))), + _ => Err(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), }?; let res = checker.type_check(&args[1], context)?; let mut update = match res { TypeSignature::TupleType(tuple_sig) => Ok(tuple_sig), - _ => Err(CheckErrors::ExpectedTuple(Box::new(res.clone()))), + _ => Err(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), }?; runtime_cost( ClarityCostFunction::AnalysisCheckTupleMerge, @@ -223,7 +225,7 @@ pub fn check_special_tuple_cons( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; let mut tuple_type_data = Vec::with_capacity(args.len()); @@ -255,7 +257,7 @@ pub fn check_special_tuple_cons( .saturating_add(var_type.size()?); tuple_type_data.push((var_name.clone(), var_type)); } else { - cons_error = Err(CheckErrors::BadTupleConstruction(format!( + cons_error = Err(CheckErrorKind::BadTupleConstruction(format!( "type size of {type_size} bytes exceeds maximum of {MAX_VALUE_SIZE} bytes" ))); } @@ -266,7 +268,7 @@ pub fn check_special_tuple_cons( cons_error?; let tuple_signature = TupleTypeSignature::try_from(tuple_type_data) - .map_err(|e| CheckErrors::BadTupleConstruction(e.message()))?; + .map_err(|e| CheckErrorKind::BadTupleConstruction(e.message()))?; Ok(TypeSignature::TupleType(tuple_signature)) } @@ -276,12 +278,12 @@ fn check_special_let( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; let binding_list = args[0] .match_list() - .ok_or(CheckError::new(CheckErrors::BadLetSyntax))?; + .ok_or(StaticCheckError::new(CheckErrorKind::BadLetSyntax))?; let mut out_context = context.extend()?; @@ -294,7 +296,7 @@ fn check_special_let( |var_name, var_sexp| { checker.contract_context.check_name_used(var_name)?; if out_context.lookup_variable_type(var_name).is_some() { - return Err(CheckError::new(CheckErrors::NameAlreadyUsed( + return Err(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( var_name.to_string(), ))); } @@ -331,17 +333,17 @@ fn check_special_fetch_var( checker: &mut TypeChecker, args: &[SymbolicExpression], _context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let var_name = args[0] .match_atom() - .ok_or(CheckError::new(CheckErrors::BadMapName))?; + .ok_or(StaticCheckError::new(CheckErrorKind::BadMapName))?; let value_type = checker .contract_context .get_persisted_variable_type(var_name) - .ok_or(CheckError::new(CheckErrors::NoSuchDataVariable( + .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchDataVariable( var_name.to_string(), )))?; @@ -358,17 +360,17 @@ fn check_special_set_var( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let var_name = args[0].match_atom().ok_or(CheckErrors::BadMapName)?; + let var_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; let value_type = checker.type_check(&args[1], context)?; let expected_value_type = checker .contract_context .get_persisted_variable_type(var_name) - .ok_or(CheckErrors::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -378,7 +380,7 @@ fn check_special_set_var( analysis_typecheck_cost(&mut checker.cost_track, &value_type, expected_value_type)?; if !expected_value_type.admits_type(&StacksEpochId::Epoch21, &value_type)? { - Err(CheckError::new(CheckErrors::TypeError( + Err(StaticCheckError::new(CheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) @@ -391,7 +393,7 @@ fn check_special_equals( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; let mut arg_type = None; @@ -407,7 +409,7 @@ fn check_special_equals( costs.push(cost); arg_type = Some( TypeSignature::least_supertype(&StacksEpochId::Epoch21, &x_type, &cur_type) - .map_err(|_| CheckErrors::TypeError(Box::new(x_type), Box::new(cur_type))), + .map_err(|_| CheckErrorKind::TypeError(Box::new(x_type), Box::new(cur_type))), ); } } @@ -418,7 +420,7 @@ fn check_special_equals( // check if there was a least supertype failure. arg_type.ok_or_else(|| { - CheckErrors::Expects("Arg type should be set because arguments checked for >= 1".into()) + CheckErrorKind::Expects("Arg type should be set because arguments checked for >= 1".into()) })??; Ok(TypeSignature::BoolType) @@ -428,7 +430,7 @@ fn check_special_if( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; checker.type_check_expects(&args[0], context, &TypeSignature::BoolType)?; @@ -443,7 +445,7 @@ fn check_special_if( TypeSignature::least_supertype(&StacksEpochId::Epoch21, expr1, expr2) .and_then(|t| t.concretize()) .map_err(|_| { - CheckErrors::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())).into() + CheckErrorKind::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())).into() }) } @@ -451,12 +453,12 @@ fn check_contract_call( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let func_name = args[1] - .match_atom() - .ok_or(CheckError::new(CheckErrors::ContractCallExpectName))?; + let func_name = args[1].match_atom().ok_or(StaticCheckError::new( + CheckErrorKind::ContractCallExpectName, + ))?; checker.type_map.set_type(&args[1], no_type())?; let expected_sig = match &args[0].expr { @@ -480,7 +482,7 @@ fn check_contract_call( { Ok(function) } else { - Err(CheckError::new(CheckErrors::NoSuchPublicFunction( + Err(StaticCheckError::new(CheckErrorKind::NoSuchPublicFunction( contract_identifier.to_string(), func_name.to_string(), ))) @@ -503,21 +505,22 @@ fn check_contract_call( let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, _ => { - return Err( - CheckErrors::TraitReferenceUnknown(trait_instance.to_string()).into(), - ); + return Err(CheckErrorKind::TraitReferenceUnknown( + trait_instance.to_string(), + ) + .into()); } }; runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; let trait_signature = checker.contract_context.get_trait(trait_id).ok_or( - CheckErrors::TraitReferenceUnknown(trait_id.name.to_string()), + CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), )?; let func_signature = trait_signature .get(func_name) - .ok_or(CheckErrors::TraitMethodUnknown( + .ok_or(CheckErrorKind::TraitMethodUnknown( trait_id.name.to_string(), func_name.to_string(), ))?; @@ -554,7 +557,7 @@ fn check_contract_call( { Ok(function) } else { - Err(CheckError::new(CheckErrors::NoSuchPublicFunction( + Err(StaticCheckError::new(CheckErrorKind::NoSuchPublicFunction( contract_identifier.to_string(), func_name.to_string(), ))) @@ -573,16 +576,17 @@ fn check_contract_call( } Some(var_type) => { // Any other typed constant is an error - return Err( - CheckErrors::ExpectedCallableType(Box::new(var_type.clone())).into(), - ); + return Err(CheckErrorKind::ExpectedCallableType(Box::new( + var_type.clone(), + )) + .into()); } _ => { // Dynamic dispatch let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, _ => { - return Err(CheckErrors::TraitReferenceUnknown( + return Err(CheckErrorKind::TraitReferenceUnknown( trait_instance.to_string(), ) .into()); @@ -592,10 +596,10 @@ fn check_contract_call( runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; let trait_signature = checker.contract_context.get_trait(trait_id).ok_or( - CheckErrors::TraitReferenceUnknown(trait_id.name.to_string()), + CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), )?; let func_signature = trait_signature.get(func_name).ok_or( - CheckErrors::TraitMethodUnknown( + CheckErrorKind::TraitMethodUnknown( trait_id.name.to_string(), func_name.to_string(), ), @@ -612,7 +616,11 @@ fn check_contract_call( } } } - _ => return Err(CheckError::new(CheckErrors::ContractCallExpectName)), + _ => { + return Err(StaticCheckError::new( + CheckErrorKind::ContractCallExpectName, + )) + } }; check_argument_count(expected_sig.args.len(), &args[2..])?; @@ -627,17 +635,21 @@ fn check_contract_of( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let trait_instance = match &args[0].expr { SymbolicExpressionType::Atom(trait_instance) => trait_instance, - _ => return Err(CheckError::new(CheckErrors::ContractOfExpectsTrait)), + _ => { + return Err(StaticCheckError::new( + CheckErrorKind::ContractOfExpectsTrait, + )) + } }; let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, - _ => return Err(CheckErrors::TraitReferenceUnknown(trait_instance.to_string()).into()), + _ => return Err(CheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into()), }; runtime_cost(ClarityCostFunction::ContractOf, checker, 1)?; @@ -645,7 +657,7 @@ fn check_contract_of( checker .contract_context .get_trait(trait_id) - .ok_or_else(|| CheckErrors::TraitReferenceUnknown(trait_id.name.to_string()))?; + .ok_or_else(|| CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()))?; Ok(TypeSignature::PrincipalType) } @@ -654,12 +666,12 @@ fn check_principal_of( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; checker.type_check_expects(&args[0], context, &BUFF_33)?; Ok( TypeSignature::new_response(TypeSignature::PrincipalType, TypeSignature::UIntType) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -673,7 +685,7 @@ fn check_principal_construct( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; check_arguments_at_most(3, args)?; checker.type_check_expects(&args[0], context, &BUFF_1)?; @@ -691,13 +703,13 @@ fn check_principal_construct( ("error_code".into(), TypeSignature::UIntType), ( "value".into(), - TypeSignature::new_option(TypeSignature::PrincipalType).map_err(|_| CheckErrors::Expects("FATAL: failed to create (optional principal) type signature".into()))?, + TypeSignature::new_option(TypeSignature::PrincipalType).map_err(|_| CheckErrorKind::Expects("FATAL: failed to create (optional principal) type signature".into()))?, ), ]) - .map_err(|_| CheckErrors::Expects("FAIL: PrincipalConstruct failed to initialize type signature".into()))? + .map_err(|_| CheckErrorKind::Expects("FAIL: PrincipalConstruct failed to initialize type signature".into()))? .into() ) - .map_err(|_| CheckErrors::Expects("FATAL: failed to create `(response principal { error_code: uint, principal: (optional principal) })` type signature".into()))? + .map_err(|_| CheckErrorKind::Expects("FATAL: failed to create `(response principal { error_code: uint, principal: (optional principal) })` type signature".into()))? ) } @@ -705,13 +717,13 @@ fn check_secp256k1_recover( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; checker.type_check_expects(&args[0], context, &BUFF_32)?; checker.type_check_expects(&args[1], context, &BUFF_65)?; Ok( TypeSignature::new_response(BUFF_33.clone(), TypeSignature::UIntType) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -719,7 +731,7 @@ fn check_secp256k1_verify( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; checker.type_check_expects(&args[0], context, &BUFF_32)?; checker.type_check_expects(&args[1], context, &BUFF_65)?; @@ -731,18 +743,18 @@ fn check_get_block_info( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; - let block_info_prop_str = args[0] - .match_atom() - .ok_or(CheckError::new(CheckErrors::GetBlockInfoExpectPropertyName))?; + let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( + CheckErrorKind::GetBlockInfoExpectPropertyName, + ))?; let block_info_prop = BlockInfoProperty::lookup_by_name_at_version(block_info_prop_str, &checker.clarity_version) - .ok_or(CheckError::new(CheckErrors::NoSuchBlockInfoProperty( - block_info_prop_str.to_string(), - )))?; + .ok_or(StaticCheckError::new( + CheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), + ))?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -750,30 +762,30 @@ fn check_get_block_info( } // # Errors -// - `CheckErrors::GetBurnBlockInfoExpectPropertyName` when `args[0]` is not a valid `ClarityName`. -// - `CheckErrors::NoSuchBlockInfoProperty` when `args[0]` does not name a `BurnBlockInfoProperty`. +// - `CheckErrorKind::GetBurnBlockInfoExpectPropertyName` when `args[0]` is not a valid `ClarityName`. +// - `CheckErrorKind::NoSuchBlockInfoProperty` when `args[0]` does not name a `BurnBlockInfoProperty`. fn check_get_burn_block_info( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let block_info_prop_str = args[0].match_atom().ok_or(CheckError::new( - CheckErrors::GetBurnBlockInfoExpectPropertyName, + let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( + CheckErrorKind::GetBurnBlockInfoExpectPropertyName, ))?; let block_info_prop = - BurnBlockInfoProperty::lookup_by_name(block_info_prop_str).ok_or(CheckError::new( - CheckErrors::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), + BurnBlockInfoProperty::lookup_by_name(block_info_prop_str).ok_or(StaticCheckError::new( + CheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), ))?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; Ok(TypeSignature::new_option( - block_info_prop - .type_result() - .map_err(|_| CheckErrors::Expects("FAILED to type valid burn info property".into()))?, + block_info_prop.type_result().map_err(|_| { + CheckErrorKind::Expects("FAILED to type valid burn info property".into()) + })?, )?) } @@ -781,17 +793,18 @@ fn check_get_stacks_block_info( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let block_info_prop_str = args[0].match_atom().ok_or(CheckError::new( - CheckErrors::GetStacksBlockInfoExpectPropertyName, + let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( + CheckErrorKind::GetStacksBlockInfoExpectPropertyName, ))?; - let block_info_prop = - StacksBlockInfoProperty::lookup_by_name(block_info_prop_str).ok_or(CheckError::new( - CheckErrors::NoSuchStacksBlockInfoProperty(block_info_prop_str.to_string()), - ))?; + let block_info_prop = StacksBlockInfoProperty::lookup_by_name(block_info_prop_str).ok_or( + StaticCheckError::new(CheckErrorKind::NoSuchStacksBlockInfoProperty( + block_info_prop_str.to_string(), + )), + )?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -802,16 +815,16 @@ fn check_get_tenure_info( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; - let block_info_prop_str = args[0].match_atom().ok_or(CheckError::new( - CheckErrors::GetTenureInfoExpectPropertyName, + let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( + CheckErrorKind::GetTenureInfoExpectPropertyName, ))?; let block_info_prop = - TenureInfoProperty::lookup_by_name(block_info_prop_str).ok_or(CheckError::new( - CheckErrors::NoSuchTenureInfoProperty(block_info_prop_str.to_string()), + TenureInfoProperty::lookup_by_name(block_info_prop_str).ok_or(StaticCheckError::new( + CheckErrorKind::NoSuchTenureInfoProperty(block_info_prop_str.to_string()), ))?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -825,7 +838,7 @@ impl TypedNativeFunction { checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, - ) -> Result { + ) -> Result { use self::TypedNativeFunction::{Simple, Special}; match self { Special(SpecialNativeFunction(check)) => check(checker, args, context), @@ -841,7 +854,7 @@ impl TypedNativeFunction { pub fn type_native_function( function: &NativeFunctions, - ) -> Result { + ) -> Result { use self::TypedNativeFunction::{Simple, Special}; use crate::vm::functions::NativeFunctions::*; let out = match function { @@ -870,7 +883,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::IntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -881,7 +894,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -892,7 +905,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -904,10 +917,10 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(16_u32) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, )), ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -920,10 +933,10 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(16_u32) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, )), ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -959,7 +972,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::BoolType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1012,7 +1025,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("owner".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1024,7 +1037,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("principal".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1032,7 +1045,7 @@ impl TypedNativeFunction { returns: { /// The return type of `principal-destruct` is a Response, in which the success /// and error types are the same. - fn parse_principal_basic_type() -> Result { + fn parse_principal_basic_type() -> Result { TupleTypeSignature::try_from(vec![ ("version".into(), BUFF_1.clone()), ("hash-bytes".into(), BUFF_20.clone()), @@ -1041,11 +1054,11 @@ impl TypedNativeFunction { TypeSignature::new_option( TypeSignature::contract_name_string_ascii_type()?, ) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, ), ]) .map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: PrincipalDestruct failed to initialize type signature" .into(), ) @@ -1061,7 +1074,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("owner".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1072,7 +1085,7 @@ impl TypedNativeFunction { ("unlock-height".into(), TypeSignature::UIntType), ]) .map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: StxGetAccount failed to initialize type signature".into(), ) })? @@ -1083,7 +1096,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("amount".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1091,7 +1104,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("sender".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1101,7 +1114,7 @@ impl TypedNativeFunction { TypeSignature::BoolType, TypeSignature::UIntType, ) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, }))), StxTransfer => Special(SpecialNativeFunction(&assets::check_special_stx_transfer)), StxTransferMemo => Special(SpecialNativeFunction( @@ -1184,13 +1197,13 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("contract".to_owned()).map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, )], returns: TypeSignature::new_response(BUFF_32.clone(), TypeSignature::UIntType) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, }))), ToAscii => Simple(SimpleNativeFunction(FunctionType::UnionArgs( vec![ @@ -1206,7 +1219,9 @@ impl TypedNativeFunction { TypeSignature::UIntType, ) .map_err(|_| { - CheckErrors::Expects("FATAL: Legal Clarity response type marked invalid".into()) + CheckErrorKind::Expects( + "FATAL: Legal Clarity response type marked invalid".into(), + ) })?, ))), }; diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/options.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/options.rs index 56d145298a6..b4f01b196c7 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/options.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/options.rs @@ -19,7 +19,8 @@ use clarity_types::types::TypeSignature; use stacks_common::types::StacksEpochId; use super::{ - check_argument_count, check_arguments_at_least, no_type, CheckError, CheckErrors, TypeChecker, + check_argument_count, check_arguments_at_least, no_type, CheckErrorKind, StaticCheckError, + TypeChecker, }; use crate::vm::analysis::type_checker::contexts::TypingContext; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -30,7 +31,7 @@ pub fn check_special_okay( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; runtime_cost(ClarityCostFunction::AnalysisOptionCons, checker, 0)?; @@ -44,7 +45,7 @@ pub fn check_special_some( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; runtime_cost(ClarityCostFunction::AnalysisOptionCons, checker, 0)?; @@ -58,7 +59,7 @@ pub fn check_special_error( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; runtime_cost(ClarityCostFunction::AnalysisOptionCons, checker, 0)?; @@ -72,7 +73,7 @@ pub fn check_special_is_response( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -82,7 +83,7 @@ pub fn check_special_is_response( if let TypeSignature::ResponseType(_types) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrors::ExpectedResponseType(Box::new(input.clone())).into()) + Err(CheckErrorKind::ExpectedResponseType(Box::new(input.clone())).into()) } } @@ -90,7 +91,7 @@ pub fn check_special_is_optional( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -100,7 +101,7 @@ pub fn check_special_is_optional( if let TypeSignature::OptionalType(_type) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrors::ExpectedOptionalType(Box::new(input.clone())).into()) + Err(CheckErrorKind::ExpectedOptionalType(Box::new(input.clone())).into()) } } @@ -108,7 +109,7 @@ pub fn check_special_default_to( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let default = checker.type_check(&args[0], context)?; @@ -120,12 +121,12 @@ pub fn check_special_default_to( let contained_type = *input_type; TypeSignature::least_supertype(&StacksEpochId::Epoch21, &default, &contained_type).map_err( |_| { - CheckErrors::DefaultTypesMustMatch(Box::new(default), Box::new(contained_type)) + CheckErrorKind::DefaultTypesMustMatch(Box::new(default), Box::new(contained_type)) .into() }, ) } else { - Err(CheckErrors::ExpectedOptionalType(Box::new(input)).into()) + Err(CheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) } } @@ -133,7 +134,7 @@ pub fn check_special_asserts( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; checker.type_check_expects(&args[0], context, &TypeSignature::BoolType)?; @@ -147,13 +148,13 @@ pub fn check_special_asserts( fn inner_unwrap( input: TypeSignature, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost(ClarityCostFunction::AnalysisOptionCheck, checker, 0)?; match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(*input_type) } @@ -161,30 +162,30 @@ fn inner_unwrap( TypeSignature::ResponseType(response_type) => { let ok_type = response_type.0; if ok_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(ok_type) } } - _ => Err(CheckErrors::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } fn inner_unwrap_err( input: TypeSignature, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost(ClarityCostFunction::AnalysisOptionCheck, checker, 0)?; if let TypeSignature::ResponseType(response_type) = input { let err_type = response_type.1; if err_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseErrType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { Ok(err_type) } } else { - Err(CheckErrors::ExpectedResponseType(Box::new(input)).into()) + Err(CheckErrorKind::ExpectedResponseType(Box::new(input)).into()) } } @@ -192,7 +193,7 @@ pub fn check_special_unwrap_or_ret( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let input = checker.type_check(&args[0], context)?; @@ -207,7 +208,7 @@ pub fn check_special_unwrap_err_or_ret( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let input = checker.type_check(&args[0], context)?; @@ -222,7 +223,7 @@ pub fn check_special_try_ret( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -232,7 +233,7 @@ pub fn check_special_try_ret( match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { checker.track_return_type(TypeSignature::new_option(TypeSignature::NoType)?)?; Ok(*input_type) @@ -241,9 +242,9 @@ pub fn check_special_try_ret( TypeSignature::ResponseType(response_type) => { let (ok_type, err_type) = *response_type; if ok_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseOkType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) } else if err_type.is_no_type() { - Err(CheckErrors::CouldNotDetermineResponseErrType.into()) + Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { checker.track_return_type(TypeSignature::new_response( TypeSignature::NoType, @@ -252,7 +253,7 @@ pub fn check_special_try_ret( Ok(ok_type) } } - _ => Err(CheckErrors::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } @@ -260,7 +261,7 @@ pub fn check_special_unwrap( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -272,7 +273,7 @@ pub fn check_special_unwrap_err( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -287,7 +288,7 @@ fn eval_with_new_binding( bind_type: TypeSignature, checker: &mut TypeChecker, context: &TypingContext, -) -> Result { +) -> Result { let mut inner_context = context.extend()?; runtime_cost( @@ -305,7 +306,7 @@ fn eval_with_new_binding( checker.contract_context.check_name_used(&bind_name)?; if inner_context.lookup_variable_type(&bind_name).is_some() { - return Err(CheckErrors::NameAlreadyUsed(bind_name.into()).into()); + return Err(CheckErrorKind::NameAlreadyUsed(bind_name.into()).into()); } inner_context.add_variable_type(bind_name, bind_type, checker.clarity_version); @@ -322,22 +323,24 @@ fn check_special_match_opt( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { if args.len() != 3 { - Err(CheckErrors::BadMatchOptionSyntax(Box::new( - CheckErrors::IncorrectArgumentCount(4, args.len() + 1), + Err(CheckErrorKind::BadMatchOptionSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(4, args.len() + 1), )))?; } let bind_name = args[0] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchOptionSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let some_branch = &args[1]; let none_branch = &args[2]; if option_type.is_no_type() { - return Err(CheckErrors::CouldNotDetermineMatchTypes.into()); + return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); } let some_branch_type = @@ -352,7 +355,7 @@ fn check_special_match_opt( &none_branch_type, ) .map_err(|_| { - CheckErrors::MatchArmsMustMatch(Box::new(some_branch_type), Box::new(none_branch_type)) + CheckErrorKind::MatchArmsMustMatch(Box::new(some_branch_type), Box::new(none_branch_type)) .into() }) } @@ -362,28 +365,32 @@ fn check_special_match_resp( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { if args.len() != 4 { - Err(CheckErrors::BadMatchResponseSyntax(Box::new( - CheckErrors::IncorrectArgumentCount(5, args.len() + 1), + Err(CheckErrorKind::BadMatchResponseSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(5, args.len() + 1), )))?; } let ok_bind_name = args[0] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let ok_branch = &args[1]; let err_bind_name = args[2] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let err_branch = &args[3]; let (ok_type, err_type) = resp_type; if ok_type.is_no_type() || err_type.is_no_type() { - return Err(CheckErrors::CouldNotDetermineMatchTypes.into()); + return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); } let ok_branch_type = eval_with_new_binding(ok_branch, ok_bind_name, ok_type, checker, context)?; @@ -394,7 +401,7 @@ fn check_special_match_resp( TypeSignature::least_supertype(&StacksEpochId::Epoch21, &ok_branch_type, &err_branch_type) .map_err(|_| { - CheckErrors::MatchArmsMustMatch(Box::new(ok_branch_type), Box::new(err_branch_type)) + CheckErrorKind::MatchArmsMustMatch(Box::new(ok_branch_type), Box::new(err_branch_type)) .into() }) } @@ -403,7 +410,7 @@ pub fn check_special_match( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(1, args)?; let input = checker.type_check(&args[0], context)?; @@ -415,6 +422,6 @@ pub fn check_special_match( TypeSignature::ResponseType(resp_type) => { check_special_match_resp(*resp_type, checker, &args[1..], context) } - _ => Err(CheckErrors::BadMatchInput(Box::new(input)).into()), + _ => Err(CheckErrorKind::BadMatchInput(Box::new(input)).into()), } } diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs index 92143b80b0f..bcf9354b667 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs @@ -18,7 +18,7 @@ use stacks_common::types::StacksEpochId; use super::{SimpleNativeFunction, TypedNativeFunction}; use crate::vm::analysis::type_checker::v2_1::{ - check_argument_count, check_arguments_at_least, CheckError, CheckErrors, TypeChecker, + check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -34,7 +34,7 @@ use crate::vm::types::{FunctionType, TypeSignature, Value}; fn get_simple_native_or_user_define( function_name: &str, checker: &mut TypeChecker, -) -> Result { +) -> Result { runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; if let Some(ref native_function) = NativeFunctions::lookup_by_name_at_version(function_name, &checker.clarity_version) @@ -44,11 +44,14 @@ fn get_simple_native_or_user_define( { Ok(function_type) } else { - Err(CheckErrors::IllegalOrUnknownFunctionApplication(function_name.to_string()).into()) + Err( + CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()) + .into(), + ) } } else { checker.get_function_type(function_name).ok_or( - CheckErrors::IllegalOrUnknownFunctionApplication(function_name.to_string()).into(), + CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()).into(), ) } } @@ -57,12 +60,12 @@ pub fn check_special_map( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_arguments_at_least(2, args)?; let function_name = args[0] .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; // we will only lookup native or defined functions here. // you _cannot_ map a special function. let function_type = get_simple_native_or_user_define(function_name, checker)?; @@ -104,7 +107,7 @@ pub fn check_special_map( // However that could lead to confusions when combining certain types: // ex: (map concat (list "hello " "hi ") "world") would fail, because // strings are handled as sequences. - return Err(CheckErrors::ExpectedSequence(Box::new(argument_type)).into()); + return Err(CheckErrorKind::ExpectedSequence(Box::new(argument_type)).into()); } }; @@ -134,8 +137,8 @@ pub fn check_special_map( } if let Err(mut check_error) = check_result { - if let CheckErrors::IncorrectArgumentCount(expected, _actual) = *check_error.err { - check_error.err = Box::new(CheckErrors::IncorrectArgumentCount( + if let CheckErrorKind::IncorrectArgumentCount(expected, _actual) = *check_error.err { + check_error.err = Box::new(CheckErrorKind::IncorrectArgumentCount( expected, args.len().saturating_sub(1), )); @@ -156,19 +159,19 @@ pub fn check_special_map( context.clarity_version, )?; TypeSignature::list_of(mapped_type, min_args) - .map_err(|_| CheckErrors::ConstructedListTooLarge.into()) + .map_err(|_| CheckErrorKind::ConstructedListTooLarge.into()) } pub fn check_special_filter( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let function_name = args[0] .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; // we will only lookup native or defined functions here. // you _cannot_ map a special function. let function_type = get_simple_native_or_user_define(function_name, checker)?; @@ -179,7 +182,7 @@ pub fn check_special_filter( { let input_type = match argument_type { TypeSignature::SequenceType(ref sequence_type) => Ok(sequence_type.unit_type()?), - _ => Err(CheckErrors::ExpectedSequence(Box::new( + _ => Err(CheckErrorKind::ExpectedSequence(Box::new( argument_type.clone(), ))), }?; @@ -192,7 +195,7 @@ pub fn check_special_filter( )?; if TypeSignature::BoolType != filter_type { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(TypeSignature::BoolType), Box::new(filter_type), ) @@ -207,12 +210,12 @@ pub fn check_special_fold( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; let function_name = args[0] .match_atom() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; // we will only lookup native or defined functions here. // you _cannot_ fold a special function. let function_type = get_simple_native_or_user_define(function_name, checker)?; @@ -222,7 +225,7 @@ pub fn check_special_fold( let input_type = match argument_type { TypeSignature::SequenceType(sequence_type) => Ok(sequence_type.unit_type()?), - _ => Err(CheckErrors::ExpectedSequence(Box::new(argument_type))), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(argument_type))), }?; let initial_value_type = checker.type_check(&args[2], context)?; @@ -254,7 +257,7 @@ pub fn check_special_concat( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let lhs_type = checker.type_check(&args[0], context)?; @@ -280,29 +283,29 @@ pub fn check_special_concat( )?; let new_len = lhs_max_len .checked_add(rhs_max_len) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::list_of(list_entry_type, new_len)? } (BufferType(lhs_len), BufferType(rhs_len)) => { let size: u32 = u32::from(lhs_len) .checked_add(u32::from(rhs_len)) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(BufferType(size.try_into()?)) } (StringType(ASCII(lhs_len)), StringType(ASCII(rhs_len))) => { let size: u32 = u32::from(lhs_len) .checked_add(u32::from(rhs_len)) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(StringType(ASCII(size.try_into()?))) } (StringType(UTF8(lhs_len)), StringType(UTF8(rhs_len))) => { let size: u32 = u32::from(lhs_len) .checked_add(u32::from(rhs_len)) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(StringType(UTF8(size.try_into()?))) } (_, _) => { - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(lhs_type.clone()), Box::new(rhs_type.clone()), ) @@ -310,7 +313,7 @@ pub fn check_special_concat( } } } - _ => return Err(CheckErrors::ExpectedSequence(Box::new(lhs_type.clone())).into()), + _ => return Err(CheckErrorKind::ExpectedSequence(Box::new(lhs_type.clone())).into()), }; Ok(res) } @@ -319,7 +322,7 @@ pub fn check_special_append( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -339,11 +342,11 @@ pub fn check_special_append( )?; let new_len = lhs_max_len .checked_add(1) - .ok_or(CheckErrors::MaxLengthOverflow)?; + .ok_or(CheckErrorKind::MaxLengthOverflow)?; let return_type = TypeSignature::list_of(list_entry_type, new_len)?; Ok(return_type) } - _ => Err(CheckErrors::ExpectedListApplication.into()), + _ => Err(CheckErrorKind::ExpectedListApplication.into()), } } @@ -351,14 +354,14 @@ pub fn check_special_as_max_len( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let expected_len = match args[1].expr { SymbolicExpressionType::LiteralValue(Value::UInt(expected_len)) => expected_len, _ => { let expected_len_type = checker.type_check(&args[1], context)?; - return Err(CheckErrors::TypeError( + return Err(CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(expected_len_type), ) @@ -374,7 +377,8 @@ pub fn check_special_as_max_len( .type_map .set_type(&args[1], TypeSignature::UIntType)?; - let expected_len = u32::try_from(expected_len).map_err(|_e| CheckErrors::MaxLengthOverflow)?; + let expected_len = + u32::try_from(expected_len).map_err(|_e| CheckErrorKind::MaxLengthOverflow)?; let sequence = checker.type_check(&args[0], context)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -400,7 +404,7 @@ pub fn check_special_as_max_len( StringUTF8Length::try_from(expected_len)?, )))), )), - _ => Err(CheckErrors::ExpectedSequence(Box::new(sequence)).into()), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(sequence)).into()), } } @@ -408,7 +412,7 @@ pub fn check_special_len( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(1, args)?; let collection_type = checker.type_check(&args[0], context)?; @@ -416,7 +420,7 @@ pub fn check_special_len( match collection_type { TypeSignature::SequenceType(_) => Ok(()), - _ => Err(CheckErrors::ExpectedSequence(Box::new(collection_type))), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type))), }?; Ok(TypeSignature::UIntType) @@ -426,7 +430,7 @@ pub fn check_special_element_at( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; let _index_type = checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -445,16 +449,16 @@ pub fn check_special_element_at( TypeSignature::SequenceType(StringType(ASCII(_))) => Ok(TypeSignature::OptionalType( Box::new(TypeSignature::SequenceType(StringType(ASCII( BufferLength::try_from(1u32) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, )))), )), TypeSignature::SequenceType(StringType(UTF8(_))) => Ok(TypeSignature::OptionalType( Box::new(TypeSignature::SequenceType(StringType(UTF8( StringUTF8Length::try_from(1u32) - .map_err(|_| CheckErrors::Expects("Bad constructor".into()))?, + .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, )))), )), - _ => Err(CheckErrors::ExpectedSequence(Box::new(collection_type)).into()), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type)).into()), } } @@ -462,7 +466,7 @@ pub fn check_special_index_of( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(2, args)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -470,7 +474,7 @@ pub fn check_special_index_of( let expected_input_type = match list_type { TypeSignature::SequenceType(ref sequence_type) => Ok(sequence_type.unit_type()?), - _ => Err(CheckErrors::ExpectedSequence(Box::new(list_type))), + _ => Err(CheckErrorKind::ExpectedSequence(Box::new(list_type))), }?; checker.type_check_expects(&args[1], context, &expected_input_type)?; @@ -483,7 +487,7 @@ pub fn check_special_slice( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -493,7 +497,7 @@ pub fn check_special_slice( TypeSignature::SequenceType(seq) => { TypeSignature::new_option(TypeSignature::SequenceType(seq))? } - _ => return Err(CheckErrors::ExpectedSequence(Box::new(seq_type)).into()), + _ => return Err(CheckErrorKind::ExpectedSequence(Box::new(seq_type)).into()), }; // Check left position argument @@ -509,7 +513,7 @@ pub fn check_special_replace_at( checker: &mut TypeChecker, args: &[SymbolicExpression], context: &TypingContext, -) -> Result { +) -> Result { check_argument_count(3, args)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -517,7 +521,7 @@ pub fn check_special_replace_at( let input_type = checker.type_check(&args[0], context)?; let seq_type = match &input_type { TypeSignature::SequenceType(seq) => seq, - _ => return Err(CheckErrors::ExpectedSequence(Box::new(input_type)).into()), + _ => return Err(CheckErrorKind::ExpectedSequence(Box::new(input_type)).into()), }; let unit_seq = seq_type.unit_type()?; // Check index argument diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs index a25a43a3cc5..cd2c5620c04 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs @@ -21,7 +21,7 @@ use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; use super::contracts::type_check; -use crate::vm::analysis::errors::CheckErrors; +use crate::vm::analysis::errors::CheckErrorKind; use crate::vm::ast::parse; use crate::vm::database::MemoryBackingStore; use crate::vm::tests::test_clarity_versions; @@ -173,108 +173,108 @@ fn test_bad_asset_usage() { ]; let expected = [ - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::BadTokenName, - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::BadTokenName, + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), ), - CheckErrors::BadTokenName, - CheckErrors::NoSuchNFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::NoSuchNFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrors::BadTokenName, - CheckErrors::NoSuchNFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::NoSuchNFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrors::BadTokenName, - CheckErrors::NoSuchNFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::NoSuchNFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::BadTokenName, - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::BadTokenName, + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrors::DefineNFTBadSignature, - CheckErrors::TypeError( + CheckErrorKind::DefineNFTBadSignature, + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::NoSuchFT("stackoos".to_string()), - CheckErrors::TypeError( + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::NoSuchFT("stackoos".to_string()), + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), ), diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs index 82dd67ce0ea..696ce27a3e0 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs @@ -21,11 +21,11 @@ use serde_json; use stacks_common::types::StacksEpochId; use crate::vm::analysis::contract_interface_builder::build_contract_interface; -use crate::vm::analysis::errors::CheckErrors; +use crate::vm::analysis::errors::CheckErrorKind; use crate::vm::analysis::type_checker::v2_1::tests::mem_type_check; use crate::vm::analysis::{ - mem_type_check as mem_run_analysis, run_analysis, AnalysisDatabase, CheckError, - ContractAnalysis, + mem_type_check as mem_run_analysis, run_analysis, AnalysisDatabase, ContractAnalysis, + StaticCheckError, }; use crate::vm::ast::parse; use crate::vm::costs::LimitedCostTracker; @@ -40,7 +40,7 @@ use crate::vm::{ClarityName, ClarityVersion, SymbolicExpression}; fn mem_type_check_v1( snippet: &str, -) -> Result<(Option, ContractAnalysis), CheckError> { +) -> Result<(Option, ContractAnalysis), StaticCheckError> { mem_run_analysis(snippet, ClarityVersion::Clarity1, StacksEpochId::latest()) } @@ -56,7 +56,7 @@ pub fn type_check( expressions: &mut [SymbolicExpression], analysis_db: &mut AnalysisDatabase, save_contract: bool, -) -> Result { +) -> Result { type_check_version( contract_identifier, expressions, @@ -74,7 +74,7 @@ pub fn type_check_version( save_contract: bool, epoch: StacksEpochId, version: ClarityVersion, -) -> Result { +) -> Result { run_analysis( contract_identifier, expressions, @@ -494,7 +494,7 @@ fn test_names_tokens_contracts_bad(#[case] version: ClarityVersion, #[case] epoc let err = db .execute(|db| type_check(&names_contract_id, &mut names_contract, db, true)) .unwrap_err(); - assert!(matches!(*err.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*err.err, CheckErrorKind::TypeError(_, _))); } #[test] @@ -535,12 +535,12 @@ fn test_bad_map_usage() { for contract in tests.iter() { let err = mem_type_check(contract).unwrap_err(); - assert!(matches!(*err.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*err.err, CheckErrorKind::TypeError(_, _))); } assert!(matches!( *mem_type_check(unhandled_option).unwrap_err().err, - CheckErrors::UnionTypeError(_, _) + CheckErrorKind::UnionTypeError(_, _) )); } @@ -627,25 +627,31 @@ fn test_expects() { for unmatched_return_types in bad_return_types_tests.iter() { let err = mem_type_check(unmatched_return_types).unwrap_err(); eprintln!("unmatched_return_types returned check error: {err}"); - assert!(matches!(*err.err, CheckErrors::ReturnTypesMustMatch(_, _))); + assert!(matches!( + *err.err, + CheckErrorKind::ReturnTypesMustMatch(_, _) + )); } let err = mem_type_check(bad_default_type).unwrap_err(); eprintln!("bad_default_types returned check error: {err}"); - assert!(matches!(*err.err, CheckErrors::DefaultTypesMustMatch(_, _))); + assert!(matches!( + *err.err, + CheckErrorKind::DefaultTypesMustMatch(_, _) + )); let err = mem_type_check(notype_response_type).unwrap_err(); eprintln!("notype_response_type returned check error: {err}"); assert!(matches!( *err.err, - CheckErrors::CouldNotDetermineResponseErrType + CheckErrorKind::CouldNotDetermineResponseErrType )); let err = mem_type_check(notype_response_type_2).unwrap_err(); eprintln!("notype_response_type_2 returned check error: {err}"); assert!(matches!( *err.err, - CheckErrors::CouldNotDetermineResponseOkType + CheckErrorKind::CouldNotDetermineResponseOkType )); } @@ -681,7 +687,7 @@ fn test_trait_to_compatible_trait() { mem_type_check(trait_to_compatible_trait).unwrap(); let err = mem_type_check_v1(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -708,7 +714,7 @@ fn test_bad_principal_to_trait() { let err = mem_type_check(bad_principal_to_trait).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::PrincipalType, @@ -721,7 +727,7 @@ fn test_bad_principal_to_trait() { }; let err = mem_type_check_v1(bad_principal_to_trait).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::PrincipalType, @@ -750,7 +756,7 @@ fn test_bad_other_trait() { let err = mem_type_check(bad_other_trait).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, actual) => { + CheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -758,7 +764,7 @@ fn test_bad_other_trait() { }; let err = mem_type_check_v1(bad_other_trait).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, actual) => match (&*expected, &*actual) { + CheckErrorKind::TypeError(expected, actual) => match (&*expected, &*actual) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -791,7 +797,7 @@ fn test_embedded_trait() { mem_type_check(embedded_trait).unwrap(); let err = mem_type_check_v1(embedded_trait).unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(name) => { + CheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "contract"); } _ => panic!("Unexpected error: {err:?}"), @@ -821,7 +827,7 @@ fn test_embedded_trait_compatible() { mem_type_check(embedded_trait_compatible).unwrap(); let err = mem_type_check_v1(embedded_trait_compatible).unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(name) => { + CheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "contract"); } _ => panic!("Unexpected error: {err:?}"), @@ -854,7 +860,7 @@ fn test_bad_embedded_trait() { let err = mem_type_check(bad_embedded_trait).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, actual) => { + CheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-12"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -862,7 +868,7 @@ fn test_bad_embedded_trait() { }; let err = mem_type_check_v1(bad_embedded_trait).unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(name) => { + CheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "contract"); } _ => panic!("Unexpected error: {err:?}"), @@ -884,7 +890,7 @@ fn test_let_trait() { mem_type_check(let_trait).unwrap(); let err = mem_type_check_v1(let_trait).unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(name) => { + CheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "t1"); } _ => panic!("Unexpected error: {err:?}"), @@ -910,7 +916,7 @@ fn test_let3_trait() { mem_type_check(let3_trait).unwrap(); let err = mem_type_check_v1(let3_trait).unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(name) => { + CheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "t3"); } _ => panic!("Unexpected error: {err:?}"), @@ -965,7 +971,7 @@ fn test_let3_compound_trait_call() { mem_type_check(let3_compound_trait_call).unwrap(); let err = mem_type_check_v1(let3_compound_trait_call).unwrap_err(); match *err.err { - CheckErrors::TraitReferenceUnknown(name) => { + CheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "t4"); } _ => panic!("Unexpected error: {err:?}"), @@ -989,7 +995,7 @@ fn test_trait_args_differ() { let err = mem_type_check(trait_args_differ).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, actual) => { + CheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -997,7 +1003,7 @@ fn test_trait_args_differ() { }; let err = mem_type_check_v1(trait_args_differ).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1027,7 +1033,7 @@ fn test_trait_arg_counts_differ1() { let err = mem_type_check(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, found) => { + CheckErrorKind::IncompatibleTrait(expected, found) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(found.name.as_str(), "trait-1"); } @@ -1035,7 +1041,7 @@ fn test_trait_arg_counts_differ1() { }; let err = mem_type_check_v1(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1065,7 +1071,7 @@ fn test_trait_arg_counts_differ2() { let err = mem_type_check(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, found) => { + CheckErrorKind::IncompatibleTrait(expected, found) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(found.name.as_str(), "trait-1"); } @@ -1073,7 +1079,7 @@ fn test_trait_arg_counts_differ2() { }; let err = mem_type_check_v1(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1103,7 +1109,7 @@ fn test_trait_ret_ty_differ() { let err = mem_type_check(trait_ret_ty_differ).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, actual) => { + CheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -1111,7 +1117,7 @@ fn test_trait_ret_ty_differ() { }; let err = mem_type_check_v1(trait_ret_ty_differ).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1149,7 +1155,7 @@ fn test_trait_with_compatible_trait_arg() { mem_type_check(trait_with_compatible_trait_arg).unwrap(); let err = mem_type_check_v1(trait_with_compatible_trait_arg).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1186,7 +1192,7 @@ fn test_trait_with_bad_trait_arg() { let err = mem_type_check(trait_with_bad_trait_arg).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, actual) => { + CheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-b"); assert_eq!(actual.name.as_str(), "trait-a"); } @@ -1194,7 +1200,7 @@ fn test_trait_with_bad_trait_arg() { }; let err = mem_type_check_v1(trait_with_bad_trait_arg).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1232,7 +1238,7 @@ fn test_trait_with_superset_trait_arg() { let err = mem_type_check(trait_with_superset_trait_arg).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, actual) => { + CheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-b"); assert_eq!(actual.name.as_str(), "trait-a"); } @@ -1242,7 +1248,7 @@ fn test_trait_with_superset_trait_arg() { let err = mem_type_check_v1(trait_with_superset_trait_arg).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1281,7 +1287,7 @@ fn test_trait_with_subset_trait_arg() { mem_type_check(trait_with_subset_trait_arg).unwrap(); let err = mem_type_check_v1(trait_with_subset_trait_arg).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1305,7 +1311,7 @@ fn test_trait_with_duplicate_method() { let err = mem_type_check(trait_with_duplicate_method).unwrap_err(); match *err.err { - CheckErrors::DefineTraitDuplicateMethod(method_name) => { + CheckErrorKind::DefineTraitDuplicateMethod(method_name) => { assert_eq!(method_name.as_str(), "foo"); } _ => panic!("Unexpected error: {err:?}"), @@ -1334,7 +1340,7 @@ fn test_trait_to_subtrait_and_back() { let err = mem_type_check(trait_to_subtrait_and_back).unwrap_err(); match *err.err { - CheckErrors::IncompatibleTrait(expected, actual) => { + CheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -1342,7 +1348,7 @@ fn test_trait_to_subtrait_and_back() { }; let err = mem_type_check_v1(trait_to_subtrait_and_back).unwrap_err(); match *err.err { - CheckErrors::TypeError(expected, found) => match (&*expected, &*found) { + CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1389,7 +1395,7 @@ fn test_if_branches_with_incompatible_trait_types() { )"; let err = mem_type_check(if_branches_with_incompatible_trait_types).unwrap_err(); match *err.err { - CheckErrors::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1403,7 +1409,7 @@ fn test_if_branches_with_incompatible_trait_types() { }; let err = mem_type_check_v1(if_branches_with_incompatible_trait_types).unwrap_err(); match *err.err { - CheckErrors::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1435,7 +1441,7 @@ fn test_if_branches_with_compatible_trait_types() { let err = mem_type_check(if_branches_with_compatible_trait_types).unwrap_err(); match *err.err { - CheckErrors::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1449,7 +1455,7 @@ fn test_if_branches_with_compatible_trait_types() { }; let err = mem_type_check_v1(if_branches_with_compatible_trait_types).unwrap_err(); match *err.err { - CheckErrors::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1507,8 +1513,8 @@ fn test_traits_multi_contract(#[case] version: ClarityVersion) { }); match result { Ok(_) if version >= ClarityVersion::Clarity2 => (), - Err(CheckError { err, .. }) if version < ClarityVersion::Clarity2 => match *err { - CheckErrors::TraitMethodUnknown(trait_name, function) => { + Err(StaticCheckError { err, .. }) if version < ClarityVersion::Clarity2 => match *err { + CheckErrorKind::TraitMethodUnknown(trait_name, function) => { assert_eq!(trait_name.as_str(), "a"); assert_eq!(function.as_str(), "do-it"); } @@ -3388,7 +3394,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? 123)", "int type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), )), @@ -3396,7 +3402,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? u123)", "uint type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), )), @@ -3404,7 +3410,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? true)", "bool type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::BoolType), )), @@ -3412,7 +3418,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? 0x1234)", "buffer type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(2u32).unwrap(), @@ -3422,7 +3428,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? \"60 percent of the time, it works every time\")", "ascii string", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(BufferLength::try_from(43u32).unwrap()), @@ -3432,7 +3438,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? u\"I am serious, and don't call me Shirley.\")", "utf8 string", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::UTF8(StringUTF8Length::try_from(40u32).unwrap()), @@ -3442,7 +3448,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? (list 1 2 3))", "list type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::ListType( ListTypeData::new_list(TypeSignature::IntType, 3).unwrap(), @@ -3452,7 +3458,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? { a: 1, b: u2 })", "tuple type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::TupleType( vec![ @@ -3467,7 +3473,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? (some u789))", "optional type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::new_option(TypeSignature::UIntType).unwrap()), )), @@ -3475,7 +3481,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? (ok true))", "response type", - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new( TypeSignature::new_response(TypeSignature::BoolType, TypeSignature::NoType) @@ -3492,7 +3498,9 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc let expected = if version >= ClarityVersion::Clarity4 { clarity4_expected } else { - &Err(CheckErrors::UnknownFunction("contract-hash?".to_string())) + &Err(CheckErrorKind::UnknownFunction( + "contract-hash?".to_string(), + )) }; assert_eq!(&actual, expected, "Failed for test case: {description}"); @@ -3548,7 +3556,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( &format!("(to-ascii? 0x{})", "ff".repeat(524285)), "oversized buffer type", - Err(CheckErrors::UnionTypeError( + Err(CheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(524285u32).unwrap(), @@ -3563,7 +3571,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? \"60 percent of the time, it works every time\")", "ascii string", - Err(CheckErrors::UnionTypeError( + Err(CheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(BufferLength::try_from(43u32).unwrap()), @@ -3573,7 +3581,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? (list 1 2 3))", "list type", - Err(CheckErrors::UnionTypeError( + Err(CheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::SequenceType(SequenceSubtype::ListType( ListTypeData::new_list(TypeSignature::IntType, 3).unwrap(), @@ -3583,7 +3591,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? { a: 1, b: u2 })", "tuple type", - Err(CheckErrors::UnionTypeError( + Err(CheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::TupleType( vec![ @@ -3598,7 +3606,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? (some u789))", "optional type", - Err(CheckErrors::UnionTypeError( + Err(CheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::new_option(TypeSignature::UIntType).unwrap()), )), @@ -3606,7 +3614,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? (ok true))", "response type", - Err(CheckErrors::UnionTypeError( + Err(CheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new( TypeSignature::new_response(TypeSignature::BoolType, TypeSignature::NoType) @@ -3623,7 +3631,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) let expected = if version >= ClarityVersion::Clarity4 { clarity4_expected } else { - &Err(CheckErrors::UnknownFunction("to-ascii?".to_string())) + &Err(CheckErrorKind::UnknownFunction("to-ascii?".to_string())) }; assert_eq!(&actual, expected, "Failed for test case: {description}"); diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs index ac978b277b6..0329605ee7c 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs @@ -20,11 +20,11 @@ use rstest::rstest; use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::{CheckError, CheckErrors, SyntaxBindingError}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError, SyntaxBindingError}; use crate::vm::analysis::mem_type_check as mem_run_analysis; use crate::vm::analysis::types::ContractAnalysis; use crate::vm::ast::build_ast; -use crate::vm::ast::errors::ParseErrors; +use crate::vm::ast::errors::ParseErrorKind; use crate::vm::tests::test_clarity_versions; use crate::vm::types::signatures::TypeSignature::OptionalType; use crate::vm::types::signatures::{ListTypeData, StringUTF8Length}; @@ -41,7 +41,9 @@ mod assets; pub mod contracts; /// Backwards-compatibility shim for type_checker tests. Runs at latest Clarity version. -pub fn mem_type_check(exp: &str) -> Result<(Option, ContractAnalysis), CheckError> { +pub fn mem_type_check( + exp: &str, +) -> Result<(Option, ContractAnalysis), StaticCheckError> { mem_run_analysis( exp, crate::vm::ClarityVersion::latest(), @@ -50,19 +52,19 @@ pub fn mem_type_check(exp: &str) -> Result<(Option, ContractAnaly } /// NOTE: runs at latest Clarity version -fn type_check_helper(exp: &str) -> Result { +fn type_check_helper(exp: &str) -> Result { mem_type_check(exp).map(|(type_sig_opt, _)| type_sig_opt.unwrap()) } fn type_check_helper_version( exp: &str, version: ClarityVersion, -) -> Result { +) -> Result { mem_run_analysis(exp, version, StacksEpochId::latest()) .map(|(type_sig_opt, _)| type_sig_opt.unwrap()) } -fn type_check_helper_v1(exp: &str) -> Result { +fn type_check_helper_v1(exp: &str) -> Result { type_check_helper_version(exp, ClarityVersion::Clarity1) } @@ -87,26 +89,26 @@ fn test_from_consensus_buff() { let bad = [ ( "(from-consensus-buff?)", - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), ), ( "(from-consensus-buff? 0x00 0x00 0x00)", - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), ), ( "(from-consensus-buff? 0x00 0x00)", - CheckErrors::InvalidTypeDescription, + CheckErrorKind::InvalidTypeDescription, ), ( "(from-consensus-buff? int u6)", - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::max_buffer().unwrap()), Box::new(TypeSignature::UIntType), ), ), ( "(from-consensus-buff? (buff 1048576) 0x00)", - CheckErrors::ValueTooLarge, + CheckErrorKind::ValueTooLarge, ), ]; @@ -183,26 +185,26 @@ fn test_to_consensus_buff() { let bad = [ ( "(to-consensus-buff?)", - CheckErrors::IncorrectArgumentCount(1, 0), + CheckErrorKind::IncorrectArgumentCount(1, 0), ), ( "(to-consensus-buff? 0x00 0x00)", - CheckErrors::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 2), ), ( "(define-private (my-func (x (buff 1048576))) (to-consensus-buff? x))", - CheckErrors::ValueTooLarge, + CheckErrorKind::ValueTooLarge, ), ( "(define-private (my-func (x (buff 1048570))) (to-consensus-buff? x))", - CheckErrors::ValueTooLarge, + CheckErrorKind::ValueTooLarge, ), ( "(define-private (my-func (x (buff 1048567))) (to-consensus-buff? x))", - CheckErrors::ValueTooLarge, + CheckErrorKind::ValueTooLarge, ), ]; @@ -261,10 +263,10 @@ fn test_get_block_info() { "(get-block-info? time)", ]; let bad_expected = [ - CheckErrors::NoSuchBlockInfoProperty("none".to_string()), - CheckErrors::TypeError(Box::new(UIntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::RequiresAtLeastArguments(2, 1), + CheckErrorKind::NoSuchBlockInfoProperty("none".to_string()), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::RequiresAtLeastArguments(2, 1), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -296,7 +298,7 @@ fn test_get_block_info() { } for good_test in good_v210.iter() { - if let CheckErrors::NoSuchBlockInfoProperty(_) = + if let CheckErrorKind::NoSuchBlockInfoProperty(_) = *type_check_helper_v1(good_test).unwrap_err().err { } else { @@ -317,10 +319,10 @@ fn test_get_burn_block_info() { r#"(get-burn-block-info? header-hash "a")"#, ]; let bad_expected = [ - CheckErrors::NoSuchBlockInfoProperty("none".to_string()), - CheckErrors::IncorrectArgumentCount(2, 0), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::TypeError( + CheckErrorKind::NoSuchBlockInfoProperty("none".to_string()), + CheckErrorKind::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError( Box::new(UIntType), Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(1u32).expect("BufferLength::try_from failed"), @@ -361,10 +363,10 @@ fn test_define_trait(#[case] version: ClarityVersion, #[case] epoch: StacksEpoch "(define-trait)", ]; let bad_expected = [ - CheckErrors::InvalidTypeDescription, - CheckErrors::DefineTraitBadSignature, - CheckErrors::DefineTraitBadSignature, - CheckErrors::InvalidTypeDescription, + CheckErrorKind::InvalidTypeDescription, + CheckErrorKind::DefineTraitBadSignature, + CheckErrorKind::DefineTraitBadSignature, + CheckErrorKind::InvalidTypeDescription, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -373,8 +375,8 @@ fn test_define_trait(#[case] version: ClarityVersion, #[case] epoch: StacksEpoch let bad = ["(define-trait trait-1)", "(define-trait)"]; let bad_expected = [ - ParseErrors::DefineTraitBadSignature, - ParseErrors::DefineTraitBadSignature, + ParseErrorKind::DefineTraitBadSignature, + ParseErrorKind::DefineTraitBadSignature, ]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -393,10 +395,10 @@ fn test_use_trait(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) "(use-trait)", ]; let bad_expected = [ - ParseErrors::ImportTraitBadSignature, - ParseErrors::ImportTraitBadSignature, - ParseErrors::ImportTraitBadSignature, - ParseErrors::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, + ParseErrorKind::ImportTraitBadSignature, ]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -410,8 +412,8 @@ fn test_use_trait(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) fn test_impl_trait(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) { let bad = ["(impl-trait trait-1)", "(impl-trait)"]; let bad_expected = [ - ParseErrors::ImplTraitBadSignature, - ParseErrors::ImplTraitBadSignature, + ParseErrorKind::ImplTraitBadSignature, + ParseErrorKind::ImplTraitBadSignature, ]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -459,42 +461,42 @@ fn test_stx_ops() { "(stx-get-balance 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)" ]; let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), ), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 5), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(BoolType)), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 5), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + CheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(OptionalType(Box::from(PrincipalType))), ), - CheckErrors::IncorrectArgumentCount(3, 4), - CheckErrors::TypeError( + CheckErrorKind::IncorrectArgumentCount(3, 4), + CheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), ), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(4, 5), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(BoolType)), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(4, 5), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + CheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(OptionalType(Box::from(PrincipalType))), ), - CheckErrors::IncorrectArgumentCount(4, 3), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(BoolType)), - CheckErrors::IncorrectArgumentCount(2, 3), - CheckErrors::TypeError(Box::new(PrincipalType), Box::new(BoolType)), - CheckErrors::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(4, 3), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), + CheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + CheckErrorKind::IncorrectArgumentCount(1, 2), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -523,7 +525,7 @@ fn test_tx_sponsor() { ]; let bad = ["(stx-transfer? u10 tx-sponsor? 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G)"]; - let bad_expected = [CheckErrors::TypeError( + let bad_expected = [CheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(OptionalType(Box::from(PrincipalType))), )]; @@ -591,7 +593,7 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack let bad = [ ( "(unwrap-err! (some 2) 2)", - CheckErrors::ExpectedResponseType(Box::new(TypeSignature::from_string( + CheckErrorKind::ExpectedResponseType(Box::new(TypeSignature::from_string( "(optional int)", version, epoch, @@ -599,88 +601,92 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack ), ( "(unwrap! (err 3) 2)", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-err-panic (ok 3))", - CheckErrors::CouldNotDetermineResponseErrType, + CheckErrorKind::CouldNotDetermineResponseErrType, ), ( "(unwrap-panic none)", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(define-private (foo) (if (> 1 0) none none)) (unwrap-panic (foo))", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-panic (err 3))", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(match none inner-value (/ 1 0) (+ 1 8))", - CheckErrors::CouldNotDetermineMatchTypes, + CheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (ok 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrors::CouldNotDetermineMatchTypes, + CheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (err 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrors::CouldNotDetermineMatchTypes, + CheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(define-private (foo) (if (> 1 0) (ok 1) (err u8))) (match (foo) ok-val (+ 1 ok-val) err-val (/ err-val u0))", - CheckErrors::MatchArmsMustMatch( + CheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value) (> 1 28))", - CheckErrors::MatchArmsMustMatch( + CheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::BoolType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value))", - CheckErrors::BadMatchOptionSyntax(Box::new(CheckErrors::IncorrectArgumentCount(4, 3))), + CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::IncorrectArgumentCount( + 4, 3, + ))), ), ( "(match (ok 1) inner-value (+ 1 inner-value))", - CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::IncorrectArgumentCount( - 5, 3, - ))), + CheckErrorKind::BadMatchResponseSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(5, 3), + )), ), ( "(match (ok 1) 1 (+ 1 1) err-val (+ 2 err-val))", - CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)), + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), ), ( "(match (ok 1) ok-val (+ 1 1) (+ 3 4) (+ 2 err-val))", - CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)), + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), ), ( "(match (some 1) 2 (+ 1 1) (+ 3 4))", - CheckErrors::BadMatchOptionSyntax(Box::new(CheckErrors::ExpectedName)), + CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)), ), - ("(match)", CheckErrors::RequiresAtLeastArguments(1, 0)), + ("(match)", CheckErrorKind::RequiresAtLeastArguments(1, 0)), ( "(match 1 ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrors::BadMatchInput(Box::new(TypeSignature::from_string("int", version, epoch))), + CheckErrorKind::BadMatchInput(Box::new(TypeSignature::from_string( + "int", version, epoch, + ))), ), ( "(default-to 3 5)", - CheckErrors::ExpectedOptionalType(Box::new(TypeSignature::IntType)), + CheckErrorKind::ExpectedOptionalType(Box::new(TypeSignature::IntType)), ), ( "(define-private (foo (x int)) (match (some 3) x (+ x 2) 5))", - CheckErrors::NameAlreadyUsed("x".to_string()), + CheckErrorKind::NameAlreadyUsed("x".to_string()), ), ( "(define-private (t1 (x uint)) (if (> x u1) (ok x) (err false))) @@ -688,7 +694,7 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack (if (> x u4) (err u3) (ok (+ u2 (try! (t1 x))))))", - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -703,7 +709,7 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack "(define-private (t1 (x uint)) (if (> x u1) (ok x) (err false))) (define-private (t2 (x uint)) (> u2 (try! (t1 x))))", - CheckErrors::ReturnTypesMustMatch( + CheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -713,18 +719,24 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack ), ( "(try! (ok 3))", - CheckErrors::CouldNotDetermineResponseErrType, + CheckErrorKind::CouldNotDetermineResponseErrType, + ), + ( + "(try! none)", + CheckErrorKind::CouldNotDetermineResponseOkType, ), - ("(try! none)", CheckErrors::CouldNotDetermineResponseOkType), ( "(try! (err 3))", - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(try! 3)", - CheckErrors::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), + CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), + ), + ( + "(try! (ok 3) 4)", + CheckErrorKind::IncorrectArgumentCount(1, 2), ), - ("(try! (ok 3) 4)", CheckErrors::IncorrectArgumentCount(1, 2)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -746,11 +758,11 @@ fn test_at_block() { let bad = [ ( "(at-block (sha512 u0) u1)", - CheckErrors::TypeError(Box::new(BUFF_32.clone()), Box::new(BUFF_64.clone())), + CheckErrorKind::TypeError(Box::new(BUFF_32.clone()), Box::new(BUFF_64.clone())), ), ( "(at-block (sha256 u0) u1 u2)", - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), ), ]; @@ -770,7 +782,7 @@ fn test_at_block() { fn test_trait_reference_unknown(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) { let bad = [( "(+ 1 )", - ParseErrors::TraitReferenceUnknown("kvstore".to_string()), + ParseErrorKind::TraitReferenceUnknown("kvstore".to_string()), )]; let contract_identifier = QualifiedContractIdentifier::transient(); @@ -784,7 +796,7 @@ fn test_trait_reference_unknown(#[case] version: ClarityVersion, #[case] epoch: fn test_unexpected_use_of_field_or_trait_reference() { let bad = [( "(+ 1 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.contract.field)", - CheckErrors::UnexpectedTraitOrFieldReference, + CheckErrorKind::UnexpectedTraitOrFieldReference, )]; for (bad_test, expected) in bad.iter() { @@ -831,23 +843,23 @@ fn test_bitwise_bad_checks() { "(bit-or 1 2 u4)", ]; let bad_expected = [ - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::UnionTypeError( + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(5u32).unwrap(), )))), ), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)), + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -872,12 +884,12 @@ fn test_simple_arithmetic_checks() { "(and (or true false) (+ 1 2 3))", ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::RequiresAtLeastArguments(1, 0), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::UndefinedVariable("x".to_string()), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::RequiresAtLeastArguments(1, 0), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::UndefinedVariable("x".to_string()), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -938,14 +950,14 @@ fn test_simple_hash_checks() { for bad_test in bad_types.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrors::UnionTypeError(_, _) + CheckErrorKind::UnionTypeError(_, _) )); } for bad_test in invalid_args.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrors::IncorrectArgumentCount(_, _) + CheckErrorKind::IncorrectArgumentCount(_, _) )); } } @@ -968,10 +980,10 @@ fn test_simple_ifs() { ]; let bad_expected = [ - CheckErrors::IfArmsMustMatch(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IfArmsMustMatch(Box::new(ascii_type(1)), Box::new(BoolType)), - CheckErrors::IncorrectArgumentCount(3, 0), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IfArmsMustMatch(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IfArmsMustMatch(Box::new(ascii_type(1)), Box::new(BoolType)), + CheckErrorKind::IncorrectArgumentCount(3, 0), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1004,9 +1016,9 @@ fn test_simple_lets() { ]; let bad_expected = [ - CheckErrors::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), - CheckErrors::TypeError( + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), + CheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), @@ -1079,47 +1091,47 @@ fn test_index_of() { ]; let bad_expected = [ - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrors::TypeError( + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_buffer().unwrap()), Box::new(TypeSignature::min_string_ascii().unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_string_utf8().unwrap()), Box::new(TypeSignature::min_string_ascii().unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_string_ascii().unwrap()), Box::new(TypeSignature::min_string_utf8().unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 1).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::IntType, 2).unwrap()), ), - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrors::TypeError( + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_buffer().unwrap()), Box::new(TypeSignature::min_string_ascii().unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_string_utf8().unwrap()), Box::new(TypeSignature::min_string_ascii().unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::min_string_ascii().unwrap()), Box::new(TypeSignature::min_string_utf8().unwrap()), ), - CheckErrors::CouldNotDetermineType, - CheckErrors::CouldNotDetermineType, - CheckErrors::CouldNotDetermineType, + CheckErrorKind::CouldNotDetermineType, + CheckErrorKind::CouldNotDetermineType, + CheckErrorKind::CouldNotDetermineType, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -1163,16 +1175,16 @@ fn test_element_at() { ]; let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrors::TypeError( + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1204,12 +1216,12 @@ fn test_eqs(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::TypeError( Box::new(TypeSignature::list_of(IntType, 1).unwrap()), Box::new(IntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(optional bool)", version, @@ -1247,9 +1259,9 @@ fn test_asserts() { ]; let bad_expected = [ - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1313,23 +1325,23 @@ fn test_lists() { "(map + (list 1 2 3 4 5) (list true true true true true))", ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(buff_type(20))), - CheckErrors::TypeError(Box::new(BoolType), Box::new(buff_type(20))), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 3), - CheckErrors::UnknownFunction("ynot".to_string()), - CheckErrors::IllegalOrUnknownFunctionApplication("if".to_string()), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), - CheckErrors::ExpectedSequence(Box::new(UIntType)), - CheckErrors::ExpectedSequence(Box::new(IntType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), + CheckErrorKind::UnknownFunction("ynot".to_string()), + CheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + CheckErrorKind::ExpectedSequence(Box::new(UIntType)), + CheckErrorKind::ExpectedSequence(Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1370,20 +1382,20 @@ fn test_buff() { "(len 1)", ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(buff_type(20))), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 3), - CheckErrors::UnknownFunction("ynot".to_string()), - CheckErrors::IllegalOrUnknownFunctionApplication("if".to_string()), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), - CheckErrors::ExpectedSequence(Box::new(UIntType)), - CheckErrors::ExpectedSequence(Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 3), + CheckErrorKind::UnknownFunction("ynot".to_string()), + CheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + CheckErrorKind::ExpectedSequence(Box::new(UIntType)), + CheckErrorKind::ExpectedSequence(Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1451,9 +1463,9 @@ fn test_native_as_max_len() { "(as-max-len? 0x01 u1048577)", ]; let bad_expected = [ - CheckErrors::ValueTooLarge, - CheckErrors::ValueTooLarge, - CheckErrors::ValueTooLarge, + CheckErrorKind::ValueTooLarge, + CheckErrorKind::ValueTooLarge, + CheckErrorKind::ValueTooLarge, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1497,9 +1509,9 @@ fn test_native_append() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 1), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1537,9 +1549,9 @@ fn test_slice_list() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 2), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1568,9 +1580,9 @@ fn test_slice_buff() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 2), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1602,9 +1614,9 @@ fn test_slice_ascii() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 2), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1633,9 +1645,9 @@ fn test_slice_utf8() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 2), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1681,17 +1693,17 @@ fn test_replace_at_list() { ]; let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(IntType), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 4), - CheckErrors::IncorrectArgumentCount(3, 2), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 4), + CheckErrorKind::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError( Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), @@ -1739,20 +1751,20 @@ fn test_replace_at_buff() { let buff_len = BufferLength::try_from(1u32).unwrap(); let buff_len_two = BufferLength::try_from(2u32).unwrap(); let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(BufferType(buff_len.clone()))), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(BufferType(buff_len.clone()))), Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), ), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 4), - CheckErrors::IncorrectArgumentCount(3, 2), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 4), + CheckErrorKind::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError( Box::new(SequenceType(BufferType(buff_len))), Box::new(SequenceType(BufferType(buff_len_two))), ), @@ -1797,20 +1809,20 @@ fn test_replace_at_ascii() { let buff_len = BufferLength::try_from(1u32).unwrap(); let buff_len_two = BufferLength::try_from(2u32).unwrap(); let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), Box::new(SequenceType(BufferType(buff_len.clone()))), ), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 4), - CheckErrors::IncorrectArgumentCount(3, 2), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 4), + CheckErrorKind::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII(buff_len)))), Box::new(SequenceType(StringType(ASCII(buff_len_two)))), ), @@ -1855,20 +1867,20 @@ fn test_replace_at_utf8() { let str_len = StringUTF8Length::try_from(1u32).unwrap(); let str_len_two = StringUTF8Length::try_from(2u32).unwrap(); let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8(str_len.clone())))), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8(str_len.clone())))), Box::new(SequenceType(BufferType(buff_len))), ), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(3, 4), - CheckErrors::IncorrectArgumentCount(3, 2), - CheckErrors::TypeError( + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(3, 4), + CheckErrorKind::IncorrectArgumentCount(3, 2), + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8(str_len)))), Box::new(SequenceType(StringType(UTF8(str_len_two)))), ), @@ -1897,9 +1909,9 @@ fn test_native_concat() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::IncorrectArgumentCount(2, 1), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1982,8 +1994,8 @@ fn test_tuples() { ]; let bad_expected = [ - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(BoolType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -2007,7 +2019,7 @@ fn test_empty_tuple_should_fail() { assert_eq!( *mem_type_check(contract_src).unwrap_err().err, - CheckErrors::EmptyTuplesNotAllowed, + CheckErrorKind::EmptyTuplesNotAllowed, ); } @@ -2087,9 +2099,9 @@ fn test_simple_uints() { let bad = ["(> u1 1)", "(to-uint true)", "(to-int false)"]; let bad_expected = [ - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrors::TypeError(Box::new(UIntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -2121,9 +2133,9 @@ fn test_buffer_to_ints() { ]; let bad_expected = [ - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 0), - CheckErrors::TypeError( + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 0), + CheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap(), ))), @@ -2131,7 +2143,7 @@ fn test_buffer_to_ints() { BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap(), ))), @@ -2195,37 +2207,37 @@ fn test_string_to_ints() { ]; let bad_expected = [ - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 0), - CheckErrors::UnionTypeError( + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 0), + CheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(BufferType( BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrors::UnionTypeError( + CheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(1_u32).unwrap(), )))), ), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 0), - CheckErrors::UnionTypeError( + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 0), + CheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(BufferType( BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrors::UnionTypeError( + CheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(1_u32).unwrap(), )))), ), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 0), - CheckErrors::UnionTypeError( + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 0), + CheckErrorKind::UnionTypeError( vec![ TypeSignature::max_string_ascii().unwrap(), TypeSignature::max_string_utf8().unwrap(), @@ -2234,16 +2246,16 @@ fn test_string_to_ints() { BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrors::UnionTypeError( + CheckErrorKind::UnionTypeError( vec![ TypeSignature::max_string_ascii().unwrap(), TypeSignature::max_string_utf8().unwrap(), ], Box::new(IntType), ), - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 0), - CheckErrors::UnionTypeError( + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 0), + CheckErrorKind::UnionTypeError( vec![ TypeSignature::max_string_ascii().unwrap(), TypeSignature::max_string_utf8().unwrap(), @@ -2252,7 +2264,7 @@ fn test_string_to_ints() { BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrors::UnionTypeError( + CheckErrorKind::UnionTypeError( vec![ TypeSignature::max_string_ascii().unwrap(), TypeSignature::max_string_utf8().unwrap(), @@ -2307,7 +2319,7 @@ fn test_response_inference(#[case] version: ClarityVersion, #[case] epoch: Stack ]; let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(response bool int)", version, @@ -2315,8 +2327,8 @@ fn test_response_inference(#[case] version: ClarityVersion, #[case] epoch: Stack )), Box::new(BoolType), ), - CheckErrors::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), - CheckErrors::CouldNotDetermineResponseOkType, + CheckErrorKind::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), + CheckErrorKind::CouldNotDetermineResponseOkType, ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -2434,7 +2446,7 @@ fn test_options(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) { if version < ClarityVersion::Clarity2 { assert!( match *mem_run_analysis(contract, version, epoch).unwrap_err().err { - CheckErrors::TypeError(t1, t2) => { + CheckErrorKind::TypeError(t1, t2) => { *t1 == TypeSignature::from_string("(optional bool)", version, epoch) && *t2 == TypeSignature::from_string("(optional int)", version, epoch) } @@ -2444,7 +2456,7 @@ fn test_options(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) { } else { assert!( match *mem_run_analysis(contract, version, epoch).unwrap_err().err { - CheckErrors::TypeError(t1, t2) => { + CheckErrorKind::TypeError(t1, t2) => { *t1 == TypeSignature::from_string("bool", version, epoch) && *t2 == TypeSignature::from_string("int", version, epoch) } @@ -2553,7 +2565,7 @@ fn test_missing_value_on_declaration_should_fail() { let res = mem_type_check(contract_src).unwrap_err(); assert!(matches!( *res.err, - CheckErrors::IncorrectArgumentCount(_, _) + CheckErrorKind::IncorrectArgumentCount(_, _) )); } @@ -2564,7 +2576,7 @@ fn test_mismatching_type_on_declaration_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } #[test] @@ -2580,7 +2592,7 @@ fn test_mismatching_type_on_update_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } #[test] @@ -2592,7 +2604,7 @@ fn test_direct_access_to_persisted_var_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } #[test] @@ -2607,7 +2619,7 @@ fn test_data_var_shadowed_by_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2620,7 +2632,7 @@ fn test_mutating_unknown_data_var_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NoSuchDataVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); } #[test] @@ -2631,7 +2643,7 @@ fn test_accessing_unknown_data_var_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NoSuchDataVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); } #[test] @@ -2642,7 +2654,7 @@ fn test_let_shadowed_by_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2654,7 +2666,7 @@ fn test_let_shadowed_by_nested_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2667,7 +2679,7 @@ fn test_define_constant_shadowed_by_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2679,7 +2691,7 @@ fn test_define_constant_shadowed_by_argument_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::NameAlreadyUsed(_))); + assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2879,7 +2891,7 @@ fn test_fetch_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -2894,7 +2906,7 @@ fn test_fetch_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -2936,7 +2948,7 @@ fn test_insert_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -2954,7 +2966,7 @@ fn test_insert_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -2994,7 +3006,7 @@ fn test_delete_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -3009,7 +3021,7 @@ fn test_delete_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -3053,7 +3065,7 @@ fn test_set_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::TypeError(_, _))); + assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); } } @@ -3071,7 +3083,7 @@ fn test_set_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrors::UndefinedVariable(_))); + assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); } } @@ -3187,7 +3199,7 @@ fn test_buff_negative_len() { (func 0x00)"; let res = mem_type_check(contract_src).unwrap_err(); - assert_eq!(*res.err, CheckErrors::ValueOutOfBounds); + assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); } #[test] @@ -3196,7 +3208,7 @@ fn test_string_ascii_negative_len() { (func \"\")"; let res = mem_type_check(contract_src).unwrap_err(); - assert_eq!(*res.err, CheckErrors::ValueOutOfBounds); + assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); } #[test] @@ -3205,7 +3217,7 @@ fn test_string_utf8_negative_len() { (func u\"\")"; let res = mem_type_check(contract_src).unwrap_err(); - assert_eq!(*res.err, CheckErrors::ValueOutOfBounds); + assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); } #[test] @@ -3249,7 +3261,7 @@ fn test_comparison_types() { r#"(>= "aaa" "aaa" "aaa")"#, ]; let bad_expected = [ - CheckErrors::UnionTypeError( + CheckErrorKind::UnionTypeError( vec![ IntType, UIntType, @@ -3263,7 +3275,7 @@ fn test_comparison_types() { ], Box::new(PrincipalType), ), - CheckErrors::UnionTypeError( + CheckErrorKind::UnionTypeError( vec![ IntType, UIntType, @@ -3279,7 +3291,7 @@ fn test_comparison_types() { ListTypeData::new_list(IntType, 3).unwrap(), ))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8( StringUTF8Length::try_from(3u32).unwrap(), )))), @@ -3287,7 +3299,7 @@ fn test_comparison_types() { BufferLength::try_from(2_u32).unwrap(), )))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(3_u32).unwrap(), )))), @@ -3295,7 +3307,7 @@ fn test_comparison_types() { BufferLength::try_from(2_u32).unwrap(), ))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), @@ -3303,7 +3315,7 @@ fn test_comparison_types() { StringUTF8Length::try_from(3u32).unwrap(), )))), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), @@ -3311,9 +3323,9 @@ fn test_comparison_types() { BufferLength::try_from(3_u32).unwrap(), )))), ), - CheckErrors::IncorrectArgumentCount(2, 0), - CheckErrors::IncorrectArgumentCount(2, 1), - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 3), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -3342,9 +3354,9 @@ fn test_principal_destruct() { r#"(principal-destruct? 0x22)"#, ]; let bad_expected = [ - CheckErrors::IncorrectArgumentCount(1, 2), - CheckErrors::IncorrectArgumentCount(1, 0), - CheckErrors::TypeError( + CheckErrorKind::IncorrectArgumentCount(1, 2), + CheckErrorKind::IncorrectArgumentCount(1, 0), + CheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(BUFF_1.clone()), ), @@ -3398,32 +3410,32 @@ fn test_principal_construct() { // Too few arguments, just has the `(buff 1)`. ( r#"(principal-construct? 0x22)"#, - CheckErrors::RequiresAtLeastArguments(2, 1), + CheckErrorKind::RequiresAtLeastArguments(2, 1), ), // Too few arguments, just hs the `(buff 20)`. ( r#"(principal-construct? 0xfa6bf38ed557fe417333710d6033e9419391a320)"#, - CheckErrors::RequiresAtLeastArguments(2, 1), + CheckErrorKind::RequiresAtLeastArguments(2, 1), ), // The first buffer is too long, should be `(buff 1)`. ( r#"(principal-construct? 0xfa6bf38ed557fe417333710d6033e9419391a320 0xfa6bf38ed557fe417333710d6033e9419391a320)"#, - CheckErrors::TypeError(Box::new(BUFF_1.clone()), Box::new(BUFF_20.clone())), + CheckErrorKind::TypeError(Box::new(BUFF_1.clone()), Box::new(BUFF_20.clone())), ), // The second buffer is too long, should be `(buff 20)`. ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a32009)"#, - CheckErrors::TypeError(Box::new(BUFF_20.clone()), Box::new(BUFF_21.clone())), + CheckErrorKind::TypeError(Box::new(BUFF_20.clone()), Box::new(BUFF_21.clone())), ), // `int` argument instead of `(buff 1)` for version. ( r#"(principal-construct? 22 0xfa6bf38ed557fe417333710d6033e9419391a320)"#, - CheckErrors::TypeError(Box::new(BUFF_1.clone()), Box::new(IntType.clone())), + CheckErrorKind::TypeError(Box::new(BUFF_1.clone()), Box::new(IntType.clone())), ), // `name` argument is too long ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a320 "foooooooooooooooooooooooooooooooooooooooo")"#, - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::contract_name_string_ascii_type().unwrap()), Box::new(TypeSignature::bound_string_ascii_type(41).unwrap()), ), @@ -3431,7 +3443,7 @@ fn test_principal_construct() { // bad argument type for `name` ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a320 u123)"#, - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::contract_name_string_ascii_type().unwrap()), Box::new(UIntType), ), @@ -3439,7 +3451,7 @@ fn test_principal_construct() { // too many arguments ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a320 "foo" "bar")"#, - CheckErrors::RequiresAtMostArguments(3, 4), + CheckErrorKind::RequiresAtMostArguments(3, 4), ), ]; @@ -3493,7 +3505,7 @@ fn test_trait_args() { )"]; let contract_identifier = QualifiedContractIdentifier::transient(); - let bad_expected = [CheckErrors::IncompatibleTrait( + let bad_expected = [CheckErrorKind::IncompatibleTrait( Box::new(TraitIdentifier { name: ClarityName::from("trait-foo"), contract_identifier: contract_identifier.clone(), @@ -3659,15 +3671,15 @@ fn test_list_arg(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ", ]; let bad_expected = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::IntType, 4).unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::UIntType, 1).unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new( TypeSignature::list_of( @@ -3679,15 +3691,15 @@ fn test_list_arg(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ), ]; let bad_expected2 = [ - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::IntType, 4).unwrap()), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::list_of(TypeSignature::NoType, 0).unwrap()), ), @@ -3799,17 +3811,17 @@ fn test_simple_bad_syntax_bindings() { "(from-consensus-buff? (tuple (a (string-ascii -12))) 0x00)", ]; let expected = [ - CheckErrors::BadSyntaxBinding(SyntaxBindingError::let_binding_not_list(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_list(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::eval_binding_invalid_length(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_atom(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_list(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::tuple_cons_invalid_length(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_atom(0)), - CheckErrors::ValueOutOfBounds, - CheckErrors::ValueOutOfBounds, + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_list(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_list(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::eval_binding_invalid_length(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_atom(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_list(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_invalid_length(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_atom(0)), + CheckErrorKind::ValueOutOfBounds, + CheckErrorKind::ValueOutOfBounds, ]; for (bad_code, expected_err) in bad.iter().zip(expected.iter()) { @@ -3833,9 +3845,9 @@ fn test_nested_bad_type_signature_syntax_bindings() { ]; let expected = [ - CheckErrors::ValueOutOfBounds, - CheckErrors::InvalidTypeDescription, - CheckErrors::ValueOutOfBounds, + CheckErrorKind::ValueOutOfBounds, + CheckErrorKind::InvalidTypeDescription, + CheckErrorKind::ValueOutOfBounds, ]; for (bad_code, expected_err) in bad.iter().zip(expected.iter()) { diff --git a/clarity/src/vm/analysis/types.rs b/clarity/src/vm/analysis/types.rs index 145ce59bd3c..1be8f15918e 100644 --- a/clarity/src/vm/analysis/types.rs +++ b/clarity/src/vm/analysis/types.rs @@ -22,7 +22,7 @@ use stacks_common::types::StacksEpochId; use crate::vm::analysis::analysis_db::AnalysisDatabase; use crate::vm::analysis::contract_interface_builder::ContractInterface; -use crate::vm::analysis::errors::{CheckError, CheckErrors}; +use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError}; use crate::vm::analysis::type_checker::contexts::TypeMap; use crate::vm::costs::LimitedCostTracker; use crate::vm::types::signatures::FunctionSignature; @@ -39,7 +39,7 @@ pub trait AnalysisPass { epoch: &StacksEpochId, contract_analysis: &mut ContractAnalysis, analysis_db: &mut AnalysisDatabase, - ) -> Result<(), CheckError>; + ) -> Result<(), StaticCheckError>; } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] @@ -230,7 +230,7 @@ impl ContractAnalysis { epoch: &StacksEpochId, trait_identifier: &TraitIdentifier, trait_definition: &BTreeMap, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { let trait_name = trait_identifier.name.to_string(); for (func_name, expected_sig) in trait_definition.iter() { @@ -242,7 +242,7 @@ impl ContractAnalysis { | (None, Some(FunctionType::Fixed(func))) => { let args_sig = func.args.iter().map(|a| a.signature.clone()).collect(); if !expected_sig.check_args_trait_compliance(epoch, args_sig)? { - return Err(CheckErrors::BadTraitImplementation( + return Err(CheckErrorKind::BadTraitImplementation( trait_name, func_name.to_string(), ) @@ -250,7 +250,7 @@ impl ContractAnalysis { } if !expected_sig.returns.admits_type(epoch, &func.returns)? { - return Err(CheckErrors::BadTraitImplementation( + return Err(CheckErrorKind::BadTraitImplementation( trait_name, func_name.to_string(), ) @@ -258,7 +258,7 @@ impl ContractAnalysis { } } (_, _) => { - return Err(CheckErrors::BadTraitImplementation( + return Err(CheckErrorKind::BadTraitImplementation( trait_name, func_name.to_string(), ) diff --git a/clarity/src/vm/ast/definition_sorter/mod.rs b/clarity/src/vm/ast/definition_sorter/mod.rs index bc12151af1b..153914110f3 100644 --- a/clarity/src/vm/ast/definition_sorter/mod.rs +++ b/clarity/src/vm/ast/definition_sorter/mod.rs @@ -18,7 +18,7 @@ use std::collections::{HashMap, HashSet}; use clarity_types::representations::ClarityName; -use crate::vm::ast::errors::{ParseError, ParseErrors, ParseResult}; +use crate::vm::ast::errors::{ParseError, ParseErrorKind, ParseResult}; use crate::vm::ast::types::ContractAST; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{runtime_cost, CostTracker}; @@ -99,7 +99,7 @@ impl DefinitionSorter { .map(|i| i.0.to_string()) .collect::>(); - let error = ParseError::new(ParseErrors::CircularReference(functions_names)); + let error = ParseError::new(ParseErrorKind::CircularReference(functions_names)); return Err(error); } @@ -421,7 +421,7 @@ impl Graph { let list = self .adjacency_list .get_mut(src_expr_index) - .ok_or(ParseErrors::InterpreterFailure)?; + .ok_or(ParseErrorKind::InterpreterFailure)?; list.push(dst_expr_index); Ok(()) } @@ -443,7 +443,7 @@ impl Graph { for node in self.adjacency_list.iter() { total = total .checked_add(node.len() as u64) - .ok_or(ParseErrors::CostOverflow)?; + .ok_or(ParseErrorKind::CostOverflow)?; } Ok(total) } diff --git a/clarity/src/vm/ast/definition_sorter/tests.rs b/clarity/src/vm/ast/definition_sorter/tests.rs index 9bbb3211781..c05611c3b20 100644 --- a/clarity/src/vm/ast/definition_sorter/tests.rs +++ b/clarity/src/vm/ast/definition_sorter/tests.rs @@ -21,7 +21,7 @@ use rstest_reuse::{self, *}; use crate::vm::analysis::type_checker::v2_1::tests::mem_type_check as run_analysis_helper; use crate::vm::ast::definition_sorter::DefinitionSorter; -use crate::vm::ast::errors::{ParseErrors, ParseResult}; +use crate::vm::ast::errors::{ParseErrorKind, ParseResult}; use crate::vm::ast::expression_identifier::ExpressionIdentifier; use crate::vm::ast::parser; use crate::vm::ast::types::ContractAST; @@ -96,7 +96,7 @@ fn should_raise_dependency_cycle_case_1(#[case] version: ClarityVersion) { "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -109,7 +109,7 @@ fn should_raise_dependency_cycle_case_2(#[case] version: ClarityVersion) { "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -131,7 +131,7 @@ fn should_raise_dependency_cycle_case_let(#[case] version: ClarityVersion) { "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -153,7 +153,7 @@ fn should_raise_dependency_cycle_case_get(#[case] version: ClarityVersion) { "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -177,7 +177,7 @@ fn should_raise_dependency_cycle_case_fetch_entry(#[case] version: ClarityVersio "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -201,7 +201,7 @@ fn should_raise_dependency_cycle_case_delete_entry(#[case] version: ClarityVersi "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -225,7 +225,7 @@ fn should_raise_dependency_cycle_case_set_entry(#[case] version: ClarityVersion) "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -249,7 +249,7 @@ fn should_raise_dependency_cycle_case_insert_entry(#[case] version: ClarityVersi "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] @@ -260,7 +260,7 @@ fn should_raise_dependency_cycle_case_fetch_contract_entry(#[case] version: Clar "#; let err = run_scoped_parsing_helper(contract, version).unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[apply(test_clarity_versions_definition_sorter)] diff --git a/clarity/src/vm/ast/errors.rs b/clarity/src/vm/ast/errors.rs index 2b9b5beb3c5..897d4fed24e 100644 --- a/clarity/src/vm/ast/errors.rs +++ b/clarity/src/vm/ast/errors.rs @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pub use clarity_types::errors::ast::{ParseError, ParseErrors, ParseResult, PlacedError}; +pub use clarity_types::errors::ast::{ParseError, ParseErrorKind, ParseResult, PlacedError}; diff --git a/clarity/src/vm/ast/expression_identifier/mod.rs b/clarity/src/vm/ast/expression_identifier/mod.rs index 13b9aac2bd1..d73d99dc242 100644 --- a/clarity/src/vm/ast/expression_identifier/mod.rs +++ b/clarity/src/vm/ast/expression_identifier/mod.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::vm::ast::errors::{ParseError, ParseErrors, ParseResult}; +use crate::vm::ast::errors::{ParseError, ParseErrorKind, ParseResult}; use crate::vm::ast::types::ContractAST; use crate::vm::representations::SymbolicExpressionCommon; use crate::vm::ClarityVersion; @@ -22,7 +22,7 @@ use crate::vm::ClarityVersion; fn inner_relabel(args: &mut [T], index: u64) -> ParseResult { let mut current = index .checked_add(1) - .ok_or(ParseError::new(ParseErrors::TooManyExpressions))?; + .ok_or(ParseError::new(ParseErrorKind::TooManyExpressions))?; for expression in &mut args[..] { expression.set_id(current); current = if let Some(exprs) = expression.match_list_mut() { @@ -30,7 +30,7 @@ fn inner_relabel(args: &mut [T], index: u64) -> Par } else { current .checked_add(1) - .ok_or(ParseError::new(ParseErrors::TooManyExpressions)) + .ok_or(ParseError::new(ParseErrorKind::TooManyExpressions)) }?; } Ok(current) diff --git a/clarity/src/vm/ast/mod.rs b/clarity/src/vm/ast/mod.rs index da65d20521b..1947a5c602d 100644 --- a/clarity/src/vm/ast/mod.rs +++ b/clarity/src/vm/ast/mod.rs @@ -49,7 +49,8 @@ pub fn parse( source_code: &str, version: ClarityVersion, epoch: StacksEpochId, -) -> Result, crate::vm::errors::Error> { +) -> Result, crate::vm::errors::VmExecutionError> +{ let ast = build_ast(contract_identifier, source_code, &mut (), version, epoch)?; Ok(ast.expressions) } @@ -240,7 +241,7 @@ mod test { use stacks_common::types::StacksEpochId; use crate::vm::ast::build_ast; - use crate::vm::ast::errors::ParseErrors; + use crate::vm::ast::errors::ParseErrorKind; use crate::vm::ast::stack_depth_checker::AST_CALL_STACK_DEPTH_BUFFER; use crate::vm::costs::{LimitedCostTracker, *}; use crate::vm::representations::depth_traverse; @@ -320,7 +321,7 @@ mod test { ) .expect_err("Contract should error in parsing"); - let expected_err = ParseErrors::VaryExpressionStackDepthTooDeep; + let expected_err = ParseErrorKind::VaryExpressionStackDepthTooDeep; let expected_list_cost_state = UnitTestTracker { invoked_functions: vec![(ClarityCostFunction::AstParse, vec![500])], invocation_count: 1, @@ -340,7 +341,7 @@ mod test { ) .expect_err("Contract should error in parsing"); - let expected_err = ParseErrors::VaryExpressionStackDepthTooDeep; + let expected_err = ParseErrorKind::VaryExpressionStackDepthTooDeep; let expected_list_cost_state = UnitTestTracker { invoked_functions: vec![(ClarityCostFunction::AstParse, vec![571])], invocation_count: 1, @@ -382,7 +383,7 @@ mod test { ) .expect_err("Contract should error in parsing"); - let expected_err = ParseErrors::ExpressionStackDepthTooDeep; + let expected_err = ParseErrorKind::ExpressionStackDepthTooDeep; let expected_list_cost_state = UnitTestTracker { invoked_functions: vec![(ClarityCostFunction::AstParse, vec![500])], invocation_count: 1, @@ -402,7 +403,7 @@ mod test { ) .expect_err("Contract should error in parsing"); - let expected_err = ParseErrors::ExpressionStackDepthTooDeep; + let expected_err = ParseErrorKind::ExpressionStackDepthTooDeep; let expected_list_cost_state = UnitTestTracker { invoked_functions: vec![(ClarityCostFunction::AstParse, vec![571])], invocation_count: 1, diff --git a/clarity/src/vm/ast/parser/v1.rs b/clarity/src/vm/ast/parser/v1.rs index feb59798956..98fe7028724 100644 --- a/clarity/src/vm/ast/parser/v1.rs +++ b/clarity/src/vm/ast/parser/v1.rs @@ -18,7 +18,7 @@ use lazy_static::lazy_static; use regex::{Captures, Regex}; use stacks_common::util::hash::hex_bytes; -use crate::vm::ast::errors::{ParseError, ParseErrors, ParseResult}; +use crate::vm::ast::errors::{ParseError, ParseErrorKind, ParseResult}; use crate::vm::ast::stack_depth_checker::AST_CALL_STACK_DEPTH_BUFFER; use crate::vm::representations::{ ClarityName, ContractName, PreSymbolicExpression, MAX_STRING_LEN, @@ -98,7 +98,7 @@ impl LexMatcher { fn get_value_or_err(input: &str, captures: Captures) -> ParseResult { let matched = captures .name("value") - .ok_or(ParseError::new(ParseErrors::FailedCapturingInput))?; + .ok_or(ParseError::new(ParseErrorKind::FailedCapturingInput))?; Ok(input[matched.start()..matched.end()].to_string()) } @@ -207,7 +207,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult ParseResult ParseResult Ok(()), TokenType::Comma => Ok(()), TokenType::Colon => Ok(()), - _ => Err(ParseError::new(ParseErrors::SeparatorExpected( + _ => Err(ParseError::new(ParseErrorKind::SeparatorExpected( current_slice[..whole_match.end()].to_string(), ))), } @@ -244,9 +244,11 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok(()), TokenType::Comma => Ok(()), TokenType::Colon => Ok(()), - _ => Err(ParseError::new(ParseErrors::SeparatorExpectedAfterColon( - current_slice[..whole_match.end()].to_string(), - ))), + _ => Err(ParseError::new( + ParseErrorKind::SeparatorExpectedAfterColon( + current_slice[..whole_match.end()].to_string(), + ), + )), } } }?; @@ -260,7 +262,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult max_nesting { return Err(ParseError::new( - ParseErrors::VaryExpressionStackDepthTooDeep, + ParseErrorKind::VaryExpressionStackDepthTooDeep, )); } Ok(LexItem::LeftParen) @@ -289,7 +291,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult max_nesting { return Err(ParseError::new( - ParseErrors::VaryExpressionStackDepthTooDeep, + ParseErrorKind::VaryExpressionStackDepthTooDeep, )); } Ok(LexItem::LeftCurly) @@ -302,7 +304,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult { let value = get_value_or_err(current_slice, captures)?; if value.contains('#') { - Err(ParseError::new(ParseErrors::IllegalVariableName(value))) + Err(ParseError::new(ParseErrorKind::IllegalVariableName(value))) } else { Ok(LexItem::Variable(value)) } @@ -311,7 +313,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult() { Ok(parsed) => Ok(Value::UInt(parsed)), - Err(_e) => Err(ParseError::new(ParseErrors::FailedParsingIntValue( + Err(_e) => Err(ParseError::new(ParseErrorKind::FailedParsingIntValue( str_value.clone(), ))), }?; @@ -321,7 +323,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult() { Ok(parsed) => Ok(Value::Int(parsed)), - Err(_e) => Err(ParseError::new(ParseErrors::FailedParsingIntValue( + Err(_e) => Err(ParseError::new(ParseErrorKind::FailedParsingIntValue( str_value.clone(), ))), }?; @@ -333,7 +335,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok(Value::Principal(parsed)), Err(_e) => Err(ParseError::new( - ParseErrors::FailedParsingPrincipal(str_value.clone()), + ParseErrorKind::FailedParsingPrincipal(str_value.clone()), )), }?; Ok(LexItem::LiteralValue(str_value.len(), value)) @@ -342,9 +344,9 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok(parsed), - Err(_e) => Err(ParseError::new(ParseErrors::FailedParsingPrincipal( - str_value.clone(), - ))), + Err(_e) => Err(ParseError::new( + ParseErrorKind::FailedParsingPrincipal(str_value.clone()), + )), }?; Ok(LexItem::SugaredContractIdentifier(str_value.len(), value)) } @@ -352,7 +354,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok(parsed), - Err(_e) => Err(ParseError::new(ParseErrors::FailedParsingField( + Err(_e) => Err(ParseError::new(ParseErrorKind::FailedParsingField( str_value.clone(), ))), }?; @@ -363,9 +365,9 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok((contract_name, field_name)), - Err(_e) => Err(ParseError::new(ParseErrors::FailedParsingField( - str_value.clone(), - ))), + Err(_e) => Err(ParseError::new( + ParseErrorKind::FailedParsingField(str_value.clone()), + )), }?; Ok(LexItem::SugaredFieldIdentifier( str_value.len(), @@ -377,30 +379,32 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok(Value::Principal(PrincipalData::Standard(parsed))), - Err(_e) => Err(ParseError::new(ParseErrors::FailedParsingPrincipal( - str_value.clone(), - ))), + Err(_e) => Err(ParseError::new( + ParseErrorKind::FailedParsingPrincipal(str_value.clone()), + )), }?; Ok(LexItem::LiteralValue(str_value.len(), value)) } TokenType::TraitReferenceLiteral => { let str_value = get_value_or_err(current_slice, captures)?; let data = str_value.clone().try_into().map_err(|_| { - ParseError::new(ParseErrors::IllegalVariableName(str_value.to_string())) + ParseError::new(ParseErrorKind::IllegalVariableName( + str_value.to_string(), + )) })?; Ok(LexItem::TraitReference(str_value.len(), data)) } TokenType::HexStringLiteral => { let str_value = get_value_or_err(current_slice, captures)?; let byte_vec = hex_bytes(&str_value).map_err(|x| { - ParseError::new(ParseErrors::FailedParsingHexValue( + ParseError::new(ParseErrorKind::FailedParsingHexValue( str_value.clone(), x.to_string(), )) })?; let value = match Value::buff_from(byte_vec) { Ok(parsed) => Ok(parsed), - Err(_e) => Err(ParseError::new(ParseErrors::FailedParsingBuffer( + Err(_e) => Err(ParseError::new(ParseErrorKind::FailedParsingBuffer( str_value.clone(), ))), }?; @@ -414,7 +418,9 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok(parsed), - Err(_e) => Err(ParseError::new(ParseErrors::InvalidCharactersDetected)), + Err(_e) => { + Err(ParseError::new(ParseErrorKind::InvalidCharactersDetected)) + } }?; Ok(LexItem::LiteralValue(str_value_len, value)) } @@ -426,7 +432,9 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Ok(parsed), - Err(_e) => Err(ParseError::new(ParseErrors::InvalidCharactersDetected)), + Err(_e) => { + Err(ParseError::new(ParseErrorKind::InvalidCharactersDetected)) + } }?; Ok(LexItem::LiteralValue(str_value_len, value)) } @@ -443,7 +451,7 @@ fn inner_lex(input: &str, max_nesting: u64) -> ParseResult Pars 'r' => unescaped_str.push('\r'), '0' => unescaped_str.push('\0'), 'u' if allow_unicode_escape => unescaped_str.push_str("\\u"), - _ => return Err(ParseError::new(ParseErrors::InvalidEscaping)), + _ => return Err(ParseError::new(ParseErrorKind::InvalidEscaping)), } } else { - return Err(ParseError::new(ParseErrors::InvalidEscaping)); + return Err(ParseError::new(ParseErrorKind::InvalidEscaping)); } } else { unescaped_str.push(char); @@ -525,12 +533,12 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult Ok(e), - ParseStackItem::Colon => { - Err(ParseError::new(ParseErrors::ColonSeparatorUnexpected)) - } - ParseStackItem::Comma => { - Err(ParseError::new(ParseErrors::CommaSeparatorUnexpected)) - } + ParseStackItem::Colon => Err(ParseError::new( + ParseErrorKind::ColonSeparatorUnexpected, + )), + ParseStackItem::Comma => Err(ParseError::new( + ParseErrorKind::CommaSeparatorUnexpected, + )), }) .collect(); let checked_list = checked_list?; @@ -540,7 +548,7 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult { let mut error = - ParseError::new(ParseErrors::ClosingTupleLiteralExpected); + ParseError::new(ParseErrorKind::ClosingTupleLiteralExpected); error.diagnostic.add_span( start_line, start_column, @@ -552,7 +560,9 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult { @@ -574,21 +584,21 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult { if let ParseStackItem::Colon = item { Ok(()) } else { - Err(ParseErrors::TupleColonExpected(index)) + Err(ParseErrorKind::TupleColonExpected(index)) } } 3 => { if let ParseStackItem::Comma = item { Ok(()) } else { - Err(ParseErrors::TupleCommaExpected(index)) + Err(ParseErrorKind::TupleCommaExpected(index)) } } _ => unreachable!("More than four modulos of four."), @@ -600,7 +610,7 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult { let mut error = - ParseError::new(ParseErrors::ClosingParenthesisExpected); + ParseError::new(ParseErrorKind::ClosingParenthesisExpected); error.diagnostic.add_span( start_line, start_column, @@ -612,13 +622,15 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult { let end_column = column_pos + (value.len() as u32) - 1; let value = value.clone().try_into().map_err(|_| { - ParseError::new(ParseErrors::IllegalVariableName(value.to_string())) + ParseError::new(ParseErrorKind::IllegalVariableName(value.to_string())) })?; let mut pre_expr = PreSymbolicExpression::atom(value); pre_expr.set_span(line_pos, column_pos, line_pos, end_column); @@ -673,7 +685,7 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult { match parse_stack.last_mut() { - None => return Err(ParseError::new(ParseErrors::ColonSeparatorUnexpected)), + None => return Err(ParseError::new(ParseErrorKind::ColonSeparatorUnexpected)), Some((ref mut list, ..)) => { list.push(ParseStackItem::Colon); } @@ -681,7 +693,7 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult { match parse_stack.last_mut() { - None => return Err(ParseError::new(ParseErrors::CommaSeparatorUnexpected)), + None => return Err(ParseError::new(ParseErrorKind::CommaSeparatorUnexpected)), Some((ref mut list, ..)) => { list.push(ParseStackItem::Comma); } @@ -693,7 +705,7 @@ pub fn parse_lexed(input: Vec<(LexItem, u32, u32)>) -> ParseResult ParseResult Parser<'a> { - pub fn new(input: &'a str, fail_fast: bool) -> Result { + pub fn new(input: &'a str, fail_fast: bool) -> Result { let lexer = match Lexer::new(input, fail_fast) { Ok(lexer) => lexer, - Err(e) => return Err(ParseErrors::Lexer(e)), + Err(e) => return Err(ParseErrorKind::Lexer(e)), }; let mut p = Self { lexer, @@ -89,7 +89,7 @@ impl<'a> Parser<'a> { "Parser::read_token should not return an error when not in fail_fast mode" ); p.success = false; - return Err(ParseErrors::Lexer(e)); + return Err(ParseErrorKind::Lexer(e)); } }; if token.token == Token::Eof { @@ -103,7 +103,7 @@ impl<'a> Parser<'a> { .diagnostics .iter() .map(|lex_error| PlacedError { - e: ParseErrors::Lexer(lex_error.e.clone()), + e: ParseErrorKind::Lexer(lex_error.e.clone()), span: lex_error.span.clone(), }) .collect(); @@ -111,7 +111,7 @@ impl<'a> Parser<'a> { Ok(p) } - fn add_diagnostic(&mut self, e: ParseErrors, span: Span) -> ParseResult<()> { + fn add_diagnostic(&mut self, e: ParseErrorKind, span: Span) -> ParseResult<()> { if self.fail_fast { return Err(ParseError::new(e)); } else { @@ -152,11 +152,11 @@ impl<'a> Parser<'a> { /// raises an UnexpectedParserFailure. fn peek_last_token(&self) -> ParseResult<&PlacedToken> { if self.next_token == 0 { - return Err(ParseError::new(ParseErrors::UnexpectedParserFailure)); + return Err(ParseError::new(ParseErrorKind::UnexpectedParserFailure)); } self.tokens .get(self.next_token - 1) - .ok_or_else(|| ParseError::new(ParseErrors::UnexpectedParserFailure)) + .ok_or_else(|| ParseError::new(ParseErrorKind::UnexpectedParserFailure)) } fn skip_to_end(&mut self) { @@ -222,7 +222,10 @@ impl<'a> Parser<'a> { } => { if let Some(node) = node_opt { if !*whitespace && node.match_comment().is_none() { - self.add_diagnostic(ParseErrors::ExpectedWhitespace, node.span().clone())?; + self.add_diagnostic( + ParseErrorKind::ExpectedWhitespace, + node.span().clone(), + )?; } nodes.push(node); *whitespace = self.ignore_whitespace(); @@ -241,11 +244,11 @@ impl<'a> Parser<'a> { Token::Eof => { // Report an error, but return the list and attempt to continue parsing self.add_diagnostic( - ParseErrors::ExpectedClosing(Token::Rparen), + ParseErrorKind::ExpectedClosing(Token::Rparen), token.span.clone(), )?; self.add_diagnostic( - ParseErrors::NoteToMatchThis(Token::Lparen), + ParseErrorKind::NoteToMatchThis(Token::Lparen), span.clone(), )?; span.end_line = token.span.end_line; @@ -258,7 +261,7 @@ impl<'a> Parser<'a> { _ => { // Report an error, then skip this token self.add_diagnostic( - ParseErrors::UnexpectedToken(token.token.clone()), + ParseErrorKind::UnexpectedToken(token.token.clone()), token.span, )?; *whitespace = self.ignore_whitespace(); @@ -293,11 +296,11 @@ impl<'a> Parser<'a> { match last_token.token { Token::Eof => { self.add_diagnostic( - ParseErrors::ExpectedClosing(Token::Rbrace), + ParseErrorKind::ExpectedClosing(Token::Rbrace), open_tuple.diagnostic_token.span.clone(), )?; self.add_diagnostic( - ParseErrors::NoteToMatchThis(Token::Lbrace), + ParseErrorKind::NoteToMatchThis(Token::Lbrace), open_tuple.span.clone(), )?; let out_nodes: Vec<_> = open_tuple.nodes.drain(..).collect(); @@ -311,7 +314,7 @@ impl<'a> Parser<'a> { _ => { // Report an error, then skip this token self.add_diagnostic( - ParseErrors::UnexpectedToken(last_token.token), + ParseErrorKind::UnexpectedToken(last_token.token), last_token.span, )?; return Ok(None); // Ok(None) yields to the parse loop @@ -335,7 +338,10 @@ impl<'a> Parser<'a> { // This indicates we have reached the end of the input. // Create a placeholder value so that parsing can continue, // then return. - self.add_diagnostic(ParseErrors::TupleColonExpectedv2, token.span.clone())?; + self.add_diagnostic( + ParseErrorKind::TupleColonExpectedv2, + token.span.clone(), + )?; let mut placeholder = PreSymbolicExpression::placeholder("".to_string()); placeholder.copy_span(&token.span); open_tuple.nodes.push(placeholder); // Placeholder value @@ -349,7 +355,10 @@ impl<'a> Parser<'a> { } _ => { // Record an error, then continue to parse - self.add_diagnostic(ParseErrors::TupleColonExpectedv2, token.span.clone())?; + self.add_diagnostic( + ParseErrorKind::TupleColonExpectedv2, + token.span.clone(), + )?; } } open_tuple.diagnostic_token = token; @@ -377,7 +386,7 @@ impl<'a> Parser<'a> { let eof_span = last_token.span; self.add_diagnostic( - ParseErrors::TupleValueExpected, + ParseErrorKind::TupleValueExpected, open_tuple.diagnostic_token.span.clone(), )?; let mut placeholder = @@ -396,7 +405,7 @@ impl<'a> Parser<'a> { _ => { // Report an error, then skip this token self.add_diagnostic( - ParseErrors::UnexpectedToken(last_token.token), + ParseErrorKind::UnexpectedToken(last_token.token), last_token.span, )?; return Ok(None); // Ok(None) yields to the parse loop @@ -425,7 +434,7 @@ impl<'a> Parser<'a> { return Ok(Some(e)); } Token::Eof => (), - _ => self.add_diagnostic(ParseErrors::TupleCommaExpectedv2, token.span)?, + _ => self.add_diagnostic(ParseErrorKind::TupleCommaExpectedv2, token.span)?, } let mut comments = self.ignore_whitespace_and_comments(); @@ -469,7 +478,7 @@ impl<'a> Parser<'a> { let token = self.peek_next_token(); match token.token { Token::Comma => { - self.add_diagnostic(ParseErrors::UnexpectedToken(token.token), token.span)?; + self.add_diagnostic(ParseErrorKind::UnexpectedToken(token.token), token.span)?; self.next_token(); } Token::Rbrace => { @@ -514,7 +523,7 @@ impl<'a> Parser<'a> { let principal = match PrincipalData::parse_standard_principal(&addr) { Ok(principal) => principal, _ => { - self.add_diagnostic(ParseErrors::InvalidPrincipalLiteral, span.clone())?; + self.add_diagnostic(ParseErrorKind::InvalidPrincipalLiteral, span.clone())?; let mut placeholder = PreSymbolicExpression::placeholder(format!("'{addr}")); placeholder.copy_span(&span); return Ok(placeholder); @@ -540,7 +549,7 @@ impl<'a> Parser<'a> { }) => { span.end_line = token_span.end_line; span.end_column = token_span.end_column; - self.add_diagnostic(ParseErrors::ExpectedContractIdentifier, token_span)?; + self.add_diagnostic(ParseErrorKind::ExpectedContractIdentifier, token_span)?; let mut placeholder = PreSymbolicExpression::placeholder(format!( "'{principal}.{}", token.reproduce() @@ -549,7 +558,7 @@ impl<'a> Parser<'a> { return Ok(placeholder); } None => { - self.add_diagnostic(ParseErrors::ExpectedContractIdentifier, dot.span)?; + self.add_diagnostic(ParseErrorKind::ExpectedContractIdentifier, dot.span)?; let mut placeholder = PreSymbolicExpression::placeholder(format!("'{principal}.")); placeholder.copy_span(&span); @@ -559,7 +568,7 @@ impl<'a> Parser<'a> { if name.len() > MAX_CONTRACT_NAME_LEN { self.add_diagnostic( - ParseErrors::ContractNameTooLong(name.clone()), + ParseErrorKind::ContractNameTooLong(name.clone()), contract_span, )?; let mut placeholder = @@ -571,7 +580,7 @@ impl<'a> Parser<'a> { Ok(id) => id, Err(_) => { self.add_diagnostic( - ParseErrors::IllegalContractName(name.clone()), + ParseErrorKind::IllegalContractName(name.clone()), contract_span, )?; let mut placeholder = @@ -600,7 +609,7 @@ impl<'a> Parser<'a> { token, }) => { self.add_diagnostic( - ParseErrors::ExpectedTraitIdentifier, + ParseErrorKind::ExpectedTraitIdentifier, token_span.clone(), )?; let mut placeholder = PreSymbolicExpression::placeholder(format!( @@ -614,7 +623,7 @@ impl<'a> Parser<'a> { } None => { self.add_diagnostic( - ParseErrors::ExpectedTraitIdentifier, + ParseErrorKind::ExpectedTraitIdentifier, dot.span.clone(), )?; let mut placeholder = @@ -626,7 +635,7 @@ impl<'a> Parser<'a> { } }; if name.len() > MAX_STRING_LEN { - self.add_diagnostic(ParseErrors::NameTooLong(name.clone()), trait_span)?; + self.add_diagnostic(ParseErrorKind::NameTooLong(name.clone()), trait_span)?; let mut placeholder = PreSymbolicExpression::placeholder(format!("'{contract_id}.{name}",)); placeholder.copy_span(&span); @@ -636,7 +645,7 @@ impl<'a> Parser<'a> { Ok(id) => id, Err(_) => { self.add_diagnostic( - ParseErrors::IllegalTraitName(name.clone()), + ParseErrorKind::IllegalTraitName(name.clone()), trait_span, )?; let mut placeholder = @@ -682,7 +691,10 @@ impl<'a> Parser<'a> { span: token_span, token, }) => { - self.add_diagnostic(ParseErrors::ExpectedContractIdentifier, token_span.clone())?; + self.add_diagnostic( + ParseErrorKind::ExpectedContractIdentifier, + token_span.clone(), + )?; let mut placeholder = PreSymbolicExpression::placeholder(format!(".{}", token.reproduce())); span.end_line = token_span.end_line; @@ -691,7 +703,7 @@ impl<'a> Parser<'a> { return Ok(placeholder); } None => { - self.add_diagnostic(ParseErrors::ExpectedContractIdentifier, span.clone())?; + self.add_diagnostic(ParseErrorKind::ExpectedContractIdentifier, span.clone())?; let mut placeholder = PreSymbolicExpression::placeholder(".".to_string()); placeholder.copy_span(&span); return Ok(placeholder); @@ -699,7 +711,10 @@ impl<'a> Parser<'a> { }; if name.len() > MAX_CONTRACT_NAME_LEN { - self.add_diagnostic(ParseErrors::ContractNameTooLong(name.clone()), span.clone())?; + self.add_diagnostic( + ParseErrorKind::ContractNameTooLong(name.clone()), + span.clone(), + )?; let mut placeholder = PreSymbolicExpression::placeholder(format!(".{name}")); placeholder.copy_span(&span); return Ok(placeholder); @@ -709,7 +724,7 @@ impl<'a> Parser<'a> { Ok(id) => id, Err(_) => { self.add_diagnostic( - ParseErrors::IllegalContractName(name.clone()), + ParseErrorKind::IllegalContractName(name.clone()), contract_span, )?; let mut placeholder = PreSymbolicExpression::placeholder(format!(".{name}")); @@ -735,7 +750,10 @@ impl<'a> Parser<'a> { span: token_span, token, }) => { - self.add_diagnostic(ParseErrors::ExpectedTraitIdentifier, token_span.clone())?; + self.add_diagnostic( + ParseErrorKind::ExpectedTraitIdentifier, + token_span.clone(), + )?; let mut placeholder = PreSymbolicExpression::placeholder(format!( ".{contract_name}.{}", token.reproduce(), @@ -746,7 +764,7 @@ impl<'a> Parser<'a> { return Ok(placeholder); } None => { - self.add_diagnostic(ParseErrors::ExpectedTraitIdentifier, dot.span.clone())?; + self.add_diagnostic(ParseErrorKind::ExpectedTraitIdentifier, dot.span.clone())?; let mut placeholder = PreSymbolicExpression::placeholder(format!(".{contract_name}.")); span.end_line = dot.span.end_line; @@ -756,7 +774,7 @@ impl<'a> Parser<'a> { } }; if name.len() > MAX_STRING_LEN { - self.add_diagnostic(ParseErrors::NameTooLong(name.clone()), trait_span)?; + self.add_diagnostic(ParseErrorKind::NameTooLong(name.clone()), trait_span)?; let mut placeholder = PreSymbolicExpression::placeholder(format!(".{contract_name}.{name}")); placeholder.copy_span(&span); @@ -765,7 +783,10 @@ impl<'a> Parser<'a> { let trait_name = match ClarityName::try_from(name.clone()) { Ok(id) => id, Err(_) => { - self.add_diagnostic(ParseErrors::IllegalTraitName(name.clone()), trait_span)?; + self.add_diagnostic( + ParseErrorKind::IllegalTraitName(name.clone()), + trait_span, + )?; let mut placeholder = PreSymbolicExpression::placeholder(format!(".{contract_name}.{name}")); placeholder.copy_span(&span); @@ -805,7 +826,7 @@ impl<'a> Parser<'a> { self.nesting_depth += 1; if self.nesting_depth > MAX_NESTING_DEPTH { self.add_diagnostic( - ParseErrors::ExpressionStackDepthTooDeep, + ParseErrorKind::ExpressionStackDepthTooDeep, token.span.clone(), )?; // Do not try to continue, exit cleanly now to avoid a stack overflow. @@ -824,7 +845,7 @@ impl<'a> Parser<'a> { // This sugared syntax for tuple becomes a list of pairs, so depth is increased by 2. if self.nesting_depth + 2 > MAX_NESTING_DEPTH { self.add_diagnostic( - ParseErrors::ExpressionStackDepthTooDeep, + ParseErrorKind::ExpressionStackDepthTooDeep, token.span.clone(), )?; // Do not try to continue, exit cleanly now to avoid a stack overflow. @@ -847,7 +868,7 @@ impl<'a> Parser<'a> { Ok(val) => PreSymbolicExpression::atom_value(Value::Int(val)), Err(_) => { self.add_diagnostic( - ParseErrors::FailedParsingIntValue(val_string.clone()), + ParseErrorKind::FailedParsingIntValue(val_string.clone()), token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -861,7 +882,7 @@ impl<'a> Parser<'a> { Ok(val) => PreSymbolicExpression::atom_value(Value::UInt(val)), Err(_) => { self.add_diagnostic( - ParseErrors::FailedParsingUIntValue(val_string.clone()), + ParseErrorKind::FailedParsingUIntValue(val_string.clone()), token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -876,7 +897,7 @@ impl<'a> Parser<'a> { Ok(s) => PreSymbolicExpression::atom_value(s), Err(_) => { self.add_diagnostic( - ParseErrors::IllegalASCIIString(val.clone()), + ParseErrorKind::IllegalASCIIString(val.clone()), token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -905,7 +926,7 @@ impl<'a> Parser<'a> { Token::Ident(name) => { let mut expr = if name.len() > MAX_STRING_LEN { self.add_diagnostic( - ParseErrors::NameTooLong(name.clone()), + ParseErrorKind::NameTooLong(name.clone()), token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -914,7 +935,7 @@ impl<'a> Parser<'a> { Ok(name) => PreSymbolicExpression::atom(name), Err(_) => { self.add_diagnostic( - ParseErrors::IllegalClarityName(name.clone()), + ParseErrorKind::IllegalClarityName(name.clone()), token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -927,7 +948,7 @@ impl<'a> Parser<'a> { Token::TraitIdent(name) => { let mut expr = if name.len() > MAX_STRING_LEN { self.add_diagnostic( - ParseErrors::NameTooLong(name.clone()), + ParseErrorKind::NameTooLong(name.clone()), token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -936,7 +957,7 @@ impl<'a> Parser<'a> { Ok(name) => PreSymbolicExpression::trait_reference(name), Err(_) => { self.add_diagnostic( - ParseErrors::IllegalTraitName(name.clone()), + ParseErrorKind::IllegalTraitName(name.clone()), token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -952,7 +973,7 @@ impl<'a> Parser<'a> { Ok(value) => PreSymbolicExpression::atom_value(value), _ => { self.add_diagnostic( - ParseErrors::InvalidBuffer, + ParseErrorKind::InvalidBuffer, token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -960,7 +981,7 @@ impl<'a> Parser<'a> { }, Err(_) => { self.add_diagnostic( - ParseErrors::InvalidBuffer, + ParseErrorKind::InvalidBuffer, token.span.clone(), )?; PreSymbolicExpression::placeholder(token.token.reproduce()) @@ -986,7 +1007,7 @@ impl<'a> Parser<'a> { | Token::Greater | Token::GreaterEqual => { let name = ClarityName::try_from(token.token.to_string()) - .map_err(|_| ParseErrors::InterpreterFailure)?; + .map_err(|_| ParseErrorKind::InterpreterFailure)?; let mut e = PreSymbolicExpression::atom(name); e.copy_span(&token.span); Some(e) @@ -1054,7 +1075,7 @@ impl<'a> Parser<'a> { _ => { // Report an error, then skip this token self.add_diagnostic( - ParseErrors::UnexpectedToken(token.token), + ParseErrorKind::UnexpectedToken(token.token), token.span, )?; } @@ -3533,7 +3554,10 @@ mod tests { fn test_parse_fail_fast() { match parse("42g !ok") { Ok(_) => panic!("fail_fast mode should have returned an error"), - Err(e) => assert_eq!(*e.err, ParseErrors::Lexer(LexerError::InvalidCharInt('g'))), + Err(e) => assert_eq!( + *e.err, + ParseErrorKind::Lexer(LexerError::InvalidCharInt('g')) + ), } } @@ -3561,7 +3585,7 @@ mod tests { ); assert!(match *(parse(&exceeds_stack_depth_list).unwrap_err().err) { - ParseErrors::ExpressionStackDepthTooDeep => true, + ParseErrorKind::ExpressionStackDepthTooDeep => true, x => panic!("expected a stack depth too deep error, got {x:?}"), }); @@ -3584,7 +3608,7 @@ mod tests { ); assert!(match *parse(&exceeds_stack_depth_tuple).unwrap_err().err { - ParseErrors::ExpressionStackDepthTooDeep => true, + ParseErrorKind::ExpressionStackDepthTooDeep => true, x => panic!("expected a stack depth too deep error, got {x:?}"), }); diff --git a/clarity/src/vm/ast/stack_depth_checker.rs b/clarity/src/vm/ast/stack_depth_checker.rs index 5115e107373..0e3bf7db23c 100644 --- a/clarity/src/vm/ast/stack_depth_checker.rs +++ b/clarity/src/vm/ast/stack_depth_checker.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::vm::ast::errors::{ParseErrors, ParseResult}; +use crate::vm::ast::errors::{ParseErrorKind, ParseResult}; use crate::vm::ast::types::{BuildASTPass, ContractAST}; use crate::vm::representations::PreSymbolicExpression; use crate::vm::representations::PreSymbolicExpressionType::{List, Tuple}; @@ -27,7 +27,7 @@ pub const AST_CALL_STACK_DEPTH_BUFFER: u64 = 5; fn check(args: &[PreSymbolicExpression], depth: u64) -> ParseResult<()> { if depth >= (AST_CALL_STACK_DEPTH_BUFFER + MAX_CALL_STACK_DEPTH as u64) { - return Err(ParseErrors::ExpressionStackDepthTooDeep.into()); + return Err(ParseErrorKind::ExpressionStackDepthTooDeep.into()); } for expression in args.iter() { match expression.pre_expr { @@ -52,7 +52,7 @@ impl BuildASTPass for StackDepthChecker { fn check_vary(args: &[PreSymbolicExpression], depth: u64) -> ParseResult<()> { if depth >= (AST_CALL_STACK_DEPTH_BUFFER + MAX_CALL_STACK_DEPTH as u64) { - return Err(ParseErrors::VaryExpressionStackDepthTooDeep.into()); + return Err(ParseErrorKind::VaryExpressionStackDepthTooDeep.into()); } for expression in args.iter() { match expression.pre_expr { diff --git a/clarity/src/vm/ast/sugar_expander/mod.rs b/clarity/src/vm/ast/sugar_expander/mod.rs index b7b4965f50c..57b2f414c2c 100644 --- a/clarity/src/vm/ast/sugar_expander/mod.rs +++ b/clarity/src/vm/ast/sugar_expander/mod.rs @@ -21,7 +21,7 @@ use clarity_types::types::{ PrincipalData, QualifiedContractIdentifier, StandardPrincipalData, TraitIdentifier, Value, }; -use crate::vm::ast::errors::{ParseErrors, ParseResult}; +use crate::vm::ast::errors::{ParseErrorKind, ParseResult}; use crate::vm::ast::types::{BuildASTPass, ContractAST, PreExpressionsDrain}; use crate::vm::representations::{PreSymbolicExpressionType, SymbolicExpression}; use crate::vm::ClarityVersion; @@ -92,7 +92,7 @@ impl SugarExpander { "tuple" .to_string() .try_into() - .map_err(|_| ParseErrors::InterpreterFailure)?, + .map_err(|_| ParseErrorKind::InterpreterFailure)?, ), ); SymbolicExpression::list(pairs) @@ -119,7 +119,7 @@ impl SugarExpander { if let Some(trait_reference) = contract_ast.get_referenced_trait(&name) { SymbolicExpression::trait_reference(name, trait_reference.clone()) } else { - return Err(ParseErrors::TraitReferenceUnknown(name.to_string()).into()); + return Err(ParseErrorKind::TraitReferenceUnknown(name.to_string()).into()); } } #[cfg(not(feature = "developer-mode"))] diff --git a/clarity/src/vm/ast/traits_resolver/mod.rs b/clarity/src/vm/ast/traits_resolver/mod.rs index 90bf989ade5..df77ed41f65 100644 --- a/clarity/src/vm/ast/traits_resolver/mod.rs +++ b/clarity/src/vm/ast/traits_resolver/mod.rs @@ -19,7 +19,7 @@ use std::collections::HashMap; use clarity_types::representations::ClarityName; use clarity_types::types::{QualifiedContractIdentifier, TraitIdentifier}; -use crate::vm::ast::errors::{ParseError, ParseErrors, ParseResult}; +use crate::vm::ast::errors::{ParseError, ParseErrorKind, ParseResult}; use crate::vm::ast::types::{BuildASTPass, ContractAST}; use crate::vm::functions::define::DefineFunctions; use crate::vm::representations::PreSymbolicExpressionType::{ @@ -56,16 +56,17 @@ impl TraitsResolver { match define_type { DefineFunctions::Trait => { if args.len() != 2 { - return Err(ParseErrors::DefineTraitBadSignature.into()); + return Err(ParseErrorKind::DefineTraitBadSignature.into()); } match (&args[0].pre_expr, &args[1].pre_expr) { (Atom(trait_name), List(trait_definition)) => { // Check for collisions if contract_ast.referenced_traits.contains_key(trait_name) { - return Err( - ParseErrors::NameAlreadyUsed(trait_name.to_string()).into() - ); + return Err(ParseErrorKind::NameAlreadyUsed( + trait_name.to_string(), + ) + .into()); } // Traverse and probe for generics nested in the trait definition @@ -83,18 +84,20 @@ impl TraitsResolver { .referenced_traits .insert(trait_name.clone(), TraitDefinition::Defined(trait_id)); } - _ => return Err(ParseErrors::DefineTraitBadSignature.into()), + _ => return Err(ParseErrorKind::DefineTraitBadSignature.into()), } } DefineFunctions::UseTrait => { if args.len() != 2 { - return Err(ParseErrors::ImportTraitBadSignature.into()); + return Err(ParseErrorKind::ImportTraitBadSignature.into()); } if let Some(trait_name) = args[0].match_atom() { // Check for collisions if contract_ast.referenced_traits.contains_key(trait_name) { - return Err(ParseErrors::NameAlreadyUsed(trait_name.to_string()).into()); + return Err( + ParseErrorKind::NameAlreadyUsed(trait_name.to_string()).into() + ); } let trait_id = match &args[1].pre_expr { @@ -109,18 +112,18 @@ impl TraitsResolver { } } FieldIdentifier(trait_identifier) => trait_identifier.clone(), - _ => return Err(ParseErrors::ImportTraitBadSignature.into()), + _ => return Err(ParseErrorKind::ImportTraitBadSignature.into()), }; contract_ast .referenced_traits .insert(trait_name.clone(), TraitDefinition::Imported(trait_id)); } else { - return Err(ParseErrors::ImportTraitBadSignature.into()); + return Err(ParseErrorKind::ImportTraitBadSignature.into()); } } DefineFunctions::ImplTrait => { if args.len() != 1 { - return Err(ParseErrors::ImplTraitBadSignature.into()); + return Err(ParseErrorKind::ImplTraitBadSignature.into()); } let trait_id = match &args[0].pre_expr { @@ -135,7 +138,7 @@ impl TraitsResolver { } } FieldIdentifier(trait_identifier) => trait_identifier.clone(), - _ => return Err(ParseErrors::ImplTraitBadSignature.into()), + _ => return Err(ParseErrorKind::ImplTraitBadSignature.into()), }; contract_ast.implemented_traits.insert(trait_id); } @@ -166,7 +169,7 @@ impl TraitsResolver { .referenced_traits .contains_key(&trait_reference) { - let mut err = ParseError::new(ParseErrors::TraitReferenceUnknown( + let mut err = ParseError::new(ParseErrorKind::TraitReferenceUnknown( trait_reference.to_string(), )); err.set_pre_expression(&expr); @@ -207,7 +210,7 @@ impl TraitsResolver { if should_reference { referenced_traits.insert(trait_name.clone(), expression.clone()); } else { - return Err(ParseErrors::TraitReferenceNotAllowed.into()); + return Err(ParseErrorKind::TraitReferenceNotAllowed.into()); } } Tuple(atoms) => { diff --git a/clarity/src/vm/callables.rs b/clarity/src/vm/callables.rs index b697b3a0959..cce00d2f0be 100644 --- a/clarity/src/vm/callables.rs +++ b/clarity/src/vm/callables.rs @@ -21,14 +21,14 @@ pub use clarity_types::types::FunctionIdentifier; use stacks_common::types::StacksEpochId; use super::costs::{CostErrors, CostOverflowingMath}; -use super::errors::InterpreterError; +use super::errors::VmInternalError; use super::types::signatures::CallableSubtype; use super::ClarityVersion; -use crate::vm::analysis::errors::CheckErrors; +use crate::vm::analysis::errors::CheckErrorKind; use crate::vm::contexts::ContractContext; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; -use crate::vm::errors::{check_argument_count, Error, InterpreterResult as Result}; +use crate::vm::errors::{check_argument_count, InterpreterResult as Result, VmExecutionError}; use crate::vm::representations::SymbolicExpression; use crate::vm::types::{ CallableData, ListData, ListTypeData, OptionalData, PrincipalData, ResponseData, SequenceData, @@ -89,17 +89,17 @@ impl NativeHandle { check_argument_count(1, &args)?; function( args.pop() - .ok_or_else(|| InterpreterError::Expect("Unexpected list length".into()))?, + .ok_or_else(|| VmInternalError::Expect("Unexpected list length".into()))?, ) } Self::DoubleArg(function) => { check_argument_count(2, &args)?; let second = args .pop() - .ok_or_else(|| InterpreterError::Expect("Unexpected list length".into()))?; + .ok_or_else(|| VmInternalError::Expect("Unexpected list length".into()))?; let first = args .pop() - .ok_or_else(|| InterpreterError::Expect("Unexpected list length".into()))?; + .ok_or_else(|| VmInternalError::Expect("Unexpected list length".into()))?; function(first, second) } Self::MoreArg(function) => function(args), @@ -116,7 +116,7 @@ pub fn cost_input_sized_vararg(args: &[Value]) -> Result { .map_err(|e| CostErrors::Expect(format!("{e:?}")))? as u64) .cost_overflow_add(sum) }) - .map_err(Error::from) + .map_err(VmExecutionError::from) } impl DefinedFunction { @@ -156,7 +156,7 @@ impl DefinedFunction { let mut context = LocalContext::new(); if args.len() != self.arguments.len() { - Err(CheckErrors::IncorrectArgumentCount( + Err(CheckErrorKind::IncorrectArgumentCount( self.arguments.len(), args.len(), ))? @@ -227,7 +227,7 @@ impl DefinedFunction { } _ => { if !type_sig.admits(env.epoch(), value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(type_sig.clone()), Box::new(value.clone()), ) @@ -238,7 +238,7 @@ impl DefinedFunction { .insert(name.clone(), value.clone()) .is_some() { - return Err(CheckErrors::NameAlreadyUsed(name.to_string()).into()); + return Err(CheckErrorKind::NameAlreadyUsed(name.to_string()).into()); } } } @@ -272,7 +272,7 @@ impl DefinedFunction { } _ => { if !type_sig.admits(env.epoch(), &cast_value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(type_sig.clone()), Box::new(cast_value), ) @@ -282,7 +282,7 @@ impl DefinedFunction { } if context.variables.insert(name.clone(), cast_value).is_some() { - return Err(CheckErrors::NameAlreadyUsed(name.to_string()).into()); + return Err(CheckErrorKind::NameAlreadyUsed(name.to_string()).into()); } } } @@ -294,7 +294,7 @@ impl DefinedFunction { match result { Ok(r) => Ok(r), Err(e) => match e { - Error::ShortReturn(v) => Ok(v.into()), + VmExecutionError::EarlyReturn(v) => Ok(v.into()), _ => Err(e), }, } @@ -309,11 +309,13 @@ impl DefinedFunction { let trait_name = trait_identifier.name.to_string(); let constraining_trait = contract_defining_trait .lookup_trait_definition(&trait_name) - .ok_or(CheckErrors::TraitReferenceUnknown(trait_name.to_string()))?; + .ok_or(CheckErrorKind::TraitReferenceUnknown( + trait_name.to_string(), + ))?; let expected_sig = constraining_trait .get(&self.name) - .ok_or(CheckErrors::TraitMethodUnknown( + .ok_or(CheckErrorKind::TraitMethodUnknown( trait_name.to_string(), self.name.to_string(), ))?; @@ -321,7 +323,7 @@ impl DefinedFunction { let args = self.arg_types.to_vec(); if !expected_sig.check_args_trait_compliance(epoch, args)? { return Err( - CheckErrors::BadTraitImplementation(trait_name, self.name.to_string()).into(), + CheckErrorKind::BadTraitImplementation(trait_name, self.name.to_string()).into(), ); } @@ -449,7 +451,7 @@ fn clarity2_implicit_cast(type_sig: &TypeSignature, value: &Value) -> Result ty, None => { // This should be unreachable if the type-checker has already run successfully - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(type_sig.clone()), Box::new(value.clone()), ) diff --git a/clarity/src/vm/clarity.rs b/clarity/src/vm/clarity.rs index 34461862d7b..ef51074c72a 100644 --- a/clarity/src/vm/clarity.rs +++ b/clarity/src/vm/clarity.rs @@ -2,24 +2,37 @@ use std::fmt; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::{AnalysisDatabase, CheckError, CheckErrors, ContractAnalysis}; -use crate::vm::ast::errors::{ParseError, ParseErrors}; +use crate::vm::analysis::{AnalysisDatabase, CheckErrorKind, ContractAnalysis, StaticCheckError}; +use crate::vm::ast::errors::{ParseError, ParseErrorKind}; use crate::vm::ast::ContractAST; use crate::vm::contexts::{AssetMap, Environment, OwnedEnvironment}; use crate::vm::costs::{ExecutionCost, LimitedCostTracker}; use crate::vm::database::ClarityDatabase; -use crate::vm::errors::Error as InterpreterError; +use crate::vm::errors::VmExecutionError; use crate::vm::events::StacksTransactionEvent; use crate::vm::types::{BuffData, PrincipalData, QualifiedContractIdentifier}; use crate::vm::{analysis, ast, ClarityVersion, ContractContext, SymbolicExpression, Value}; +/// Top-level error type for Clarity contract processing, encompassing errors from parsing, +/// type-checking, runtime evaluation, and transaction execution. #[derive(Debug)] -pub enum Error { - Analysis(CheckError), +pub enum ClarityError { + /// Error during static type-checking or semantic analysis. + /// The `StaticCheckError` wraps the specific type-checking error, including diagnostic details. + StaticCheck(StaticCheckError), + /// Error during lexical or syntactic parsing. + /// The `ParseError` wraps the specific parsing error, such as invalid syntax or tokens. Parse(ParseError), - Interpreter(InterpreterError), + /// Error during runtime evaluation in the virtual machine. + /// The `VmExecutionError` wraps the specific error, such as runtime errors or dynamic type-checking errors. + Interpreter(VmExecutionError), + /// Transaction is malformed or invalid due to blockchain-level issues. + /// The `String` wraps a human-readable description of the issue, such as incorrect format or invalid signatures. BadTransaction(String), + /// Transaction exceeds the allocated cost budget during execution. + /// The first `ExecutionCost` represents the total consumed cost, and the second represents the budget limit. CostError(ExecutionCost, ExecutionCost), + /// Transaction aborted by a callback (e.g., post-condition check or custom logic). AbortedByCallback { /// What the output value of the transaction would have been. /// This will be a Some for contract-calls, and None for contract initialization txs. @@ -33,85 +46,85 @@ pub enum Error { }, } -impl fmt::Display for Error { +impl fmt::Display for ClarityError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Error::CostError(ref a, ref b) => { + ClarityError::CostError(ref a, ref b) => { write!(f, "Cost Error: {a} cost exceeded budget of {b} cost") } - Error::Analysis(ref e) => fmt::Display::fmt(e, f), - Error::Parse(ref e) => fmt::Display::fmt(e, f), - Error::AbortedByCallback { reason, .. } => { + ClarityError::StaticCheck(ref e) => fmt::Display::fmt(e, f), + ClarityError::Parse(ref e) => fmt::Display::fmt(e, f), + ClarityError::AbortedByCallback { reason, .. } => { write!(f, "Post condition aborted transaction: {reason}") } - Error::Interpreter(ref e) => fmt::Display::fmt(e, f), - Error::BadTransaction(ref s) => fmt::Display::fmt(s, f), + ClarityError::Interpreter(ref e) => fmt::Display::fmt(e, f), + ClarityError::BadTransaction(ref s) => fmt::Display::fmt(s, f), } } } -impl std::error::Error for Error { +impl std::error::Error for ClarityError { fn cause(&self) -> Option<&dyn std::error::Error> { match *self { - Error::CostError(ref _a, ref _b) => None, - Error::AbortedByCallback { .. } => None, - Error::Analysis(ref e) => Some(e), - Error::Parse(ref e) => Some(e), - Error::Interpreter(ref e) => Some(e), - Error::BadTransaction(ref _s) => None, + ClarityError::CostError(ref _a, ref _b) => None, + ClarityError::AbortedByCallback { .. } => None, + ClarityError::StaticCheck(ref e) => Some(e), + ClarityError::Parse(ref e) => Some(e), + ClarityError::Interpreter(ref e) => Some(e), + ClarityError::BadTransaction(ref _s) => None, } } } -impl From for Error { - fn from(e: CheckError) -> Self { +impl From for ClarityError { + fn from(e: StaticCheckError) -> Self { match *e.err { - CheckErrors::CostOverflow => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + CheckErrorKind::CostOverflow => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - CheckErrors::CostBalanceExceeded(a, b) => Error::CostError(a, b), - CheckErrors::MemoryBalanceExceeded(_a, _b) => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + CheckErrorKind::CostBalanceExceeded(a, b) => ClarityError::CostError(a, b), + CheckErrorKind::MemoryBalanceExceeded(_a, _b) => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - CheckErrors::ExecutionTimeExpired => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + CheckErrorKind::ExecutionTimeExpired => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - _ => Error::Analysis(e), + _ => ClarityError::StaticCheck(e), } } } -impl From for Error { - fn from(e: InterpreterError) -> Self { +impl From for ClarityError { + fn from(e: VmExecutionError) -> Self { match &e { - InterpreterError::Unchecked(CheckErrors::CostBalanceExceeded(a, b)) => { - Error::CostError(a.clone(), b.clone()) + VmExecutionError::Unchecked(CheckErrorKind::CostBalanceExceeded(a, b)) => { + ClarityError::CostError(a.clone(), b.clone()) } - InterpreterError::Unchecked(CheckErrors::CostOverflow) => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + VmExecutionError::Unchecked(CheckErrorKind::CostOverflow) => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - InterpreterError::Unchecked(CheckErrors::ExecutionTimeExpired) => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + VmExecutionError::Unchecked(CheckErrorKind::ExecutionTimeExpired) => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - _ => Error::Interpreter(e), + _ => ClarityError::Interpreter(e), } } } -impl From for Error { +impl From for ClarityError { fn from(e: ParseError) -> Self { match *e.err { - ParseErrors::CostOverflow => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + ParseErrorKind::CostOverflow => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - ParseErrors::CostBalanceExceeded(a, b) => Error::CostError(a, b), - ParseErrors::MemoryBalanceExceeded(_a, _b) => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + ParseErrorKind::CostBalanceExceeded(a, b) => ClarityError::CostError(a, b), + ParseErrorKind::MemoryBalanceExceeded(_a, _b) => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - ParseErrors::ExecutionTimeExpired => { - Error::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) + ParseErrorKind::ExecutionTimeExpired => { + ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - _ => Error::Parse(e), + _ => ClarityError::Parse(e), } } } @@ -143,9 +156,9 @@ pub trait ClarityConnection { sponsor: Option, cost_track: LimitedCostTracker, to_do: F, - ) -> Result + ) -> Result where - F: FnOnce(&mut Environment) -> Result, + F: FnOnce(&mut Environment) -> Result, { let epoch_id = self.get_epoch(); let clarity_version = ClarityVersion::default_for_epoch(epoch_id); @@ -192,7 +205,7 @@ pub trait TransactionConnection: ClarityConnection { where A: FnOnce(&AssetMap, &mut ClarityDatabase) -> Option, F: FnOnce(&mut OwnedEnvironment) -> Result<(R, AssetMap, Vec), E>, - E: From; + E: From; /// Do something with the analysis database and cost tracker /// instance of this transaction connection. This is a low-level @@ -209,7 +222,7 @@ pub trait TransactionConnection: ClarityConnection { identifier: &QualifiedContractIdentifier, clarity_version: ClarityVersion, contract_content: &str, - ) -> Result<(ContractAST, ContractAnalysis), Error> { + ) -> Result<(ContractAST, ContractAnalysis), ClarityError> { let epoch_id = self.get_epoch(); self.with_analysis_db(|db, mut cost_track| { @@ -254,7 +267,7 @@ pub trait TransactionConnection: ClarityConnection { &mut self, identifier: &QualifiedContractIdentifier, contract_analysis: &ContractAnalysis, - ) -> Result<(), CheckError> { + ) -> Result<(), StaticCheckError> { self.with_analysis_db(|db, cost_tracker| { db.begin(); let result = db.insert_contract(identifier, contract_analysis); @@ -262,13 +275,13 @@ pub trait TransactionConnection: ClarityConnection { Ok(_) => { let result = db .commit() - .map_err(|e| CheckErrors::Expects(format!("{e:?}")).into()); + .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()); (cost_tracker, result) } Err(e) => { let result = db .roll_back() - .map_err(|e| CheckErrors::Expects(format!("{e:?}")).into()); + .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()); if result.is_err() { (cost_tracker, result) } else { @@ -287,12 +300,12 @@ pub trait TransactionConnection: ClarityConnection { to: &PrincipalData, amount: u128, memo: &BuffData, - ) -> Result<(Value, AssetMap, Vec), Error> { + ) -> Result<(Value, AssetMap, Vec), ClarityError> { self.with_abort_callback( |vm_env| { vm_env .stx_transfer(from, to, amount, memo) - .map_err(Error::from) + .map_err(ClarityError::from) }, |_, _| None, ) @@ -314,7 +327,7 @@ pub trait TransactionConnection: ClarityConnection { args: &[Value], abort_call_back: F, max_execution_time: Option, - ) -> Result<(Value, AssetMap, Vec), Error> + ) -> Result<(Value, AssetMap, Vec), ClarityError> where F: FnOnce(&AssetMap, &mut ClarityDatabase) -> Option, { @@ -338,13 +351,13 @@ pub trait TransactionConnection: ClarityConnection { public_function, &expr_args, ) - .map_err(Error::from) + .map_err(ClarityError::from) }, abort_call_back, ) .and_then(|(value, assets_modified, tx_events, reason)| { if let Some(reason) = reason { - Err(Error::AbortedByCallback { + Err(ClarityError::AbortedByCallback { output: Some(Box::new(value)), assets_modified: Box::new(assets_modified), tx_events, @@ -371,7 +384,7 @@ pub trait TransactionConnection: ClarityConnection { sponsor: Option, abort_call_back: F, max_execution_time: Option, - ) -> Result<(AssetMap, Vec), Error> + ) -> Result<(AssetMap, Vec), ClarityError> where F: FnOnce(&AssetMap, &mut ClarityDatabase) -> Option, { @@ -390,12 +403,12 @@ pub trait TransactionConnection: ClarityConnection { contract_str, sponsor, ) - .map_err(Error::from) + .map_err(ClarityError::from) }, abort_call_back, )?; if let Some(reason) = reason { - Err(Error::AbortedByCallback { + Err(ClarityError::AbortedByCallback { output: None, assets_modified: Box::new(assets_modified), tx_events, diff --git a/clarity/src/vm/contexts.rs b/clarity/src/vm/contexts.rs index 116c631387f..4904885914b 100644 --- a/clarity/src/vm/contexts.rs +++ b/clarity/src/vm/contexts.rs @@ -21,6 +21,7 @@ use std::time::{Duration, Instant}; pub use clarity_types::errors::StackTrace; use clarity_types::representations::ClarityName; +use clarity_types::VmExecutionError; use serde::Serialize; use serde_json::json; use stacks_common::types::chainstate::StacksBlockId; @@ -37,7 +38,7 @@ use crate::vm::database::{ NonFungibleTokenMetadata, }; use crate::vm::errors::{ - CheckErrors, InterpreterError, InterpreterResult as Result, RuntimeErrorType, + CheckErrorKind, InterpreterResult as Result, RuntimeError, VmInternalError, }; use crate::vm::events::*; use crate::vm::representations::SymbolicExpression; @@ -272,7 +273,7 @@ impl AssetMap { let current_amount = self.stx_map.get(principal).unwrap_or(&0); current_amount .checked_add(amount) - .ok_or(RuntimeErrorType::ArithmeticOverflow.into()) + .ok_or(RuntimeError::ArithmeticOverflow.into()) } // This will get the next amount for a (principal, stx) entry in the burn table. @@ -280,7 +281,7 @@ impl AssetMap { let current_amount = self.burn_map.get(principal).unwrap_or(&0); current_amount .checked_add(amount) - .ok_or(RuntimeErrorType::ArithmeticOverflow.into()) + .ok_or(RuntimeError::ArithmeticOverflow.into()) } // This will get the next amount for a (principal, asset) entry in the asset table. @@ -297,7 +298,7 @@ impl AssetMap { .unwrap_or(&0); current_amount .checked_add(amount) - .ok_or(RuntimeErrorType::ArithmeticOverflow.into()) + .ok_or(RuntimeError::ArithmeticOverflow.into()) } pub fn add_stx_transfer(&mut self, principal: &PrincipalData, amount: u128) -> Result<()> { @@ -441,7 +442,7 @@ impl AssetMap { for principal in self.burn_map.keys() { total = total .checked_add(*self.burn_map.get(principal).unwrap_or(&0u128)) - .ok_or_else(|| InterpreterError::Expect("BURN OVERFLOW".into()))?; + .ok_or_else(|| VmInternalError::Expect("BURN OVERFLOW".into()))?; } Ok(total) } @@ -605,7 +606,7 @@ impl<'a, 'hooks> OwnedEnvironment<'a, 'hooks> { f: F, ) -> std::result::Result<(A, AssetMap, Vec), E> where - E: From, + E: From, F: FnOnce(&mut Environment) -> std::result::Result, { assert!(self.context.is_top_level()); @@ -724,29 +725,24 @@ impl<'a, 'hooks> OwnedEnvironment<'a, 'hooks> { #[cfg(any(test, feature = "testing"))] pub fn stx_faucet(&mut self, recipient: &PrincipalData, amount: u128) { - self.execute_in_env::<_, _, crate::vm::errors::Error>( - recipient.clone(), - None, - None, - |env| { - let mut snapshot = env - .global_context - .database - .get_stx_balance_snapshot(recipient) - .unwrap(); + self.execute_in_env::<_, _, VmExecutionError>(recipient.clone(), None, None, |env| { + let mut snapshot = env + .global_context + .database + .get_stx_balance_snapshot(recipient) + .unwrap(); - snapshot.credit(amount).unwrap(); - snapshot.save().unwrap(); + snapshot.credit(amount).unwrap(); + snapshot.save().unwrap(); - env.global_context - .database - .increment_ustx_liquid_supply(amount) - .unwrap(); + env.global_context + .database + .increment_ustx_liquid_supply(amount) + .unwrap(); - let res: std::result::Result<(), crate::vm::errors::Error> = Ok(()); - res - }, - ) + let res: std::result::Result<(), VmExecutionError> = Ok(()); + res + }) .unwrap(); } @@ -782,8 +778,8 @@ impl<'a, 'hooks> OwnedEnvironment<'a, 'hooks> { pub fn commit(&mut self) -> Result<(AssetMap, EventBatch)> { let (asset_map, event_batch) = self.context.commit()?; - let asset_map = asset_map.ok_or(InterpreterError::FailedToConstructAssetTable)?; - let event_batch = event_batch.ok_or(InterpreterError::FailedToConstructEventBatch)?; + let asset_map = asset_map.ok_or(VmInternalError::FailedToConstructAssetTable)?; + let event_batch = event_batch.ok_or(VmInternalError::FailedToConstructEventBatch)?; Ok((asset_map, event_batch)) } @@ -950,7 +946,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { .expressions; if parsed.is_empty() { - return Err(RuntimeErrorType::ParseError( + return Err(RuntimeError::TypeParseFailure( "Expected a program of at least length 1".to_string(), ) .into()); @@ -999,7 +995,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { .expressions; if parsed.is_empty() { - return Err(RuntimeErrorType::ParseError( + return Err(RuntimeError::TypeParseFailure( "Expected a program of at least length 1".to_string(), ) .into()); @@ -1083,17 +1079,17 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { let contract = self.global_context.database.get_contract(contract_identifier)?; let func = contract.contract_context.lookup_function(tx_name) - .ok_or_else(|| { CheckErrors::UndefinedFunction(tx_name.to_string()) })?; + .ok_or_else(|| { CheckErrorKind::UndefinedFunction(tx_name.to_string()) })?; if !allow_private && !func.is_public() { - return Err(CheckErrors::NoSuchPublicFunction(contract_identifier.to_string(), tx_name.to_string()).into()); + return Err(CheckErrorKind::NoSuchPublicFunction(contract_identifier.to_string(), tx_name.to_string()).into()); } else if read_only && !func.is_read_only() { - return Err(CheckErrors::PublicFunctionNotReadOnly(contract_identifier.to_string(), tx_name.to_string()).into()); + return Err(CheckErrorKind::PublicFunctionNotReadOnly(contract_identifier.to_string(), tx_name.to_string()).into()); } let args: Result> = args.iter() .map(|arg| { let value = arg.match_atom_value() - .ok_or_else(|| InterpreterError::InterpreterError(format!("Passed non-value expression to exec_tx on {tx_name}!")))?; + .ok_or_else(|| VmInternalError::InvariantViolation(format!("Passed non-value expression to exec_tx on {tx_name}!")))?; // sanitize contract-call inputs in epochs >= 2.4 // testing todo: ensure sanitize_value() preserves trait callability! let expected_type = TypeSignature::type_of(value)?; @@ -1101,7 +1097,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { self.epoch(), &expected_type, value.clone(), - ).ok_or_else(|| CheckErrors::TypeValueError( + ).ok_or_else(|| CheckErrorKind::TypeValueError( Box::new(expected_type), Box::new(value.clone()), ) @@ -1115,7 +1111,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { let func_identifier = func.get_identifier(); if self.call_stack.contains(&func_identifier) { - return Err(CheckErrors::CircularReference(vec![func_identifier.to_string()]).into()) + return Err(CheckErrorKind::CircularReference(vec![func_identifier.to_string()]).into()) } self.call_stack.insert(&func_identifier, true); let res = self.execute_function_as_transaction(&func, &args, Some(&contract.contract_context), allow_private); @@ -1197,7 +1193,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { .database .set_block_hash(prior_bhh, true) .map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "ERROR: Failed to restore prior active block after time-shifted evaluation." .into()) })?; @@ -1255,7 +1251,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { .has_contract(&contract_identifier) { return Err( - CheckErrors::ContractAlreadyExists(contract_identifier.to_string()).into(), + CheckErrorKind::ContractAlreadyExists(contract_identifier.to_string()).into(), ); } @@ -1320,7 +1316,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { } Err(_) => { self.global_context.roll_back()?; - Err(InterpreterError::InsufficientBalance.into()) + Err(VmInternalError::InsufficientBalance.into()) } }, Err(e) => { @@ -1333,7 +1329,7 @@ impl<'a, 'b, 'hooks> Environment<'a, 'b, 'hooks> { pub fn run_as_transaction(&mut self, f: F) -> std::result::Result where F: FnOnce(&mut Self) -> std::result::Result, - E: From, + E: From, { self.global_context.begin(); let result = f(self); @@ -1548,7 +1544,7 @@ impl<'a, 'hooks> GlobalContext<'a, 'hooks> { fn get_asset_map(&mut self) -> Result<&mut AssetMap> { self.asset_maps .last_mut() - .ok_or_else(|| InterpreterError::Expect("Failed to obtain asset map".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to obtain asset map".into()).into()) } pub fn log_asset_transfer( @@ -1614,7 +1610,7 @@ impl<'a, 'hooks> GlobalContext<'a, 'hooks> { f: F, ) -> std::result::Result where - E: From, + E: From, F: FnOnce(&mut Environment) -> std::result::Result, { self.begin(); @@ -1665,10 +1661,10 @@ impl<'a, 'hooks> GlobalContext<'a, 'hooks> { trace!("Calling commit"); self.read_only.pop(); let asset_map = self.asset_maps.pop().ok_or_else(|| { - InterpreterError::Expect("ERROR: Committed non-nested context.".into()) + VmInternalError::Expect("ERROR: Committed non-nested context.".into()) })?; let mut event_batch = self.event_batches.pop().ok_or_else(|| { - InterpreterError::Expect("ERROR: Committed non-nested context.".into()) + VmInternalError::Expect("ERROR: Committed non-nested context.".into()) })?; let out_map = match self.asset_maps.last_mut() { @@ -1697,15 +1693,15 @@ impl<'a, 'hooks> GlobalContext<'a, 'hooks> { pub fn roll_back(&mut self) -> Result<()> { let popped = self.asset_maps.pop(); if popped.is_none() { - return Err(InterpreterError::Expect("Expected entry to rollback".into()).into()); + return Err(VmInternalError::Expect("Expected entry to rollback".into()).into()); } let popped = self.read_only.pop(); if popped.is_none() { - return Err(InterpreterError::Expect("Expected entry to rollback".into()).into()); + return Err(VmInternalError::Expect("Expected entry to rollback".into()).into()); } let popped = self.event_batches.pop(); if popped.is_none() { - return Err(InterpreterError::Expect("Expected entry to rollback".into()).into()); + return Err(VmInternalError::Expect("Expected entry to rollback".into()).into()); } self.database.roll_back() @@ -1731,7 +1727,7 @@ impl<'a, 'hooks> GlobalContext<'a, 'hooks> { self.commit()?; Ok(result) } else { - Err(CheckErrors::PublicFunctionMustReturnResponse(Box::new( + Err(CheckErrorKind::PublicFunctionMustReturnResponse(Box::new( TypeSignature::type_of(&result)?, )) .into()) @@ -1852,7 +1848,7 @@ impl<'a> LocalContext<'a> { pub fn extend(&'a self) -> Result> { if self.depth >= MAX_CONTEXT_DEPTH { - Err(RuntimeErrorType::MaxContextDepthReached.into()) + Err(RuntimeError::MaxContextDepthReached.into()) } else { Ok(LocalContext { function_context: Some(self.function_context()), @@ -1926,20 +1922,20 @@ impl CallStack { pub fn remove(&mut self, function: &FunctionIdentifier, tracked: bool) -> Result<()> { if let Some(removed) = self.stack.pop() { if removed != *function { - return Err(InterpreterError::InterpreterError( + return Err(VmInternalError::InvariantViolation( "Tried to remove item from empty call stack.".to_string(), ) .into()); } if tracked && !self.set.remove(function) { - return Err(InterpreterError::InterpreterError( + return Err(VmInternalError::InvariantViolation( "Tried to remove tracked function from call stack, but could not find in current context.".into() ) .into()); } Ok(()) } else { - Err(InterpreterError::InterpreterError( + Err(VmInternalError::InvariantViolation( "Tried to remove item from empty call stack.".to_string(), ) .into()) @@ -2140,7 +2136,7 @@ mod test { &BuffData::empty(), ) .unwrap_err(); - assert_eq!(e.to_string(), "Interpreter(InsufficientBalance)"); + assert_eq!(e.to_string(), "Internal(InsufficientBalance)"); } #[test] diff --git a/clarity/src/vm/costs/cost_functions.rs b/clarity/src/vm/costs/cost_functions.rs index 6abbaec5556..089ab23c203 100644 --- a/clarity/src/vm/costs/cost_functions.rs +++ b/clarity/src/vm/costs/cost_functions.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use clarity_types::VmExecutionError; + use super::ExecutionCost; -use crate::vm::errors::{InterpreterResult, RuntimeErrorType}; +use crate::vm::errors::{InterpreterResult, RuntimeError}; define_named_enum!(ClarityCostFunction { AnalysisTypeAnnotate("cost_analysis_type_annotate"), @@ -169,8 +171,8 @@ pub fn linear(n: u64, a: u64, b: u64) -> u64 { } pub fn logn(n: u64, a: u64, b: u64) -> InterpreterResult { if n < 1 { - return Err(crate::vm::errors::Error::Runtime( - RuntimeErrorType::Arithmetic("log2 must be passed a positive integer".to_string()), + return Err(VmExecutionError::Runtime( + RuntimeError::Arithmetic("log2 must be passed a positive integer".to_string()), Some(vec![]), )); } @@ -179,8 +181,8 @@ pub fn logn(n: u64, a: u64, b: u64) -> InterpreterResult { } pub fn nlogn(n: u64, a: u64, b: u64) -> InterpreterResult { if n < 1 { - return Err(crate::vm::errors::Error::Runtime( - RuntimeErrorType::Arithmetic("log2 must be passed a positive integer".to_string()), + return Err(VmExecutionError::Runtime( + RuntimeError::Arithmetic("log2 must be passed a positive integer".to_string()), Some(vec![]), )); } @@ -484,7 +486,7 @@ impl ClarityCostFunction { ClarityCostFunction::BitwiseRShift => C::cost_bitwise_right_shift(n), ClarityCostFunction::ContractHash => C::cost_contract_hash(n), ClarityCostFunction::ToAscii => C::cost_to_ascii(n), - ClarityCostFunction::Unimplemented => Err(RuntimeErrorType::NotImplemented.into()), + ClarityCostFunction::Unimplemented => Err(RuntimeError::NotImplemented.into()), } } } diff --git a/clarity/src/vm/costs/costs_1.rs b/clarity/src/vm/costs/costs_1.rs index 1e400f56bd5..2292052a121 100644 --- a/clarity/src/vm/costs/costs_1.rs +++ b/clarity/src/vm/costs/costs_1.rs @@ -16,7 +16,7 @@ /// This file implements the cost functions from costs.clar in Rust. use super::cost_functions::{linear, logn, nlogn, CostValues}; use super::ExecutionCost; -use crate::vm::errors::{InterpreterResult, RuntimeErrorType}; +use crate::vm::errors::{InterpreterResult, RuntimeError}; pub struct Costs1; @@ -651,106 +651,106 @@ impl CostValues for Costs1 { } fn cost_buff_to_int_le(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_uint_le(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_int_be(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_uint_be(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_is_standard(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_principal_destruct(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_principal_construct(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_string_to_int(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_string_to_uint(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_int_to_ascii(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_int_to_utf8(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_burn_block_info(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_stx_account(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_slice(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_to_consensus_buff(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_from_consensus_buff(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_stx_transfer_memo(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_replace_at(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_as_contract(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_and(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_or(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_not(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_left_shift(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_right_shift(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_contract_hash(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_to_ascii(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } } diff --git a/clarity/src/vm/costs/costs_2.rs b/clarity/src/vm/costs/costs_2.rs index 451008bd1b9..d964d8a0ca5 100644 --- a/clarity/src/vm/costs/costs_2.rs +++ b/clarity/src/vm/costs/costs_2.rs @@ -16,7 +16,7 @@ /// This file implements the cost functions from costs-2.clar in Rust. use super::cost_functions::{linear, logn, nlogn, CostValues}; use super::ExecutionCost; -use crate::vm::errors::{InterpreterResult, RuntimeErrorType}; +use crate::vm::errors::{InterpreterResult, RuntimeError}; pub struct Costs2; @@ -651,106 +651,106 @@ impl CostValues for Costs2 { } fn cost_buff_to_int_le(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_uint_le(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_int_be(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_uint_be(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_is_standard(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_principal_destruct(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_principal_construct(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_string_to_int(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_string_to_uint(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_int_to_ascii(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_int_to_utf8(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_burn_block_info(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_stx_account(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_slice(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_to_consensus_buff(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_from_consensus_buff(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_stx_transfer_memo(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_replace_at(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_as_contract(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_and(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_or(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_not(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_left_shift(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_right_shift(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_contract_hash(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_to_ascii(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } } diff --git a/clarity/src/vm/costs/costs_2_testnet.rs b/clarity/src/vm/costs/costs_2_testnet.rs index 647bafedb96..ea67fd93991 100644 --- a/clarity/src/vm/costs/costs_2_testnet.rs +++ b/clarity/src/vm/costs/costs_2_testnet.rs @@ -16,7 +16,7 @@ /// This file implements the cost functions from costs-2-testnet.clar in Rust. use super::cost_functions::{linear, logn, nlogn, CostValues}; use super::ExecutionCost; -use crate::vm::errors::{InterpreterResult, RuntimeErrorType}; +use crate::vm::errors::{InterpreterResult, RuntimeError}; pub struct Costs2Testnet; @@ -651,106 +651,106 @@ impl CostValues for Costs2Testnet { } fn cost_buff_to_int_le(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_uint_le(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_int_be(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_buff_to_uint_be(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_is_standard(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_principal_destruct(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_principal_construct(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_string_to_int(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_string_to_uint(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_int_to_ascii(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_int_to_utf8(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_burn_block_info(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_stx_account(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_slice(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_to_consensus_buff(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_from_consensus_buff(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_stx_transfer_memo(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_replace_at(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_as_contract(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_and(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_or(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_not(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_left_shift(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_bitwise_right_shift(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_contract_hash(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_to_ascii(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } } diff --git a/clarity/src/vm/costs/costs_3.rs b/clarity/src/vm/costs/costs_3.rs index b195303510c..c64c68f7190 100644 --- a/clarity/src/vm/costs/costs_3.rs +++ b/clarity/src/vm/costs/costs_3.rs @@ -16,7 +16,7 @@ /// This file implements the cost functions from costs-3.clar in Rust. use super::cost_functions::{linear, logn, nlogn, CostValues}; use super::ExecutionCost; -use crate::vm::errors::{InterpreterResult, RuntimeErrorType}; +use crate::vm::errors::{InterpreterResult, RuntimeError}; pub struct Costs3; @@ -765,10 +765,10 @@ impl CostValues for Costs3 { } fn cost_contract_hash(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } fn cost_to_ascii(n: u64) -> InterpreterResult { - Err(RuntimeErrorType::NotImplemented.into()) + Err(RuntimeError::NotImplemented.into()) } } diff --git a/clarity/src/vm/costs/mod.rs b/clarity/src/vm/costs/mod.rs index 669f6f483dc..e19be42348f 100644 --- a/clarity/src/vm/costs/mod.rs +++ b/clarity/src/vm/costs/mod.rs @@ -19,6 +19,7 @@ use std::{cmp, fmt}; pub use clarity_types::errors::CostErrors; pub use clarity_types::execution_cost::{CostOverflowingMath, ExecutionCost}; +use clarity_types::VmExecutionError; use costs_1::Costs1; use costs_2::Costs2; use costs_2_testnet::Costs2Testnet; @@ -28,7 +29,7 @@ use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use stacks_common::types::StacksEpochId; -use super::errors::{CheckErrors, RuntimeErrorType}; +use super::errors::{CheckErrorKind, RuntimeError}; use crate::boot_util::boot_code_id; use crate::vm::contexts::{ContractContext, GlobalContext}; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -215,8 +216,9 @@ impl DefaultVersion { }; r.map_err(|e| { let e = match e { - crate::vm::errors::Error::Runtime(RuntimeErrorType::NotImplemented, _) => { - CheckErrors::UndefinedFunction(cost_function_ref.function_name.clone()).into() + VmExecutionError::Runtime(RuntimeError::NotImplemented, _) => { + CheckErrorKind::UndefinedFunction(cost_function_ref.function_name.clone()) + .into() } other => other, }; diff --git a/clarity/src/vm/coverage.rs b/clarity/src/vm/coverage.rs index 15f41b6693a..afbf45a87aa 100644 --- a/clarity/src/vm/coverage.rs +++ b/clarity/src/vm/coverage.rs @@ -241,7 +241,7 @@ impl EvalHook for CoverageReporter { _env: &mut crate::vm::Environment, _context: &crate::vm::LocalContext, _expr: &SymbolicExpression, - _res: &core::result::Result, + _res: &core::result::Result, ) { } diff --git a/clarity/src/vm/database/clarity_db.rs b/clarity/src/vm/database/clarity_db.rs index f565185352b..f770a2fe741 100644 --- a/clarity/src/vm/database/clarity_db.rs +++ b/clarity/src/vm/database/clarity_db.rs @@ -37,7 +37,7 @@ use crate::vm::database::structures::{ }; use crate::vm::database::{ClarityBackingStore, RollbackWrapper}; use crate::vm::errors::{ - CheckErrors, Error, InterpreterError, InterpreterResult as Result, RuntimeErrorType, + CheckErrorKind, InterpreterResult as Result, RuntimeError, VmExecutionError, VmInternalError, }; use crate::vm::representations::ClarityName; use crate::vm::types::serialization::NONE_SERIALIZATION_LEN; @@ -541,12 +541,12 @@ impl<'a> ClarityDatabase<'a> { let serialized = if sanitize { let value_size = value .serialized_size() - .map_err(|e| InterpreterError::Expect(e.to_string()))? + .map_err(|e| VmInternalError::Expect(e.to_string()))? as u64; let (sanitized_value, did_sanitize) = Value::sanitize_value(epoch, &TypeSignature::type_of(&value)?, value) - .ok_or_else(|| CheckErrors::CouldNotDetermineType)?; + .ok_or_else(|| CheckErrorKind::CouldNotDetermineType)?; // if data needed to be sanitized *charge* for the unsanitized cost if did_sanitize { pre_sanitized_size = Some(value_size); @@ -571,7 +571,7 @@ impl<'a> ClarityDatabase<'a> { ) -> Result> { self.store .get_value(key, expected, epoch) - .map_err(|e| InterpreterError::DBError(e.to_string()).into()) + .map_err(|e| VmInternalError::DBError(e.to_string()).into()) } pub fn get_data_with_proof(&mut self, key: &str) -> Result)>> @@ -686,7 +686,10 @@ impl<'a> ClarityDatabase<'a> { data: &str, ) -> Result<()> { if self.store.has_metadata_entry(contract_identifier, key) { - Err(Error::Runtime(RuntimeErrorType::MetadataAlreadySet, None)) + Err(VmExecutionError::Runtime( + RuntimeError::MetadataAlreadySet, + None, + )) } else { Ok(self.store.insert_metadata(contract_identifier, key, data)?) } @@ -699,7 +702,7 @@ impl<'a> ClarityDatabase<'a> { data: &T, ) -> Result<()> { if self.store.has_metadata_entry(contract_identifier, key) { - Err(InterpreterError::Expect(format!( + Err(VmInternalError::Expect(format!( "Metadata entry '{key}' already exists for contract: {contract_identifier}" )) .into()) @@ -754,7 +757,7 @@ impl<'a> ClarityDatabase<'a> { self.store .get_metadata(contract_identifier, AnalysisDatabase::storage_key()) // treat NoSuchContract error thrown by get_metadata as an Option::None -- - // the analysis will propagate that as a CheckError anyways. + // the analysis will propagate that as a StaticCheckError anyways. .ok() .flatten() .map(|x| ContractAnalysis::deserialize(&x)) @@ -772,7 +775,7 @@ impl<'a> ClarityDatabase<'a> { let contract_size: u64 = self.fetch_metadata(contract_identifier, &key)? .ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "Failed to read non-consensus contract metadata, even though contract exists in MARF." .into()) })?; @@ -783,7 +786,7 @@ impl<'a> ClarityDatabase<'a> { let data_size: u64 = self .fetch_metadata(contract_identifier, &key)? .ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "Failed to read non-consensus contract metadata, even though contract exists in MARF." .into()) })?; @@ -805,7 +808,7 @@ impl<'a> ClarityDatabase<'a> { let contract_size: u64 = self.fetch_metadata(contract_identifier, &key)? .ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "Failed to read non-consensus contract metadata, even though contract exists in MARF." .into()) })?; @@ -849,7 +852,7 @@ impl<'a> ClarityDatabase<'a> { ContractDataVarName::Contract.as_str(), ); let mut data: Contract = self.fetch_metadata(contract_identifier, &key)? - .ok_or_else(|| InterpreterError::Expect( + .ok_or_else(|| VmInternalError::Expect( "Failed to read non-consensus contract metadata, even though contract exists in MARF." .into()))?; data.canonicalize_types(&self.get_clarity_epoch_version()?); @@ -867,7 +870,7 @@ impl<'a> ClarityDatabase<'a> { pub fn get_clarity_epoch_version(&mut self) -> Result { let out = match self.get_data(Self::clarity_state_epoch_key())? { Some(x) => u32::try_into(x).map_err(|_| { - InterpreterError::Expect("Bad Clarity epoch version in stored Clarity state".into()) + VmInternalError::Expect("Bad Clarity epoch version in stored Clarity state".into()) })?, None => StacksEpochId::Epoch20, }; @@ -885,7 +888,7 @@ impl<'a> ClarityDatabase<'a> { let epoch = self.get_clarity_epoch_version()?; if epoch.uses_marfed_block_time() { let block_time = block_time.ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "FATAL: Marfed block time not provided to Clarity DB setup".into(), ) })?; @@ -897,7 +900,7 @@ impl<'a> ClarityDatabase<'a> { pub fn get_current_block_time(&mut self) -> Result { match self.get_data(CLARITY_STORAGE_BLOCK_TIME_KEY)? { Some(value) => Ok(value), - None => Err(RuntimeErrorType::BlockTimeNotAvailable.into()), + None => Err(RuntimeError::BlockTimeNotAvailable.into()), } } @@ -911,7 +914,7 @@ impl<'a> ClarityDatabase<'a> { &epoch, ) .map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "FATAL: failed to load ustx_liquid_supply Clarity key".into(), ) })? @@ -928,7 +931,7 @@ impl<'a> ClarityDatabase<'a> { &StacksEpochId::Epoch21, ) .map_err(|_| { - InterpreterError::Expect("FATAL: Failed to store STX liquid supply".into()).into() + VmInternalError::Expect("FATAL: Failed to store STX liquid supply".into()).into() }) } @@ -936,7 +939,7 @@ impl<'a> ClarityDatabase<'a> { let current = self.get_total_liquid_ustx()?; let next = current.checked_add(incr_by).ok_or_else(|| { error!("Overflowed `ustx-liquid-supply`"); - RuntimeErrorType::ArithmeticOverflow + RuntimeError::ArithmeticOverflow })?; self.set_ustx_liquid_supply(next)?; Ok(()) @@ -946,7 +949,7 @@ impl<'a> ClarityDatabase<'a> { let current = self.get_total_liquid_ustx()?; let next = current.checked_sub(decr_by).ok_or_else(|| { error!("`stx-burn?` accepted that reduces `ustx-liquid-supply` below 0"); - RuntimeErrorType::ArithmeticUnderflow + RuntimeError::ArithmeticUnderflow })?; self.set_ustx_liquid_supply(next)?; Ok(()) @@ -962,11 +965,11 @@ impl<'a> ClarityDatabase<'a> { self.get_data(TENURE_HEIGHT_KEY)? .ok_or_else(|| { - InterpreterError::Expect("No tenure height in stored Clarity state".into()).into() + VmInternalError::Expect("No tenure height in stored Clarity state".into()).into() }) .and_then(|x| { u32::try_into(x).map_err(|_| { - InterpreterError::Expect("Bad tenure height in stored Clarity state".into()) + VmInternalError::Expect("Bad tenure height in stored Clarity state".into()) .into() }) }) @@ -977,7 +980,7 @@ impl<'a> ClarityDatabase<'a> { /// transactions in the block. pub fn set_tenure_height(&mut self, height: u32) -> Result<()> { if self.get_clarity_epoch_version()? < StacksEpochId::Epoch30 { - return Err(Error::Interpreter(InterpreterError::Expect( + return Err(VmExecutionError::Internal(VmInternalError::Expect( "Setting tenure height in Clarity state is not supported before epoch 3.0".into(), ))); } @@ -1005,7 +1008,7 @@ impl ClarityDatabase<'_> { // the caller is responsible for ensuring that the block_height given // is < current_block_height, so this should _always_ return a value. .ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "Block header hash must return for provided block height".into(), ) .into() @@ -1108,7 +1111,7 @@ impl ClarityDatabase<'_> { self.get_burnchain_block_height(&last_mined_bhh) .ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "Block header hash '{last_mined_bhh}' must return for provided stacks block height {cur_stacks_height}" )) .into() @@ -1118,7 +1121,7 @@ impl ClarityDatabase<'_> { self.burn_state_db .get_tip_burn_block_height() .ok_or_else(|| { - InterpreterError::Expect("Failed to get burnchain tip height.".into()).into() + VmInternalError::Expect("Failed to get burnchain tip height.".into()).into() }) } } @@ -1128,7 +1131,7 @@ impl ClarityDatabase<'_> { let epoch = self.get_stacks_epoch_for_block(&id_bhh)?; self.headers_db .get_stacks_block_header_hash_for_block(&id_bhh, &epoch) - .ok_or_else(|| InterpreterError::Expect("Failed to get block data.".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to get block data.".into()).into()) } pub fn get_burn_block_time( @@ -1143,7 +1146,7 @@ impl ClarityDatabase<'_> { let epoch = self.get_stacks_epoch_for_block(&id_bhh)?; self.headers_db .get_burn_block_time_for_block(&id_bhh, Some(&epoch)) - .ok_or_else(|| InterpreterError::Expect("Failed to get block data.".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to get block data.".into()).into()) } pub fn get_block_time(&mut self, block_height: u32) -> Result { @@ -1155,7 +1158,7 @@ impl ClarityDatabase<'_> { self.headers_db .get_stacks_block_time_for_block(&id_bhh) - .ok_or_else(|| InterpreterError::Expect("Failed to get block data.".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to get block data.".into()).into()) } pub fn get_burnchain_block_header_hash( @@ -1165,7 +1168,7 @@ impl ClarityDatabase<'_> { let id_bhh = self.get_index_block_header_hash(block_height)?; self.headers_db .get_burn_header_hash_for_block(&id_bhh) - .ok_or_else(|| InterpreterError::Expect("Failed to get block data.".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to get block data.".into()).into()) } /// In Epoch 2.x: @@ -1198,7 +1201,7 @@ impl ClarityDatabase<'_> { .headers_db .get_consensus_hash_for_block(&parent_id_bhh, &epoch) .ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "FATAL: no consensus hash found for StacksBlockId {parent_id_bhh}" )) })?; @@ -1208,7 +1211,7 @@ impl ClarityDatabase<'_> { .burn_state_db .get_sortition_id_from_consensus_hash(&consensus_hash) .ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "FATAL: no SortitionID found for consensus hash {consensus_hash}" )) })?; @@ -1263,7 +1266,7 @@ impl ClarityDatabase<'_> { let epoch = self.get_stacks_epoch_for_block(&id_bhh)?; self.headers_db .get_vrf_seed_for_block(&id_bhh, &epoch) - .ok_or_else(|| InterpreterError::Expect("Failed to get block data.".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to get block data.".into()).into()) } pub fn get_miner_address(&mut self, block_height: u32) -> Result { @@ -1272,7 +1275,7 @@ impl ClarityDatabase<'_> { Ok(self .headers_db .get_miner_address(&id_bhh, &epoch) - .ok_or_else(|| InterpreterError::Expect("Failed to get block data.".into()))? + .ok_or_else(|| VmInternalError::Expect("Failed to get block data.".into()))? .into()) } @@ -1287,7 +1290,7 @@ impl ClarityDatabase<'_> { .headers_db .get_burnchain_tokens_spent_for_winning_block(&id_bhh, &epoch) .ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "FATAL: no winning burnchain token spend record for block".into(), ) })?) @@ -1304,7 +1307,7 @@ impl ClarityDatabase<'_> { .headers_db .get_burnchain_tokens_spent_for_block(&id_bhh, &epoch) .ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "FATAL: no total burnchain token spend record for block".into(), ) })?) @@ -1329,7 +1332,7 @@ impl ClarityDatabase<'_> { .headers_db .get_tokens_earned_for_block(&id_bhh, &epoch) .ok_or_else(|| { - InterpreterError::Expect("FATAL: matured block has no recorded reward".into()) + VmInternalError::Expect("FATAL: matured block has no recorded reward".into()) })?; Ok(Some(reward)) @@ -1383,22 +1386,22 @@ impl ClarityDatabase<'_> { TupleData::from_data(vec![ ( ClarityName::try_from("reporter").map_err(|_| { - InterpreterError::Expect("BUG: valid string representation".into()) + VmInternalError::Expect("BUG: valid string representation".into()) })?, Value::Principal(PrincipalData::Standard(reporter.clone())), ), ( ClarityName::try_from("sequence").map_err(|_| { - InterpreterError::Expect("BUG: valid string representation".into()) + VmInternalError::Expect("BUG: valid string representation".into()) })?, Value::UInt(seq as u128), ), ]) - .map_err(|_| InterpreterError::Expect("BUG: valid tuple representation".into()))?, + .map_err(|_| VmInternalError::Expect("BUG: valid tuple representation".into()))?, ); let mut value_bytes = vec![]; value.serialize_write(&mut value_bytes).map_err(|_| { - InterpreterError::Expect("BUG: valid tuple representation did not serialize".into()) + VmInternalError::Expect("BUG: valid tuple representation did not serialize".into()) })?; let value_str = to_hex(&value_bytes); @@ -1413,7 +1416,7 @@ impl ClarityDatabase<'_> { self.get_data(&key)? .map(|height_str: String| { height_str.parse::().map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "BUG: inserted non-u32 as height of microblock pubkey hash".into(), ) .into() @@ -1432,7 +1435,7 @@ impl ClarityDatabase<'_> { .map(|reporter_hex_str: String| { let reporter_value = Value::try_deserialize_hex_untyped(&reporter_hex_str) .map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "BUG: failed to decode serialized poison-microblock reporter".into(), ) })?; @@ -1440,7 +1443,7 @@ impl ClarityDatabase<'_> { let reporter_value = tuple_data .get("reporter") .map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "BUG: poison-microblock report has no 'reporter'".into(), ) })? @@ -1448,7 +1451,7 @@ impl ClarityDatabase<'_> { let seq_value = tuple_data .get("sequence") .map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "BUG: poison-microblock report has no 'sequence'".into(), ) })? @@ -1459,11 +1462,11 @@ impl ClarityDatabase<'_> { let seq: u16 = seq_u128 .try_into() - .map_err(|_| InterpreterError::Expect("BUG: seq exceeds u16 max".into()))?; + .map_err(|_| VmInternalError::Expect("BUG: seq exceeds u16 max".into()))?; if let PrincipalData::Standard(principal_data) = reporter_principal { Ok((principal_data, seq)) } else { - Err(InterpreterError::Expect( + Err(VmInternalError::Expect( "BUG: poison-microblock report principal is not a standard principal" .into(), ) @@ -1478,7 +1481,7 @@ impl ClarityDatabase<'_> { // will throw NoSuchFoo errors instead of NoSuchContract errors. fn map_no_contract_as_none(res: Result>) -> Result> { res.or_else(|e| match e { - Error::Unchecked(CheckErrors::NoSuchContract(_)) => Ok(None), + VmExecutionError::Unchecked(CheckErrorKind::NoSuchContract(_)) => Ok(None), x => Err(x), }) } @@ -1506,7 +1509,7 @@ impl ClarityDatabase<'_> { let key = ClarityDatabase::make_metadata_key(StoreType::VariableMeta, variable_name); map_no_contract_as_none(self.fetch_metadata(contract_identifier, &key))? - .ok_or(CheckErrors::NoSuchDataVariable(variable_name.to_string()).into()) + .ok_or(CheckErrorKind::NoSuchDataVariable(variable_name.to_string()).into()) } #[cfg(any(test, feature = "testing"))] @@ -1540,7 +1543,7 @@ impl ClarityDatabase<'_> { .value_type .admits(&self.get_clarity_epoch_version()?, &value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(variable_descriptor.value_type.clone()), Box::new(value), ) @@ -1647,7 +1650,7 @@ impl ClarityDatabase<'_> { let key = ClarityDatabase::make_metadata_key(StoreType::DataMapMeta, map_name); map_no_contract_as_none(self.fetch_metadata(contract_identifier, &key))? - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()).into()) + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()).into()) } pub fn make_key_for_data_map_entry( @@ -1699,7 +1702,7 @@ impl ClarityDatabase<'_> { .key_type .admits(&self.get_clarity_epoch_version()?, key_value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(map_descriptor.key_type.clone()), Box::new(key_value.clone()), ) @@ -1730,7 +1733,7 @@ impl ClarityDatabase<'_> { .key_type .admits(&self.get_clarity_epoch_version()?, key_value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(map_descriptor.key_type.clone()), Box::new(key_value.clone()), ) @@ -1760,7 +1763,7 @@ impl ClarityDatabase<'_> { serialized_byte_len: serialized_byte_len .checked_add(byte_len_of_serialization(&key_serialized)) .ok_or_else(|| { - InterpreterError::Expect("Overflowed Clarity key/value size".into()) + VmInternalError::Expect("Overflowed Clarity key/value size".into()) })?, }), } @@ -1873,7 +1876,7 @@ impl ClarityDatabase<'_> { .key_type .admits(&self.get_clarity_epoch_version()?, &key_value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(map_descriptor.key_type.clone()), Box::new(key_value), ) @@ -1883,7 +1886,7 @@ impl ClarityDatabase<'_> { .value_type .admits(&self.get_clarity_epoch_version()?, &value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(map_descriptor.value_type.clone()), Box::new(value), ) @@ -1915,7 +1918,7 @@ impl ClarityDatabase<'_> { serialized_byte_len: key_serialized_byte_len .checked_add(placed_size) .ok_or_else(|| { - InterpreterError::Expect("Overflowed Clarity key/value size".into()) + VmInternalError::Expect("Overflowed Clarity key/value size".into()) })?, }) } @@ -1932,7 +1935,7 @@ impl ClarityDatabase<'_> { .key_type .admits(&self.get_clarity_epoch_version()?, key_value)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(map_descriptor.key_type.clone()), Box::new(key_value.clone()), ) @@ -1962,7 +1965,7 @@ impl ClarityDatabase<'_> { serialized_byte_len: key_serialized_byte_len .checked_add(*NONE_SERIALIZATION_LEN) .ok_or_else(|| { - InterpreterError::Expect("Overflowed Clarity key/value size".into()) + VmInternalError::Expect("Overflowed Clarity key/value size".into()) })?, }) } @@ -2003,7 +2006,7 @@ impl ClarityDatabase<'_> { let key = ClarityDatabase::make_metadata_key(StoreType::FungibleTokenMeta, token_name); map_no_contract_as_none(self.fetch_metadata(contract_identifier, &key))? - .ok_or(CheckErrors::NoSuchFT(token_name.to_string()).into()) + .ok_or(CheckErrorKind::NoSuchFT(token_name.to_string()).into()) } pub fn create_non_fungible_token( @@ -2029,7 +2032,7 @@ impl ClarityDatabase<'_> { let key = ClarityDatabase::make_metadata_key(StoreType::NonFungibleTokenMeta, token_name); map_no_contract_as_none(self.fetch_metadata(contract_identifier, &key))? - .ok_or(CheckErrors::NoSuchNFT(token_name.to_string()).into()) + .ok_or(CheckErrorKind::NoSuchNFT(token_name.to_string()).into()) } pub fn checked_increase_token_supply( @@ -2045,16 +2048,16 @@ impl ClarityDatabase<'_> { token_name, ); let current_supply: u128 = self.get_data(&key)?.ok_or_else(|| { - InterpreterError::Expect("ERROR: Clarity VM failed to track token supply.".into()) + VmInternalError::Expect("ERROR: Clarity VM failed to track token supply.".into()) })?; let new_supply = current_supply .checked_add(amount) - .ok_or(RuntimeErrorType::ArithmeticOverflow)?; + .ok_or(RuntimeError::ArithmeticOverflow)?; if let Some(total_supply) = descriptor.total_supply { if new_supply > total_supply { - return Err(RuntimeErrorType::SupplyOverflow(new_supply, total_supply).into()); + return Err(RuntimeError::SupplyOverflow(new_supply, total_supply).into()); } } @@ -2073,11 +2076,11 @@ impl ClarityDatabase<'_> { token_name, ); let current_supply: u128 = self.get_data(&key)?.ok_or_else(|| { - InterpreterError::Expect("ERROR: Clarity VM failed to track token supply.".into()) + VmInternalError::Expect("ERROR: Clarity VM failed to track token supply.".into()) })?; if amount > current_supply { - return Err(RuntimeErrorType::SupplyUnderflow(current_supply, amount).into()); + return Err(RuntimeError::SupplyUnderflow(current_supply, amount).into()); } let new_supply = current_supply - amount; @@ -2137,7 +2140,7 @@ impl ClarityDatabase<'_> { token_name, ); let supply = self.get_data(&key)?.ok_or_else(|| { - InterpreterError::Expect("ERROR: Clarity VM failed to track token supply.".into()) + VmInternalError::Expect("ERROR: Clarity VM failed to track token supply.".into()) })?; Ok(supply) } @@ -2150,7 +2153,7 @@ impl ClarityDatabase<'_> { key_type: &TypeSignature, ) -> Result { if !key_type.admits(&self.get_clarity_epoch_version()?, asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(key_type.clone()), Box::new(asset.clone()), ) @@ -2168,17 +2171,17 @@ impl ClarityDatabase<'_> { let value: Option = self.get_value( &key, &TypeSignature::new_option(TypeSignature::PrincipalType) - .map_err(|_| InterpreterError::Expect("Unexpected type failure".into()))?, + .map_err(|_| VmInternalError::Expect("Unexpected type failure".into()))?, &epoch, )?; let owner = match value { Some(owner) => owner.value.expect_optional()?, - None => return Err(RuntimeErrorType::NoSuchToken.into()), + None => return Err(RuntimeError::NoSuchToken.into()), }; let principal = match owner { Some(value) => value.expect_principal()?, - None => return Err(RuntimeErrorType::NoSuchToken.into()), + None => return Err(RuntimeError::NoSuchToken.into()), }; Ok(principal) @@ -2203,7 +2206,7 @@ impl ClarityDatabase<'_> { epoch: &StacksEpochId, ) -> Result<()> { if !key_type.admits(&self.get_clarity_epoch_version()?, asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(key_type.clone()), Box::new(asset.clone()), ) @@ -2232,7 +2235,7 @@ impl ClarityDatabase<'_> { epoch: &StacksEpochId, ) -> Result<()> { if !key_type.admits(&self.get_clarity_epoch_version()?, asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(key_type.clone()), Box::new(asset.clone()), ) @@ -2374,13 +2377,13 @@ impl ClarityDatabase<'_> { pub fn get_stacks_epoch_for_block(&self, id_bhh: &StacksBlockId) -> Result { let burn_block = self.get_burnchain_block_height(id_bhh).ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "FATAL: no burnchain block height found for Stacks block {id_bhh}" )) })?; let epoch = self .get_stacks_epoch(burn_block) - .ok_or_else(|| InterpreterError::Expect("Failed to get block data.".into()))?; + .ok_or_else(|| VmInternalError::Expect("Failed to get block data.".into()))?; Ok(epoch.epoch_id) } } diff --git a/clarity/src/vm/database/clarity_store.rs b/clarity/src/vm/database/clarity_store.rs index e1d6dacaeee..c3d388aa439 100644 --- a/clarity/src/vm/database/clarity_store.rs +++ b/clarity/src/vm/database/clarity_store.rs @@ -24,7 +24,7 @@ use crate::vm::contexts::GlobalContext; use crate::vm::database::{ ClarityDatabase, ClarityDeserializable, ClaritySerializable, NULL_BURN_STATE_DB, NULL_HEADER_DB, }; -use crate::vm::errors::{InterpreterError, InterpreterResult as Result}; +use crate::vm::errors::{InterpreterResult as Result, VmInternalError}; use crate::vm::types::{PrincipalData, QualifiedContractIdentifier}; use crate::vm::Value; @@ -160,17 +160,17 @@ impl ClaritySerializable for ContractCommitment { impl ClarityDeserializable for ContractCommitment { fn deserialize(input: &str) -> Result { if input.len() != 72 { - return Err(InterpreterError::Expect("Unexpected input length".into()).into()); + return Err(VmInternalError::Expect("Unexpected input length".into()).into()); } let hash = Sha512Trunc256Sum::from_hex(&input[0..64]) - .map_err(|_| InterpreterError::Expect("Hex decode fail.".into()))?; + .map_err(|_| VmInternalError::Expect("Hex decode fail.".into()))?; let height_bytes = hex_bytes(&input[64..72]) - .map_err(|_| InterpreterError::Expect("Hex decode fail.".into()))?; + .map_err(|_| VmInternalError::Expect("Hex decode fail.".into()))?; let block_height = u32::from_be_bytes( height_bytes .as_slice() .try_into() - .map_err(|_| InterpreterError::Expect("Block height decode fail.".into()))?, + .map_err(|_| VmInternalError::Expect("Block height decode fail.".into()))?, ); Ok(ContractCommitment { hash, block_height }) } diff --git a/clarity/src/vm/database/key_value_wrapper.rs b/clarity/src/vm/database/key_value_wrapper.rs index 5578ac549d7..236a7d0cfb7 100644 --- a/clarity/src/vm/database/key_value_wrapper.rs +++ b/clarity/src/vm/database/key_value_wrapper.rs @@ -24,7 +24,7 @@ use stacks_common::util::hash::Sha512Trunc256Sum; use super::clarity_store::SpecialCaseHandler; use super::{ClarityBackingStore, ClarityDeserializable}; use crate::vm::database::clarity_store::{make_contract_hash_key, ContractCommitment}; -use crate::vm::errors::{InterpreterError, InterpreterResult}; +use crate::vm::errors::{InterpreterResult, VmInternalError}; use crate::vm::types::serialization::SerializationError; use crate::vm::types::{QualifiedContractIdentifier, TypeSignature}; use crate::vm::Value; @@ -49,7 +49,7 @@ fn rollback_edits_push(edits: &mut Vec<(T, RollbackValueCheck)>, key: T, _val fn rollback_check_pre_bottom_commit( edits: Vec<(T, RollbackValueCheck)>, lookup_map: &mut HashMap>, -) -> Result, InterpreterError> +) -> Result, VmInternalError> where T: Eq + Hash + Clone, { @@ -86,7 +86,7 @@ where fn rollback_check_pre_bottom_commit( edits: Vec<(T, RollbackValueCheck)>, lookup_map: &mut HashMap>, -) -> Result, InterpreterError> +) -> Result, VmInternalError> where T: Eq + Hash + Clone, { @@ -179,19 +179,19 @@ fn rollback_lookup_map( key: &T, value: &RollbackValueCheck, lookup_map: &mut HashMap>, -) -> Result +) -> Result where T: Eq + Hash + Clone, { let popped_value; let remove_edit_deque = { let key_edit_history = lookup_map.get_mut(key).ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "ERROR: Clarity VM had edit log entry, but not lookup_map entry".into(), ) })?; popped_value = key_edit_history.pop().ok_or_else(|| { - InterpreterError::Expect("ERROR: expected value in edit history".into()) + VmInternalError::Expect("ERROR: expected value in edit history".into()) })?; rollback_value_check(&popped_value, value); key_edit_history.is_empty() @@ -240,9 +240,9 @@ impl<'a> RollbackWrapper<'a> { // Rollback the child's edits. // this clears all edits from the child's edit queue, // and removes any of those edits from the lookup map. - pub fn rollback(&mut self) -> Result<(), InterpreterError> { + pub fn rollback(&mut self) -> Result<(), VmInternalError> { let mut last_item = self.stack.pop().ok_or_else(|| { - InterpreterError::Expect("ERROR: Clarity VM attempted to commit past the stack.".into()) + VmInternalError::Expect("ERROR: Clarity VM attempted to commit past the stack.".into()) })?; last_item.edits.reverse(); @@ -263,9 +263,9 @@ impl<'a> RollbackWrapper<'a> { self.stack.len() } - pub fn commit(&mut self) -> Result<(), InterpreterError> { + pub fn commit(&mut self) -> Result<(), VmInternalError> { let mut last_item = self.stack.pop().ok_or_else(|| { - InterpreterError::Expect("ERROR: Clarity VM attempted to commit past the stack.".into()) + VmInternalError::Expect("ERROR: Clarity VM attempted to commit past the stack.".into()) })?; if let Some(next_up) = self.stack.last_mut() { @@ -283,7 +283,7 @@ impl<'a> RollbackWrapper<'a> { rollback_check_pre_bottom_commit(last_item.edits, &mut self.lookup_map)?; if !all_edits.is_empty() { self.store.put_all_data(all_edits).map_err(|e| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: Failed to commit data to sql store: {e:?}" )) })?; @@ -295,7 +295,7 @@ impl<'a> RollbackWrapper<'a> { )?; if !metadata_edits.is_empty() { self.store.put_all_metadata(metadata_edits).map_err(|e| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: Failed to commit data to sql store: {e:?}" )) })?; @@ -322,9 +322,7 @@ fn inner_put_data( impl RollbackWrapper<'_> { pub fn put_data(&mut self, key: &str, value: &str) -> InterpreterResult<()> { let current = self.stack.last_mut().ok_or_else(|| { - InterpreterError::Expect( - "ERROR: Clarity VM attempted PUT on non-nested context.".into(), - ) + VmInternalError::Expect("ERROR: Clarity VM attempted PUT on non-nested context.".into()) })?; inner_put_data( @@ -387,9 +385,7 @@ impl RollbackWrapper<'_> { T: ClarityDeserializable, { self.stack.last().ok_or_else(|| { - InterpreterError::Expect( - "ERROR: Clarity VM attempted GET on non-nested context.".into(), - ) + VmInternalError::Expect("ERROR: Clarity VM attempted GET on non-nested context.".into()) })?; if self.query_pending_data { @@ -503,11 +499,9 @@ impl RollbackWrapper<'_> { contract: &QualifiedContractIdentifier, key: &str, value: &str, - ) -> Result<(), InterpreterError> { + ) -> Result<(), VmInternalError> { let current = self.stack.last_mut().ok_or_else(|| { - InterpreterError::Expect( - "ERROR: Clarity VM attempted PUT on non-nested context.".into(), - ) + VmInternalError::Expect("ERROR: Clarity VM attempted PUT on non-nested context.".into()) })?; let metadata_key = (contract.clone(), key.to_string()); @@ -529,9 +523,7 @@ impl RollbackWrapper<'_> { key: &str, ) -> InterpreterResult> { self.stack.last().ok_or_else(|| { - InterpreterError::Expect( - "ERROR: Clarity VM attempted GET on non-nested context.".into(), - ) + VmInternalError::Expect("ERROR: Clarity VM attempted GET on non-nested context.".into()) })?; // This is THEORETICALLY a spurious clone, but it's hard to turn something like @@ -560,9 +552,7 @@ impl RollbackWrapper<'_> { key: &str, ) -> InterpreterResult> { self.stack.last().ok_or_else(|| { - InterpreterError::Expect( - "ERROR: Clarity VM attempted GET on non-nested context.".into(), - ) + VmInternalError::Expect("ERROR: Clarity VM attempted GET on non-nested context.".into()) })?; // This is THEORETICALLY a spurious clone, but it's hard to turn something like @@ -584,9 +574,7 @@ impl RollbackWrapper<'_> { pub fn has_entry(&mut self, key: &str) -> InterpreterResult { self.stack.last().ok_or_else(|| { - InterpreterError::Expect( - "ERROR: Clarity VM attempted GET on non-nested context.".into(), - ) + VmInternalError::Expect("ERROR: Clarity VM attempted GET on non-nested context.".into()) })?; if self.query_pending_data && self.lookup_map.contains_key(key) { Ok(true) diff --git a/clarity/src/vm/database/sqlite.rs b/clarity/src/vm/database/sqlite.rs index c1af5530416..514782fb846 100644 --- a/clarity/src/vm/database/sqlite.rs +++ b/clarity/src/vm/database/sqlite.rs @@ -25,9 +25,9 @@ use super::{ ClarityBackingStore, ClarityDatabase, ClarityDeserializable, SpecialCaseHandler, NULL_BURN_STATE_DB, NULL_HEADER_DB, }; -use crate::vm::analysis::{AnalysisDatabase, CheckErrors}; +use crate::vm::analysis::{AnalysisDatabase, CheckErrorKind}; use crate::vm::errors::{ - IncomparableError, InterpreterError, InterpreterResult as Result, RuntimeErrorType, + IncomparableError, InterpreterResult as Result, RuntimeError, VmInternalError, }; use crate::vm::types::QualifiedContractIdentifier; @@ -43,7 +43,7 @@ fn sqlite_put(conn: &Connection, key: &str, value: &str) -> Result<()> { Ok(_) => Ok(()), Err(e) => { error!("Failed to insert/replace ({key},{value}): {e:?}"); - Err(InterpreterError::DBError(SQL_FAIL_MESSAGE.into()).into()) + Err(VmInternalError::DBError(SQL_FAIL_MESSAGE.into()).into()) } } } @@ -62,7 +62,7 @@ fn sqlite_get(conn: &Connection, key: &str) -> Result> { Ok(x) => Ok(x), Err(e) => { error!("Failed to query '{key}': {e:?}"); - Err(InterpreterError::DBError(SQL_FAIL_MESSAGE.into()).into()) + Err(VmInternalError::DBError(SQL_FAIL_MESSAGE.into()).into()) } }; @@ -82,13 +82,13 @@ pub fn sqlite_get_contract_hash( let contract_commitment = store .get_data(&key)? .map(|x| ContractCommitment::deserialize(&x)) - .ok_or_else(|| CheckErrors::NoSuchContract(contract.to_string()))?; + .ok_or_else(|| CheckErrorKind::NoSuchContract(contract.to_string()))?; let ContractCommitment { block_height, hash: contract_hash, } = contract_commitment?; let bhh = store.get_block_at_height(block_height) - .ok_or_else(|| InterpreterError::Expect("Should always be able to map from height to block hash when looking up contract information.".into()))?; + .ok_or_else(|| VmInternalError::Expect("Should always be able to map from height to block hash when looking up contract information.".into()))?; Ok((bhh, contract_hash)) } @@ -125,7 +125,7 @@ pub fn sqlite_get_metadata_manual( ) -> Result> { let bhh = store.get_block_at_height(at_height).ok_or_else(|| { warn!("Unknown block height when manually querying metadata"; "block_height" => at_height); - RuntimeErrorType::BadBlockHeight(at_height.to_string()) + RuntimeError::BadBlockHeight(at_height.to_string()) })?; SqliteConnection::get_metadata(store.get_side_store(), &bhh, &contract.to_string(), key) } @@ -154,7 +154,7 @@ impl SqliteConnection { params, ) { error!("Failed to insert ({bhh},{key},{value}): {e:?}"); - return Err(InterpreterError::DBError(SQL_FAIL_MESSAGE.into()).into()); + return Err(VmInternalError::DBError(SQL_FAIL_MESSAGE.into()).into()); } Ok(()) } @@ -170,7 +170,7 @@ impl SqliteConnection { params, ) { error!("Failed to update {from} to {to}: {e:?}"); - return Err(InterpreterError::DBError(SQL_FAIL_MESSAGE.into()).into()); + return Err(VmInternalError::DBError(SQL_FAIL_MESSAGE.into()).into()); } Ok(()) } @@ -181,7 +181,7 @@ impl SqliteConnection { params![from], ) { error!("Failed to drop metadata from {from}: {e:?}"); - return Err(InterpreterError::DBError(SQL_FAIL_MESSAGE.into()).into()); + return Err(VmInternalError::DBError(SQL_FAIL_MESSAGE.into()).into()); } Ok(()) } @@ -206,7 +206,7 @@ impl SqliteConnection { Ok(x) => Ok(x), Err(e) => { error!("Failed to query ({bhh},{key}): {e:?}"); - Err(InterpreterError::DBError(SQL_FAIL_MESSAGE.into()).into()) + Err(VmInternalError::DBError(SQL_FAIL_MESSAGE.into()).into()) } } } @@ -219,14 +219,14 @@ impl SqliteConnection { impl SqliteConnection { pub fn initialize_conn(conn: &Connection) -> Result<()> { conn.query_row("PRAGMA journal_mode = WAL;", NO_PARAMS, |_row| Ok(())) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; conn.execute( "CREATE TABLE IF NOT EXISTS data_table (key TEXT PRIMARY KEY, value TEXT)", NO_PARAMS, ) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; conn.execute( "CREATE TABLE IF NOT EXISTS metadata_table @@ -234,13 +234,13 @@ impl SqliteConnection { UNIQUE (key, blockhash))", NO_PARAMS, ) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; conn.execute( "CREATE INDEX IF NOT EXISTS md_blockhashes ON metadata_table(blockhash)", NO_PARAMS, ) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; Self::check_schema(conn)?; @@ -257,22 +257,22 @@ impl SqliteConnection { let sql = "SELECT sql FROM sqlite_master WHERE name=?"; let _: String = conn .query_row(sql, params!["data_table"], |row| row.get(0)) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; let _: String = conn .query_row(sql, params!["metadata_table"], |row| row.get(0)) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; let _: String = conn .query_row(sql, params!["md_blockhashes"], |row| row.get(0)) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; Ok(()) } fn inner_open(filename: &str) -> Result { let conn = Connection::open(filename) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; conn.busy_handler(Some(tx_busy_handler)) - .map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?; + .map_err(|x| VmInternalError::SqliteError(IncomparableError { err: x }))?; Ok(conn) } @@ -311,7 +311,7 @@ impl MemoryBackingStore { impl ClarityBackingStore for MemoryBackingStore { fn set_block_hash(&mut self, bhh: StacksBlockId) -> Result { - Err(RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)).into()) + Err(RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)).into()) } fn get_data(&mut self, key: &str) -> Result> { diff --git a/clarity/src/vm/database/structures.rs b/clarity/src/vm/database/structures.rs index c4fec9f382e..9741f3fb4ff 100644 --- a/clarity/src/vm/database/structures.rs +++ b/clarity/src/vm/database/structures.rs @@ -22,7 +22,7 @@ use stacks_common::util::hash::{hex_bytes, to_hex}; use crate::vm::analysis::ContractAnalysis; use crate::vm::contracts::Contract; use crate::vm::database::ClarityDatabase; -use crate::vm::errors::{Error, InterpreterError, RuntimeErrorType}; +use crate::vm::errors::{RuntimeError, VmExecutionError, VmInternalError}; use crate::vm::types::{PrincipalData, TypeSignature}; pub trait ClaritySerializable { @@ -30,7 +30,7 @@ pub trait ClaritySerializable { } pub trait ClarityDeserializable { - fn deserialize(json: &str) -> Result; + fn deserialize(json: &str) -> Result; } impl ClaritySerializable for String { @@ -40,7 +40,7 @@ impl ClaritySerializable for String { } impl ClarityDeserializable for String { - fn deserialize(serialized: &str) -> Result { + fn deserialize(serialized: &str) -> Result { Ok(serialized.into()) } } @@ -54,7 +54,7 @@ macro_rules! clarity_serializable { } impl ClarityDeserializable<$Name> for $Name { #[cfg(not(target_family = "wasm"))] - fn deserialize(json: &str) -> Result { + fn deserialize(json: &str) -> Result { let mut deserializer = serde_json::Deserializer::from_str(&json); // serde's default 128 depth limit can be exhausted // by a 64-stack-depth AST, so disable the recursion limit @@ -63,13 +63,13 @@ macro_rules! clarity_serializable { // this will instead spill to the heap let deserializer = serde_stacker::Deserializer::new(&mut deserializer); Deserialize::deserialize(deserializer).map_err(|_| { - InterpreterError::Expect("Failed to deserialize vm.Value".into()).into() + VmInternalError::Expect("Failed to deserialize vm.Value".into()).into() }) } #[cfg(target_family = "wasm")] - fn deserialize(json: &str) -> Result { + fn deserialize(json: &str) -> Result { serde_json::from_str(json).map_err(|_| { - InterpreterError::Expect("Failed to deserialize vm.Value".into()).into() + VmInternalError::Expect("Failed to deserialize vm.Value".into()).into() }) } } @@ -257,23 +257,23 @@ impl ClaritySerializable for STXBalance { } impl ClarityDeserializable for STXBalance { - fn deserialize(input: &str) -> Result { + fn deserialize(input: &str) -> Result { let bytes = hex_bytes(input).map_err(|_| { - InterpreterError::Expect("STXBalance deserialization: failed decoding bytes.".into()) + VmInternalError::Expect("STXBalance deserialization: failed decoding bytes.".into()) })?; let result = if bytes.len() == STXBalance::unlocked_and_v1_size { let amount_unlocked = u128::from_be_bytes(bytes[0..16].try_into().map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "STXBalance deserialization: failed reading amount_unlocked.".into(), ) })?); let amount_locked = u128::from_be_bytes(bytes[16..32].try_into().map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "STXBalance deserialization: failed reading amount_locked.".into(), ) })?); let unlock_height = u64::from_be_bytes(bytes[32..40].try_into().map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "STXBalance deserialization: failed reading unlock_height.".into(), ) })?); @@ -295,23 +295,23 @@ impl ClarityDeserializable for STXBalance { && version != &STXBalance::pox_3_version && version != &STXBalance::pox_4_version { - return Err(InterpreterError::Expect(format!( + return Err(VmInternalError::Expect(format!( "Bad version byte in STX Balance serialization = {version}" )) .into()); } let amount_unlocked = u128::from_be_bytes(bytes[1..17].try_into().map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "STXBalance deserialization: failed reading amount_unlocked.".into(), ) })?); let amount_locked = u128::from_be_bytes(bytes[17..33].try_into().map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "STXBalance deserialization: failed reading amount_locked.".into(), ) })?); let unlock_height = u64::from_be_bytes(bytes[33..41].try_into().map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "STXBalance deserialization: failed reading unlock_height.".into(), ) })?); @@ -339,13 +339,13 @@ impl ClarityDeserializable for STXBalance { unlock_height, } } else { - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "Version is checked for pox_3 or pox_2 version compliance above".into(), ) .into()); } } else { - return Err(InterpreterError::Expect(format!( + return Err(VmInternalError::Expect(format!( "Bad STX Balance serialization size = {}", bytes.len() )) @@ -374,14 +374,18 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { &self.balance } - pub fn save(self) -> Result<(), Error> { + pub fn save(self) -> Result<(), VmExecutionError> { let key = ClarityDatabase::make_key_for_account_balance(&self.principal); self.db_ref.put_data(&key, &self.balance) } - pub fn transfer_to(mut self, recipient: &PrincipalData, amount: u128) -> Result<(), Error> { + pub fn transfer_to( + mut self, + recipient: &PrincipalData, + amount: u128, + ) -> Result<(), VmExecutionError> { if !self.can_transfer(amount)? { - return Err(InterpreterError::InsufficientBalance.into()); + return Err(VmInternalError::InsufficientBalance.into()); } let recipient_key = ClarityDatabase::make_key_for_account_balance(recipient); @@ -392,7 +396,10 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { recipient_balance .checked_add_unlocked_amount(amount) - .ok_or(Error::Runtime(RuntimeErrorType::ArithmeticOverflow, None))?; + .ok_or(VmExecutionError::Runtime( + RuntimeError::ArithmeticOverflow, + None, + ))?; self.debit(amount)?; self.db_ref.put_data(&recipient_key, &recipient_balance)?; @@ -400,7 +407,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { Ok(()) } - pub fn get_available_balance(&mut self) -> Result { + pub fn get_available_balance(&mut self) -> Result { let v1_unlock_height = self.db_ref.get_v1_unlock_height(); let v2_unlock_height = self.db_ref.get_v2_unlock_height()?; let v3_unlock_height = self.db_ref.get_v3_unlock_height()?; @@ -412,7 +419,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { ) } - pub fn canonical_balance_repr(&mut self) -> Result { + pub fn canonical_balance_repr(&mut self) -> Result { let v1_unlock_height = self.db_ref.get_v1_unlock_height(); let v2_unlock_height = self.db_ref.get_v2_unlock_height()?; let v3_unlock_height = self.db_ref.get_v3_unlock_height()?; @@ -427,7 +434,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { .0) } - pub fn has_locked_tokens(&mut self) -> Result { + pub fn has_locked_tokens(&mut self) -> Result { let v1_unlock_height = self.db_ref.get_v1_unlock_height(); let v2_unlock_height = self.db_ref.get_v2_unlock_height()?; let v3_unlock_height = self.db_ref.get_v3_unlock_height()?; @@ -439,7 +446,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { )) } - pub fn has_unlockable_tokens(&mut self) -> Result { + pub fn has_unlockable_tokens(&mut self) -> Result { let v1_unlock_height = self.db_ref.get_v1_unlock_height(); let v2_unlock_height = self.db_ref.get_v2_unlock_height()?; let v3_unlock_height = self.db_ref.get_v3_unlock_height()?; @@ -451,11 +458,11 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { )) } - pub fn can_transfer(&mut self, amount: u128) -> Result { + pub fn can_transfer(&mut self, amount: u128) -> Result { Ok(self.get_available_balance()? >= amount) } - pub fn debit(&mut self, amount: u128) -> Result<(), Error> { + pub fn debit(&mut self, amount: u128) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after account-debit"); @@ -464,7 +471,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { self.balance.debit_unlocked_amount(amount) } - pub fn credit(&mut self, amount: u128) -> Result<(), Error> { + pub fn credit(&mut self, amount: u128) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after account-credit"); @@ -472,7 +479,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { self.balance .checked_add_unlocked_amount(amount) - .ok_or_else(|| InterpreterError::Expect("STX balance overflow".into()))?; + .ok_or_else(|| VmInternalError::Expect("STX balance overflow".into()))?; Ok(()) } @@ -484,7 +491,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { &mut self, amount_to_lock: u128, unlock_burn_height: u64, - ) -> Result<(), Error> { + ) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after account-token-lock"); @@ -495,7 +502,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if unlock_burn_height <= self.burn_block_height { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: cannot set a lock with expired unlock burn height".into(), ) .into()); @@ -503,10 +510,9 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if self.has_locked_tokens()? { // caller needs to have checked this - return Err(InterpreterError::Expect( - "FATAL: account already has locked tokens".into(), - ) - .into()); + return Err( + VmInternalError::Expect("FATAL: account already has locked tokens".into()).into(), + ); } // from `unlock_available_tokens_if_any` call above, `self.balance` should @@ -516,7 +522,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { .balance .get_total_balance()? .checked_sub(amount_to_lock) - .ok_or_else(|| InterpreterError::Expect("STX underflow".into()))?; + .ok_or_else(|| VmInternalError::Expect("STX underflow".into()))?; self.balance = STXBalance::LockedPoxOne { amount_unlocked: new_amount_unlocked, @@ -530,7 +536,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Return true iff `self` represents a snapshot that has a lock /// created by PoX v2. - pub fn is_v2_locked(&mut self) -> Result { + pub fn is_v2_locked(&mut self) -> Result { match self.canonical_balance_repr()? { STXBalance::LockedPoxTwo { .. } => Ok(true), _ => Ok(false), @@ -539,7 +545,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Increase the account's current lock to `new_total_locked`. /// Panics if `self` was not locked by V2 PoX. - pub fn increase_lock_v2(&mut self, new_total_locked: u128) -> Result<(), Error> { + pub fn increase_lock_v2(&mut self, new_total_locked: u128) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after extend-token-lock"); @@ -547,7 +553,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if !self.has_locked_tokens()? { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: account does not have locked tokens".into(), ) .into()); @@ -556,12 +562,12 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if !self.is_v2_locked()? { // caller needs to have checked this return Err( - InterpreterError::Expect("FATAL: account must be locked by pox-2".into()).into(), + VmInternalError::Expect("FATAL: account must be locked by pox-2".into()).into(), ); } if self.balance.amount_locked() > new_total_locked { - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: account must lock more after `increase_lock_v2`".into(), ) .into()); @@ -571,9 +577,9 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { .balance .amount_unlocked() .checked_add(self.balance.amount_locked()) - .ok_or_else(|| InterpreterError::Expect("STX balance overflowed u128".into()))?; + .ok_or_else(|| VmInternalError::Expect("STX balance overflowed u128".into()))?; let amount_unlocked = total_amount.checked_sub(new_total_locked).ok_or_else(|| { - InterpreterError::Expect("STX underflow: more is locked than total balance".into()) + VmInternalError::Expect("STX underflow: more is locked than total balance".into()) })?; self.balance = STXBalance::LockedPoxTwo { @@ -588,7 +594,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Extend this account's current lock to `unlock_burn_height`. /// After calling, this method will set the balance to a "LockedPoxTwo" balance, /// because this method is only invoked as a result of PoX2 interactions - pub fn extend_lock_v2(&mut self, unlock_burn_height: u64) -> Result<(), Error> { + pub fn extend_lock_v2(&mut self, unlock_burn_height: u64) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after extend-token-lock"); @@ -596,7 +602,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if !self.has_locked_tokens()? { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: account does not have locked tokens".into(), ) .into()); @@ -604,7 +610,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if unlock_burn_height <= self.burn_block_height { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: cannot set a lock with expired unlock burn height".into(), ) .into()); @@ -625,7 +631,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { &mut self, amount_to_lock: u128, unlock_burn_height: u64, - ) -> Result<(), Error> { + ) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after account-token-lock"); @@ -633,12 +639,12 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { // caller needs to have checked this if amount_to_lock == 0 { - return Err(InterpreterError::Expect("BUG: cannot lock 0 tokens".into()).into()); + return Err(VmInternalError::Expect("BUG: cannot lock 0 tokens".into()).into()); } if unlock_burn_height <= self.burn_block_height { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: cannot set a lock with expired unlock burn height".into(), ) .into()); @@ -646,10 +652,9 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if self.has_locked_tokens()? { // caller needs to have checked this - return Err(InterpreterError::Expect( - "FATAL: account already has locked tokens".into(), - ) - .into()); + return Err( + VmInternalError::Expect("FATAL: account already has locked tokens".into()).into(), + ); } // from `unlock_available_tokens_if_any` call above, `self.balance` should @@ -659,7 +664,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { .balance .get_total_balance()? .checked_sub(amount_to_lock) - .ok_or_else(|| InterpreterError::Expect("STX underflow".into()))?; + .ok_or_else(|| VmInternalError::Expect("STX underflow".into()))?; self.balance = STXBalance::LockedPoxTwo { amount_unlocked: new_amount_unlocked, @@ -678,7 +683,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { &mut self, amount_to_lock: u128, unlock_burn_height: u64, - ) -> Result<(), Error> { + ) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after account-token-lock"); @@ -689,7 +694,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if unlock_burn_height <= self.burn_block_height { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: cannot set a lock with expired unlock burn height".into(), ) .into()); @@ -697,10 +702,9 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if self.has_locked_tokens()? { // caller needs to have checked this - return Err(InterpreterError::Expect( - "FATAL: account already has locked tokens".into(), - ) - .into()); + return Err( + VmInternalError::Expect("FATAL: account already has locked tokens".into()).into(), + ); } // from `unlock_available_tokens_if_any` call above, `self.balance` should @@ -711,7 +715,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { .get_total_balance()? .checked_sub(amount_to_lock) .ok_or_else(|| { - InterpreterError::Expect( + VmInternalError::Expect( "FATAL: account locks more STX than balance possessed".into(), ) })?; @@ -728,7 +732,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Extend this account's current lock to `unlock_burn_height`. /// After calling, this method will set the balance to a "LockedPoxThree" balance, /// because this method is only invoked as a result of PoX3 interactions - pub fn extend_lock_v3(&mut self, unlock_burn_height: u64) -> Result<(), Error> { + pub fn extend_lock_v3(&mut self, unlock_burn_height: u64) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after extend-token-lock"); @@ -736,7 +740,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if !self.has_locked_tokens()? { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: account does not have locked tokens".into(), ) .into()); @@ -744,7 +748,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if unlock_burn_height <= self.burn_block_height { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: cannot set a lock with expired unlock burn height".into(), ) .into()); @@ -760,7 +764,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Increase the account's current lock to `new_total_locked`. /// Panics if `self` was not locked by V3 PoX. - pub fn increase_lock_v3(&mut self, new_total_locked: u128) -> Result<(), Error> { + pub fn increase_lock_v3(&mut self, new_total_locked: u128) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after extend-token-lock"); @@ -768,7 +772,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if !self.has_locked_tokens()? { // caller needs to have checked this - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "FATAL: account does not have locked tokens".into(), ) .into()); @@ -777,7 +781,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { if !self.is_v3_locked()? { // caller needs to have checked this return Err( - InterpreterError::Expect("FATAL: account must be locked by pox-3".into()).into(), + VmInternalError::Expect("FATAL: account must be locked by pox-3".into()).into(), ); } @@ -790,9 +794,9 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { .balance .amount_unlocked() .checked_add(self.balance.amount_locked()) - .ok_or_else(|| InterpreterError::Expect("STX balance overflowed u128".into()))?; + .ok_or_else(|| VmInternalError::Expect("STX balance overflowed u128".into()))?; let amount_unlocked = total_amount.checked_sub(new_total_locked).ok_or_else(|| { - InterpreterError::Expect("STX underflow: more is locked than total balance".into()) + VmInternalError::Expect("STX underflow: more is locked than total balance".into()) })?; self.balance = STXBalance::LockedPoxThree { @@ -805,7 +809,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Return true iff `self` represents a snapshot that has a lock /// created by PoX v3. - pub fn is_v3_locked(&mut self) -> Result { + pub fn is_v3_locked(&mut self) -> Result { match self.canonical_balance_repr()? { STXBalance::LockedPoxThree { .. } => Ok(true), _ => Ok(false), @@ -821,7 +825,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { &mut self, amount_to_lock: u128, unlock_burn_height: u64, - ) -> Result<(), Error> { + ) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after account-token-lock"); @@ -860,7 +864,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Extend this account's current lock to `unlock_burn_height`. /// After calling, this method will set the balance to a "LockedPoxFour" balance, /// because this method is only invoked as a result of PoX3 interactions - pub fn extend_lock_v4(&mut self, unlock_burn_height: u64) -> Result<(), Error> { + pub fn extend_lock_v4(&mut self, unlock_burn_height: u64) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after extend-token-lock"); @@ -886,7 +890,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Increase the account's current lock to `new_total_locked`. /// Panics if `self` was not locked by V3 PoX. - pub fn increase_lock_v4(&mut self, new_total_locked: u128) -> Result<(), Error> { + pub fn increase_lock_v4(&mut self, new_total_locked: u128) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after extend-token-lock"); @@ -926,7 +930,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Return true iff `self` represents a snapshot that has a lock /// created by PoX v3. - pub fn is_v4_locked(&mut self) -> Result { + pub fn is_v4_locked(&mut self) -> Result { match self.canonical_balance_repr()? { STXBalance::LockedPoxFour { .. } => Ok(true), _ => Ok(false), @@ -937,7 +941,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// If this snapshot is locked, then alter the lock height to be /// the next burn block (i.e., `self.burn_block_height + 1`) - pub fn accelerate_unlock(&mut self) -> Result<(), Error> { + pub fn accelerate_unlock(&mut self) -> Result<(), VmExecutionError> { let unlocked = self.unlock_available_tokens_if_any()?; if unlocked > 0 { debug!("Consolidated after account-token-lock"); @@ -947,10 +951,10 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { self.balance = match self.balance { STXBalance::Unlocked { amount } => STXBalance::Unlocked { amount }, STXBalance::LockedPoxOne { .. } => { - return Err(InterpreterError::Expect( + return Err(VmInternalError::Expect( "Attempted to accelerate the unlock of a lockup created by PoX-1".into(), ) - .into()) + .into()); } STXBalance::LockedPoxTwo { amount_unlocked, @@ -985,7 +989,7 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> { /// Unlock any tokens that are unlockable at the current /// burn block height, and return the amount newly unlocked - fn unlock_available_tokens_if_any(&mut self) -> Result { + fn unlock_available_tokens_if_any(&mut self) -> Result { let (new_balance, unlocked) = self.balance.canonical_repr_at_block( self.burn_block_height, self.db_ref.get_v1_unlock_height(), @@ -1102,7 +1106,7 @@ impl STXBalance { } } - fn debit_unlocked_amount(&mut self, delta: u128) -> Result<(), Error> { + fn debit_unlocked_amount(&mut self, delta: u128) -> Result<(), VmExecutionError> { match self { STXBalance::Unlocked { amount: amount_unlocked, @@ -1121,7 +1125,7 @@ impl STXBalance { } => { *amount_unlocked = amount_unlocked .checked_sub(delta) - .ok_or_else(|| InterpreterError::Expect("STX underflow".into()))?; + .ok_or_else(|| VmInternalError::Expect("STX underflow".into()))?; Ok(()) } } @@ -1164,7 +1168,7 @@ impl STXBalance { v1_unlock_height: u32, v2_unlock_height: u32, v3_unlock_height: u32, - ) -> Result<(STXBalance, u128), Error> { + ) -> Result<(STXBalance, u128), VmExecutionError> { if self.has_unlockable_tokens_at_burn_block( burn_block_height, v1_unlock_height, @@ -1188,7 +1192,7 @@ impl STXBalance { v1_unlock_height: u32, v2_unlock_height: u32, v3_unlock_height: u32, - ) -> Result { + ) -> Result { if self.has_unlockable_tokens_at_burn_block( burn_block_height, v1_unlock_height, @@ -1257,7 +1261,7 @@ impl STXBalance { } } - pub fn get_total_balance(&self) -> Result { + pub fn get_total_balance(&self) -> Result { let (unlocked, locked) = match self { STXBalance::Unlocked { amount } => (*amount, 0), STXBalance::LockedPoxOne { @@ -1283,7 +1287,7 @@ impl STXBalance { }; unlocked .checked_add(locked) - .ok_or_else(|| InterpreterError::Expect("STX overflow".into()).into()) + .ok_or_else(|| VmInternalError::Expect("STX overflow".into()).into()) } pub fn was_locked_by_v1(&self) -> bool { @@ -1462,7 +1466,7 @@ impl STXBalance { v1_unlock_height: u32, v2_unlock_height: u32, v3_unlock_height: u32, - ) -> Result { + ) -> Result { Ok(self.get_available_balance_at_burn_block( burn_block_height, v1_unlock_height, diff --git a/clarity/src/vm/docs/contracts.rs b/clarity/src/vm/docs/contracts.rs index 4860ab3934e..a8f71d214bb 100644 --- a/clarity/src/vm/docs/contracts.rs +++ b/clarity/src/vm/docs/contracts.rs @@ -67,7 +67,7 @@ fn get_constant_value(var_name: &str, contract_content: &str) -> Value { .expect("BUG: failed to return constant value") } -fn doc_execute(program: &str) -> Result, vm::Error> { +fn doc_execute(program: &str) -> Result, vm::VmExecutionError> { let contract_id = QualifiedContractIdentifier::transient(); let mut contract_context = ContractContext::new(contract_id.clone(), ClarityVersion::Clarity2); let mut marf = MemoryBackingStore::new(); diff --git a/clarity/src/vm/errors.rs b/clarity/src/vm/errors.rs index 764ac466e5c..bc3d9c1e469 100644 --- a/clarity/src/vm/errors.rs +++ b/clarity/src/vm/errors.rs @@ -15,12 +15,12 @@ // along with this program. If not, see . pub use clarity_types::errors::{ - Error, IncomparableError, InterpreterError, InterpreterResult, RuntimeErrorType, - ShortReturnType, + EarlyReturnError, IncomparableError, InterpreterResult, RuntimeError, VmExecutionError, + VmInternalError, }; pub use crate::vm::analysis::errors::{ - check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrors, + check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, SyntaxBindingError, SyntaxBindingErrorType, }; diff --git a/clarity/src/vm/functions/arithmetic.rs b/clarity/src/vm/functions/arithmetic.rs index 2d5c2aff3ae..5b40fc1e30d 100644 --- a/clarity/src/vm/functions/arithmetic.rs +++ b/clarity/src/vm/functions/arithmetic.rs @@ -21,7 +21,7 @@ use integer_sqrt::IntegerSquareRoot; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::errors::{ - check_argument_count, CheckErrors, InterpreterError, InterpreterResult, RuntimeErrorType, + check_argument_count, CheckErrorKind, InterpreterResult, RuntimeError, VmInternalError, }; use crate::vm::representations::SymbolicExpression; use crate::vm::types::{ @@ -76,7 +76,7 @@ macro_rules! type_force_binary_arithmetic { match ($x, $y) { (Value::Int(x), Value::Int(y)) => I128Ops::$function(x, y), (Value::UInt(x), Value::UInt(y)) => U128Ops::$function(x, y), - (x, _) => Err(CheckErrors::UnionTypeValueError( + (x, _) => Err(CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(x), ) @@ -91,7 +91,7 @@ macro_rules! type_force_binary_comparison_v1 { match ($x, $y) { (Value::Int(x), Value::Int(y)) => I128Ops::$function(x, y), (Value::UInt(x), Value::UInt(y)) => U128Ops::$function(x, y), - (x, _) => Err(CheckErrors::UnionTypeValueError( + (x, _) => Err(CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(x), ) @@ -119,7 +119,7 @@ macro_rules! type_force_binary_comparison_v2 { Value::Sequence(SequenceData::Buffer(BuffData { data: x })), Value::Sequence(SequenceData::Buffer(BuffData { data: y })), ) => BuffOps::$function(x, y), - (x, _) => Err(CheckErrors::UnionTypeValueError( + (x, _) => Err(CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -139,7 +139,7 @@ macro_rules! type_force_unary_arithmetic { match $x { Value::Int(x) => I128Ops::$function(x), Value::UInt(x) => U128Ops::$function(x), - x => Err(CheckErrors::UnionTypeValueError( + x => Err(CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(x), ) @@ -155,14 +155,14 @@ macro_rules! type_force_variadic_arithmetic { ($function: ident, $args: expr) => {{ let first = $args .get(0) - .ok_or(CheckErrors::IncorrectArgumentCount(1, $args.len()))?; + .ok_or(CheckErrorKind::IncorrectArgumentCount(1, $args.len()))?; match first { Value::Int(_) => { let typed_args: Result, _> = $args .drain(..) .map(|x| match x { Value::Int(value) => Ok(value), - _ => Err(CheckErrors::TypeValueError( + _ => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::IntType), Box::new(x.clone()), )), @@ -176,7 +176,7 @@ macro_rules! type_force_variadic_arithmetic { .drain(..) .map(|x| match x { Value::UInt(value) => Ok(value), - _ => Err(CheckErrors::TypeValueError( + _ => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(x.clone()), )), @@ -185,7 +185,7 @@ macro_rules! type_force_variadic_arithmetic { let checked_args = typed_args?; U128Ops::$function(&checked_args) } - _ => Err(CheckErrors::UnionTypeValueError( + _ => Err(CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(first.clone()), ) @@ -248,49 +248,49 @@ macro_rules! make_arithmetic_ops { let result = args .iter() .try_fold(0, |acc: $type, x: &$type| acc.checked_add(*x)) - .ok_or(RuntimeErrorType::ArithmeticOverflow)?; + .ok_or(RuntimeError::ArithmeticOverflow)?; Self::make_value(result) } fn sub(args: &[$type]) -> InterpreterResult { let (first, rest) = args .split_first() - .ok_or(CheckErrors::IncorrectArgumentCount(1, 0))?; + .ok_or(CheckErrorKind::IncorrectArgumentCount(1, 0))?; if rest.len() == 0 { // return negation return Self::make_value( first .checked_neg() - .ok_or(RuntimeErrorType::ArithmeticUnderflow)?, + .ok_or(RuntimeError::ArithmeticUnderflow)?, ); } let result = rest .iter() .try_fold(*first, |acc: $type, x: &$type| acc.checked_sub(*x)) - .ok_or(RuntimeErrorType::ArithmeticUnderflow)?; + .ok_or(RuntimeError::ArithmeticUnderflow)?; Self::make_value(result) } fn mul(args: &[$type]) -> InterpreterResult { let result = args .iter() .try_fold(1, |acc: $type, x: &$type| acc.checked_mul(*x)) - .ok_or(RuntimeErrorType::ArithmeticOverflow)?; + .ok_or(RuntimeError::ArithmeticOverflow)?; Self::make_value(result) } fn div(args: &[$type]) -> InterpreterResult { let (first, rest) = args .split_first() - .ok_or(CheckErrors::IncorrectArgumentCount(1, 0))?; + .ok_or(CheckErrorKind::IncorrectArgumentCount(1, 0))?; let result = rest .iter() .try_fold(*first, |acc: $type, x: &$type| acc.checked_div(*x)) - .ok_or(RuntimeErrorType::DivisionByZero)?; + .ok_or(RuntimeError::DivisionByZero)?; Self::make_value(result) } fn modulo(numerator: $type, denominator: $type) -> InterpreterResult { let result = numerator .checked_rem(denominator) - .ok_or(RuntimeErrorType::DivisionByZero)?; + .ok_or(RuntimeError::DivisionByZero)?; Self::make_value(result) } #[allow(unused_comparisons)] @@ -312,7 +312,7 @@ macro_rules! make_arithmetic_ops { } if power < 0 || power > (u32::MAX as $type) { - return Err(RuntimeErrorType::Arithmetic( + return Err(RuntimeError::Arithmetic( "Power argument to (pow ...) must be a u32 integer".to_string(), ) .into()); @@ -322,14 +322,14 @@ macro_rules! make_arithmetic_ops { let result = base .checked_pow(power_u32) - .ok_or(RuntimeErrorType::ArithmeticOverflow)?; + .ok_or(RuntimeError::ArithmeticOverflow)?; Self::make_value(result) } fn sqrti(n: $type) -> InterpreterResult { match n.integer_sqrt_checked() { Some(result) => Self::make_value(result), None => { - return Err(RuntimeErrorType::Arithmetic( + return Err(RuntimeError::Arithmetic( "sqrti must be passed a positive integer".to_string(), ) .into()) @@ -338,7 +338,7 @@ macro_rules! make_arithmetic_ops { } fn log2(n: $type) -> InterpreterResult { if n < 1 { - return Err(RuntimeErrorType::Arithmetic( + return Err(RuntimeError::Arithmetic( "log2 must be passed a positive integer".to_string(), ) .into()); @@ -586,7 +586,7 @@ pub fn native_mod(a: Value, b: Value) -> InterpreterResult { pub fn native_bitwise_left_shift(input: Value, pos: Value) -> InterpreterResult { if let Value::UInt(u128_val) = pos { let shamt = u32::try_from(u128_val & 0x7f).map_err(|_| { - InterpreterError::Expect("FATAL: lower 32 bits did not convert to u32".into()) + VmInternalError::Expect("FATAL: lower 32 bits did not convert to u32".into()) })?; match input { @@ -598,21 +598,21 @@ pub fn native_bitwise_left_shift(input: Value, pos: Value) -> InterpreterResult< let result = input.wrapping_shl(shamt); Ok(Value::UInt(result)) } - _ => Err(CheckErrors::UnionTypeError( + _ => Err(CheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(TypeSignature::type_of(&input)?), ) .into()), } } else { - Err(CheckErrors::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(pos)).into()) + Err(CheckErrorKind::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(pos)).into()) } } pub fn native_bitwise_right_shift(input: Value, pos: Value) -> InterpreterResult { if let Value::UInt(u128_val) = pos { let shamt = u32::try_from(u128_val & 0x7f).map_err(|_| { - InterpreterError::Expect("FATAL: lower 32 bits did not convert to u32".into()) + VmInternalError::Expect("FATAL: lower 32 bits did not convert to u32".into()) })?; match input { @@ -624,32 +624,37 @@ pub fn native_bitwise_right_shift(input: Value, pos: Value) -> InterpreterResult let result = input.wrapping_shr(shamt); Ok(Value::UInt(result)) } - _ => Err(CheckErrors::UnionTypeError( + _ => Err(CheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(TypeSignature::type_of(&input)?), ) .into()), } } else { - Err(CheckErrors::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(pos)).into()) + Err(CheckErrorKind::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(pos)).into()) } } pub fn native_to_uint(input: Value) -> InterpreterResult { if let Value::Int(int_val) = input { - let uint_val = - u128::try_from(int_val).map_err(|_| RuntimeErrorType::ArithmeticUnderflow)?; + let uint_val = u128::try_from(int_val).map_err(|_| RuntimeError::ArithmeticUnderflow)?; Ok(Value::UInt(uint_val)) } else { - Err(CheckErrors::TypeValueError(Box::new(TypeSignature::IntType), Box::new(input)).into()) + Err( + CheckErrorKind::TypeValueError(Box::new(TypeSignature::IntType), Box::new(input)) + .into(), + ) } } pub fn native_to_int(input: Value) -> InterpreterResult { if let Value::UInt(uint_val) = input { - let int_val = i128::try_from(uint_val).map_err(|_| RuntimeErrorType::ArithmeticOverflow)?; + let int_val = i128::try_from(uint_val).map_err(|_| RuntimeError::ArithmeticOverflow)?; Ok(Value::Int(int_val)) } else { - Err(CheckErrors::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(input)).into()) + Err( + CheckErrorKind::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(input)) + .into(), + ) } } diff --git a/clarity/src/vm/functions/assets.rs b/clarity/src/vm/functions/assets.rs index 62763fa3fc0..6f286ef1da4 100644 --- a/clarity/src/vm/functions/assets.rs +++ b/clarity/src/vm/functions/assets.rs @@ -20,8 +20,8 @@ use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{runtime_cost, CostTracker}; use crate::vm::database::STXBalance; use crate::vm::errors::{ - check_argument_count, CheckErrors, Error, InterpreterError, InterpreterResult as Result, - RuntimeErrorType, + check_argument_count, CheckErrorKind, InterpreterResult as Result, RuntimeError, + VmExecutionError, VmInternalError, }; use crate::vm::representations::SymbolicExpression; use crate::vm::types::{ @@ -109,7 +109,7 @@ pub fn special_stx_balance( Ok(Value::UInt(balance)) } else { Err( - CheckErrors::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(owner)) + CheckErrorKind::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(owner)) .into(), ) } @@ -181,7 +181,7 @@ pub fn special_stx_transfer( { stx_transfer_consolidated(env, from, to, amount, memo) } else { - Err(CheckErrors::BadTransferSTXArguments.into()) + Err(CheckErrorKind::BadTransferSTXArguments.into()) } } @@ -207,7 +207,7 @@ pub fn special_stx_transfer_memo( { stx_transfer_consolidated(env, from, to, amount, memo) } else { - Err(CheckErrors::BadTransferSTXArguments.into()) + Err(CheckErrorKind::BadTransferSTXArguments.into()) } } @@ -225,7 +225,7 @@ pub fn special_stx_account( let principal = if let Value::Principal(p) = owner { p } else { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::PrincipalType), Box::new(owner), ) @@ -245,19 +245,19 @@ pub fn special_stx_account( ( "unlocked" .try_into() - .map_err(|_| InterpreterError::Expect("Bad special tuple name".into()))?, + .map_err(|_| VmInternalError::Expect("Bad special tuple name".into()))?, Value::UInt(stx_balance.amount_unlocked()), ), ( "locked" .try_into() - .map_err(|_| InterpreterError::Expect("Bad special tuple name".into()))?, + .map_err(|_| VmInternalError::Expect("Bad special tuple name".into()))?, Value::UInt(stx_balance.amount_locked()), ), ( "unlock-height" .try_into() - .map_err(|_| InterpreterError::Expect("Bad special tuple name".into()))?, + .map_err(|_| VmInternalError::Expect("Bad special tuple name".into()))?, Value::UInt(u128::from(stx_balance.effective_unlock_height( v1_unlock_ht, v2_unlock_ht, @@ -309,7 +309,7 @@ pub fn special_stx_burn( Ok(Value::okay_true()) } else { - Err(CheckErrors::BadTransferSTXArguments.into()) + Err(CheckErrorKind::BadTransferSTXArguments.into()) } } @@ -322,7 +322,7 @@ pub fn special_mint_token( runtime_cost(ClarityCostFunction::FtMint, env, 0)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let amount = eval(&args[1], env, context)?; let to = eval(&args[2], env, context)?; @@ -336,7 +336,7 @@ pub fn special_mint_token( .contract_context .meta_ft .get(token_name) - .ok_or(CheckErrors::NoSuchFT(token_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchFT(token_name.to_string()))?; env.global_context.database.checked_increase_token_supply( &env.contract_context.contract_identifier, @@ -354,7 +354,7 @@ pub fn special_mint_token( let final_to_bal = to_bal .checked_add(amount) - .ok_or_else(|| InterpreterError::Expect("STX overflow".into()))?; + .ok_or_else(|| VmInternalError::Expect("STX overflow".into()))?; env.add_memory(TypeSignature::PrincipalType.size()? as u64)?; env.add_memory(TypeSignature::UIntType.size()? as u64)?; @@ -374,7 +374,7 @@ pub fn special_mint_token( Ok(Value::okay_true()) } else { - Err(CheckErrors::BadMintFTArguments.into()) + Err(CheckErrorKind::BadMintFTArguments.into()) } } @@ -385,7 +385,7 @@ pub fn special_mint_asset_v200( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; let to = eval(&args[2], env, context)?; @@ -394,7 +394,7 @@ pub fn special_mint_asset_v200( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; runtime_cost( @@ -404,7 +404,7 @@ pub fn special_mint_asset_v200( )?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -418,7 +418,7 @@ pub fn special_mint_asset_v200( &asset, expected_asset_type, ) { - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => Ok(()), + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => Ok(()), Ok(_owner) => return clarity_ecode!(MintAssetErrorCodes::ALREADY_EXIST), Err(e) => Err(e), }?; @@ -445,7 +445,7 @@ pub fn special_mint_asset_v200( Ok(Value::okay_true()) } else { Err( - CheckErrors::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(to)) + CheckErrorKind::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(to)) .into(), ) } @@ -460,7 +460,7 @@ pub fn special_mint_asset_v205( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; let to = eval(&args[2], env, context)?; @@ -469,16 +469,16 @@ pub fn special_mint_asset_v205( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; let asset_size = asset .serialized_size() - .map_err(|e| InterpreterError::Expect(e.to_string()))? as u64; + .map_err(|e| VmInternalError::Expect(e.to_string()))? as u64; runtime_cost(ClarityCostFunction::NftMint, env, asset_size)?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -492,7 +492,7 @@ pub fn special_mint_asset_v205( &asset, expected_asset_type, ) { - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => Ok(()), + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => Ok(()), Ok(_owner) => return clarity_ecode!(MintAssetErrorCodes::ALREADY_EXIST), Err(e) => Err(e), }?; @@ -519,7 +519,7 @@ pub fn special_mint_asset_v205( Ok(Value::okay_true()) } else { Err( - CheckErrors::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(to)) + CheckErrorKind::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(to)) .into(), ) } @@ -532,7 +532,7 @@ pub fn special_transfer_asset_v200( ) -> Result { check_argument_count(4, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; let from = eval(&args[2], env, context)?; @@ -542,7 +542,7 @@ pub fn special_transfer_asset_v200( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; runtime_cost( @@ -552,7 +552,7 @@ pub fn special_transfer_asset_v200( )?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -571,7 +571,7 @@ pub fn special_transfer_asset_v200( expected_asset_type, ) { Ok(owner) => Ok(owner), - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => { + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => { return clarity_ecode!(TransferAssetErrorCodes::DOES_NOT_EXIST) } Err(e) => Err(e), @@ -614,7 +614,7 @@ pub fn special_transfer_asset_v200( Ok(Value::okay_true()) } else { - Err(CheckErrors::BadTransferNFTArguments.into()) + Err(CheckErrorKind::BadTransferNFTArguments.into()) } } @@ -627,7 +627,7 @@ pub fn special_transfer_asset_v205( ) -> Result { check_argument_count(4, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; let from = eval(&args[2], env, context)?; @@ -637,16 +637,16 @@ pub fn special_transfer_asset_v205( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; let asset_size = asset .serialized_size() - .map_err(|e| InterpreterError::Expect(e.to_string()))? as u64; + .map_err(|e| VmInternalError::Expect(e.to_string()))? as u64; runtime_cost(ClarityCostFunction::NftTransfer, env, asset_size)?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -665,7 +665,7 @@ pub fn special_transfer_asset_v205( expected_asset_type, ) { Ok(owner) => Ok(owner), - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => { + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => { return clarity_ecode!(TransferAssetErrorCodes::DOES_NOT_EXIST) } Err(e) => Err(e), @@ -708,7 +708,7 @@ pub fn special_transfer_asset_v205( Ok(Value::okay_true()) } else { - Err(CheckErrors::BadTransferNFTArguments.into()) + Err(CheckErrorKind::BadTransferNFTArguments.into()) } } @@ -721,7 +721,7 @@ pub fn special_transfer_token( runtime_cost(ClarityCostFunction::FtTransfer, env, 0)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let amount = eval(&args[1], env, context)?; let from = eval(&args[2], env, context)?; @@ -745,7 +745,7 @@ pub fn special_transfer_token( .contract_context .meta_ft .get(token_name) - .ok_or(CheckErrors::NoSuchFT(token_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchFT(token_name.to_string()))?; let from_bal = env.global_context.database.get_ft_balance( &env.contract_context.contract_identifier, @@ -769,7 +769,7 @@ pub fn special_transfer_token( let final_to_bal = to_bal .checked_add(amount) - .ok_or(RuntimeErrorType::ArithmeticOverflow)?; + .ok_or(RuntimeError::ArithmeticOverflow)?; env.add_memory(TypeSignature::PrincipalType.size()? as u64)?; env.add_memory(TypeSignature::PrincipalType.size()? as u64)?; @@ -809,7 +809,7 @@ pub fn special_transfer_token( Ok(Value::okay_true()) } else { - Err(CheckErrors::BadTransferFTArguments.into()) + Err(CheckErrorKind::BadTransferFTArguments.into()) } } @@ -822,7 +822,7 @@ pub fn special_get_balance( runtime_cost(ClarityCostFunction::FtBalance, env, 0)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let owner = eval(&args[1], env, context)?; @@ -831,7 +831,7 @@ pub fn special_get_balance( .contract_context .meta_ft .get(token_name) - .ok_or(CheckErrors::NoSuchFT(token_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchFT(token_name.to_string()))?; let balance = env.global_context.database.get_ft_balance( &env.contract_context.contract_identifier, @@ -842,7 +842,7 @@ pub fn special_get_balance( Ok(Value::UInt(balance)) } else { Err( - CheckErrors::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(owner)) + CheckErrorKind::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(owner)) .into(), ) } @@ -855,7 +855,7 @@ pub fn special_get_owner_v200( ) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; @@ -863,7 +863,7 @@ pub fn special_get_owner_v200( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; runtime_cost( @@ -873,7 +873,7 @@ pub fn special_get_owner_v200( )?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -887,9 +887,9 @@ pub fn special_get_owner_v200( expected_asset_type, ) { Ok(owner) => Ok(Value::some(Value::Principal(owner)).map_err(|_| { - InterpreterError::Expect("Principal should always fit in optional.".into()) + VmInternalError::Expect("Principal should always fit in optional.".into()) })?), - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => Ok(Value::none()), + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => Ok(Value::none()), Err(e) => Err(e), } } @@ -903,7 +903,7 @@ pub fn special_get_owner_v205( ) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; @@ -911,16 +911,16 @@ pub fn special_get_owner_v205( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; let asset_size = asset .serialized_size() - .map_err(|e| InterpreterError::Expect(e.to_string()))? as u64; + .map_err(|e| VmInternalError::Expect(e.to_string()))? as u64; runtime_cost(ClarityCostFunction::NftOwner, env, asset_size)?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -934,9 +934,9 @@ pub fn special_get_owner_v205( expected_asset_type, ) { Ok(owner) => Ok(Value::some(Value::Principal(owner)).map_err(|_| { - InterpreterError::Expect("Principal should always fit in optional.".into()) + VmInternalError::Expect("Principal should always fit in optional.".into()) })?), - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => Ok(Value::none()), + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => Ok(Value::none()), Err(e) => Err(e), } } @@ -950,7 +950,7 @@ pub fn special_get_token_supply( runtime_cost(ClarityCostFunction::FtSupply, env, 0)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let supply = env .global_context @@ -968,7 +968,7 @@ pub fn special_burn_token( runtime_cost(ClarityCostFunction::FtBurn, env, 0)?; - let token_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let amount = eval(&args[1], env, context)?; let from = eval(&args[2], env, context)?; @@ -1022,7 +1022,7 @@ pub fn special_burn_token( Ok(Value::okay_true()) } else { - Err(CheckErrors::BadBurnFTArguments.into()) + Err(CheckErrorKind::BadBurnFTArguments.into()) } } @@ -1035,7 +1035,7 @@ pub fn special_burn_asset_v200( runtime_cost(ClarityCostFunction::NftBurn, env, 0)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; let sender = eval(&args[2], env, context)?; @@ -1044,7 +1044,7 @@ pub fn special_burn_asset_v200( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; runtime_cost( @@ -1054,7 +1054,7 @@ pub fn special_burn_asset_v200( )?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -1068,7 +1068,7 @@ pub fn special_burn_asset_v200( &asset, expected_asset_type, ) { - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => { + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => { return clarity_ecode!(BurnAssetErrorCodes::DOES_NOT_EXIST) } Ok(owner) => Ok(owner), @@ -1106,10 +1106,11 @@ pub fn special_burn_asset_v200( Ok(Value::okay_true()) } else { - Err( - CheckErrors::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(sender)) - .into(), + Err(CheckErrorKind::TypeValueError( + Box::new(TypeSignature::PrincipalType), + Box::new(sender), ) + .into()) } } @@ -1124,7 +1125,7 @@ pub fn special_burn_asset_v205( runtime_cost(ClarityCostFunction::NftBurn, env, 0)?; - let asset_name = args[0].match_atom().ok_or(CheckErrors::BadTokenName)?; + let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; let asset = eval(&args[1], env, context)?; let sender = eval(&args[2], env, context)?; @@ -1133,16 +1134,16 @@ pub fn special_burn_asset_v205( .contract_context .meta_nft .get(asset_name) - .ok_or(CheckErrors::NoSuchNFT(asset_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; let expected_asset_type = &nft_metadata.key_type; let asset_size = asset .serialized_size() - .map_err(|e| InterpreterError::Expect(e.to_string()))? as u64; + .map_err(|e| VmInternalError::Expect(e.to_string()))? as u64; runtime_cost(ClarityCostFunction::NftBurn, env, asset_size)?; if !expected_asset_type.admits(env.epoch(), &asset)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_asset_type.clone()), Box::new(asset), ) @@ -1156,7 +1157,7 @@ pub fn special_burn_asset_v205( &asset, expected_asset_type, ) { - Err(Error::Runtime(RuntimeErrorType::NoSuchToken, _)) => { + Err(VmExecutionError::Runtime(RuntimeError::NoSuchToken, _)) => { return clarity_ecode!(BurnAssetErrorCodes::DOES_NOT_EXIST) } Ok(owner) => Ok(owner), @@ -1194,9 +1195,10 @@ pub fn special_burn_asset_v205( Ok(Value::okay_true()) } else { - Err( - CheckErrors::TypeValueError(Box::new(TypeSignature::PrincipalType), Box::new(sender)) - .into(), + Err(CheckErrorKind::TypeValueError( + Box::new(TypeSignature::PrincipalType), + Box::new(sender), ) + .into()) } } diff --git a/clarity/src/vm/functions/boolean.rs b/clarity/src/vm/functions/boolean.rs index e692b4ad71c..8edf279a9b7 100644 --- a/clarity/src/vm/functions/boolean.rs +++ b/clarity/src/vm/functions/boolean.rs @@ -17,7 +17,7 @@ use crate::vm::contexts::{Environment, LocalContext}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; -use crate::vm::errors::{check_arguments_at_least, CheckErrors, InterpreterResult as Result}; +use crate::vm::errors::{check_arguments_at_least, CheckErrorKind, InterpreterResult as Result}; use crate::vm::eval; use crate::vm::representations::SymbolicExpression; use crate::vm::types::{TypeSignature, Value}; @@ -25,7 +25,7 @@ use crate::vm::types::{TypeSignature, Value}; fn type_force_bool(value: &Value) -> Result { match *value { Value::Bool(boolean) => Ok(boolean), - _ => Err(CheckErrors::TypeValueError( + _ => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::BoolType), Box::new(value.clone()), ) diff --git a/clarity/src/vm/functions/conversions.rs b/clarity/src/vm/functions/conversions.rs index bd7834a5521..5f3e8033629 100644 --- a/clarity/src/vm/functions/conversions.rs +++ b/clarity/src/vm/functions/conversions.rs @@ -19,7 +19,7 @@ use clarity_types::types::serialization::SerializationError; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::errors::{ - check_argument_count, CheckErrors, InterpreterError, InterpreterResult as Result, + check_argument_count, CheckErrorKind, InterpreterResult as Result, VmInternalError, }; use crate::vm::representations::SymbolicExpression; use crate::vm::types::signatures::TO_ASCII_MAX_BUFF; @@ -55,12 +55,12 @@ pub fn buff_to_int_generic( Value::Sequence(SequenceData::Buffer(ref sequence_data)) => { if sequence_data.len()? > BufferLength::try_from(16_u32) - .map_err(|_| InterpreterError::Expect("Failed to construct".into()))? + .map_err(|_| VmInternalError::Expect("Failed to construct".into()))? { - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32) - .map_err(|_| InterpreterError::Expect("Failed to construct".into()))?, + .map_err(|_| VmInternalError::Expect("Failed to construct".into()))?, ))), Box::new(value), ) @@ -83,10 +83,10 @@ pub fn buff_to_int_generic( Ok(value) } } - _ => Err(CheckErrors::TypeValueError( + _ => Err(CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32) - .map_err(|_| InterpreterError::Expect("Failed to construct".into()))?, + .map_err(|_| VmInternalError::Expect("Failed to construct".into()))?, ))), Box::new(value), ) @@ -149,7 +149,7 @@ pub fn native_string_to_int_generic( Err(_error) => Ok(Value::none()), } } - _ => Err(CheckErrors::UnionTypeValueError( + _ => Err(CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::max_string_ascii()?, TypeSignature::max_string_utf8()?, @@ -196,16 +196,16 @@ pub fn native_int_to_string_generic( Value::Int(ref int_value) => { let as_string = int_value.to_string(); Ok(bytes_to_value_fn(as_string.into()).map_err(|_| { - InterpreterError::Expect("Unexpected error converting Int to string.".into()) + VmInternalError::Expect("Unexpected error converting Int to string.".into()) })?) } Value::UInt(ref uint_value) => { let as_string = uint_value.to_string(); Ok(bytes_to_value_fn(as_string.into()).map_err(|_| { - InterpreterError::Expect("Unexpected error converting UInt to string.".into()) + VmInternalError::Expect("Unexpected error converting UInt to string.".into()) })?) } - _ => Err(CheckErrors::UnionTypeValueError( + _ => Err(CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(value), ) @@ -227,7 +227,7 @@ pub fn native_int_to_utf8(value: Value) -> Result { /// This should only fail due to system errors, not conversion failures fn convert_string_to_ascii_ok(s: String) -> Result { let ascii_value = Value::string_ascii_from_bytes(s.into_bytes()).map_err(|_| { - InterpreterError::Expect("Unexpected error converting string to ASCII".into()) + VmInternalError::Expect("Unexpected error converting string to ASCII".into()) })?; Value::okay(ascii_value) } @@ -271,7 +271,7 @@ pub fn special_to_ascii( Err(_) => Ok(Value::err_uint(1)), // Invalid UTF8 } } - _ => Err(CheckErrors::UnionTypeValueError( + _ => Err(CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -293,7 +293,7 @@ pub fn to_consensus_buff(value: Value) -> Result { let mut clar_buff_serialized = vec![]; value .serialize_write(&mut clar_buff_serialized) - .map_err(|_| InterpreterError::Expect("FATAL: failed to serialize to vec".into()))?; + .map_err(|_| VmInternalError::Expect("FATAL: failed to serialize to vec".into()))?; let clar_buff_serialized = match Value::buff_from(clar_buff_serialized) { Ok(x) => x, @@ -324,7 +324,7 @@ pub fn from_consensus_buff( let input_bytes = if let Value::Sequence(SequenceData::Buffer(buff_data)) = value { Ok(buff_data.data) } else { - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::max_buffer()?), Box::new(value), )) @@ -346,7 +346,7 @@ pub fn from_consensus_buff( ) { Ok(value) => value, Err(SerializationError::UnexpectedSerialization) => { - return Err(CheckErrors::Expects("UnexpectedSerialization".into()).into()); + return Err(CheckErrorKind::Expects("UnexpectedSerialization".into()).into()); } Err(_) => return Ok(Value::none()), }; diff --git a/clarity/src/vm/functions/crypto.rs b/clarity/src/vm/functions/crypto.rs index 3b5223bd721..d52ff19dded 100644 --- a/clarity/src/vm/functions/crypto.rs +++ b/clarity/src/vm/functions/crypto.rs @@ -24,7 +24,7 @@ use stacks_common::util::secp256k1::{secp256k1_recover, secp256k1_verify, Secp25 use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::errors::{ - check_argument_count, CheckErrors, InterpreterError, InterpreterResult as Result, + check_argument_count, CheckErrorKind, InterpreterResult as Result, VmInternalError, }; use crate::vm::representations::SymbolicExpression; use crate::vm::types::{BuffData, SequenceData, TypeSignature, Value, BUFF_32, BUFF_33, BUFF_65}; @@ -37,7 +37,7 @@ macro_rules! native_hash_func { Value::Int(value) => Ok(value.to_le_bytes().to_vec()), Value::UInt(value) => Ok(value.to_le_bytes().to_vec()), Value::Sequence(SequenceData::Buffer(value)) => Ok(value.data), - _ => Err(CheckErrors::UnionTypeValueError( + _ => Err(CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -67,7 +67,7 @@ fn pubkey_to_address_v1(pub_key: Secp256k1PublicKey) -> Result { 1, &vec![pub_key], ) - .ok_or_else(|| InterpreterError::Expect("Failed to create address from pubkey".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to create address from pubkey".into()).into()) } // Note: Clarity1 had a bug in how the address is computed (issues/2619). @@ -84,7 +84,7 @@ fn pubkey_to_address_v2(pub_key: Secp256k1PublicKey, is_mainnet: bool) -> Result 1, &vec![pub_key], ) - .ok_or_else(|| InterpreterError::Expect("Failed to create address from pubkey".into()).into()) + .ok_or_else(|| VmInternalError::Expect("Failed to create address from pubkey".into()).into()) } pub fn special_principal_of( @@ -102,7 +102,7 @@ pub fn special_principal_of( let pub_key = match param0 { Value::Sequence(SequenceData::Buffer(BuffData { ref data })) => { if data.len() != 33 { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(BUFF_33.clone()), Box::new(param0), ) @@ -112,7 +112,7 @@ pub fn special_principal_of( } _ => { return Err( - CheckErrors::TypeValueError(Box::new(BUFF_33.clone()), Box::new(param0)).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_33.clone()), Box::new(param0)).into(), ) } }; @@ -127,7 +127,7 @@ pub fn special_principal_of( }; let principal = addr.into(); Ok(Value::okay(Value::Principal(principal)) - .map_err(|_| InterpreterError::Expect("Failed to construct ok".into()))?) + .map_err(|_| VmInternalError::Expect("Failed to construct ok".into()))?) } else { Ok(Value::err_uint(1)) } @@ -148,7 +148,7 @@ pub fn special_secp256k1_recover( let message = match param0 { Value::Sequence(SequenceData::Buffer(BuffData { ref data })) => { if data.len() != 32 { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(BUFF_32.clone()), Box::new(param0), ) @@ -158,7 +158,7 @@ pub fn special_secp256k1_recover( } _ => { return Err( - CheckErrors::TypeValueError(Box::new(BUFF_32.clone()), Box::new(param0)).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_32.clone()), Box::new(param0)).into(), ) } }; @@ -167,7 +167,7 @@ pub fn special_secp256k1_recover( let signature = match param1 { Value::Sequence(SequenceData::Buffer(BuffData { ref data })) => { if data.len() > 65 { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(BUFF_65.clone()), Box::new(param1), ) @@ -180,17 +180,19 @@ pub fn special_secp256k1_recover( } _ => { return Err( - CheckErrors::TypeValueError(Box::new(BUFF_65.clone()), Box::new(param1)).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_65.clone()), Box::new(param1)).into(), ) } }; - match secp256k1_recover(message, signature).map_err(|_| CheckErrors::InvalidSecp65k1Signature) { + match secp256k1_recover(message, signature) + .map_err(|_| CheckErrorKind::InvalidSecp65k1Signature) + { Ok(pubkey) => Ok(Value::okay( Value::buff_from(pubkey.to_vec()) - .map_err(|_| InterpreterError::Expect("Failed to construct buff".into()))?, + .map_err(|_| VmInternalError::Expect("Failed to construct buff".into()))?, ) - .map_err(|_| InterpreterError::Expect("Failed to construct ok".into()))?), + .map_err(|_| VmInternalError::Expect("Failed to construct ok".into()))?), _ => Ok(Value::err_uint(1)), } } @@ -210,7 +212,7 @@ pub fn special_secp256k1_verify( let message = match param0 { Value::Sequence(SequenceData::Buffer(BuffData { ref data })) => { if data.len() != 32 { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(BUFF_32.clone()), Box::new(param0), ) @@ -220,7 +222,7 @@ pub fn special_secp256k1_verify( } _ => { return Err( - CheckErrors::TypeValueError(Box::new(BUFF_32.clone()), Box::new(param0)).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_32.clone()), Box::new(param0)).into(), ) } }; @@ -229,7 +231,7 @@ pub fn special_secp256k1_verify( let signature = match param1 { Value::Sequence(SequenceData::Buffer(BuffData { ref data })) => { if data.len() > 65 { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(BUFF_65.clone()), Box::new(param1), ) @@ -245,7 +247,7 @@ pub fn special_secp256k1_verify( } _ => { return Err( - CheckErrors::TypeValueError(Box::new(BUFF_65.clone()), Box::new(param1)).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_65.clone()), Box::new(param1)).into(), ) } }; @@ -254,7 +256,7 @@ pub fn special_secp256k1_verify( let pubkey = match param2 { Value::Sequence(SequenceData::Buffer(BuffData { ref data })) => { if data.len() != 33 { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(BUFF_33.clone()), Box::new(param2), ) @@ -264,7 +266,7 @@ pub fn special_secp256k1_verify( } _ => { return Err( - CheckErrors::TypeValueError(Box::new(BUFF_33.clone()), Box::new(param2)).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_33.clone()), Box::new(param2)).into(), ) } }; diff --git a/clarity/src/vm/functions/database.rs b/clarity/src/vm/functions/database.rs index 93fbef0258e..fc1857e4421 100644 --- a/clarity/src/vm/functions/database.rs +++ b/clarity/src/vm/functions/database.rs @@ -22,8 +22,8 @@ use crate::vm::callables::DefineType; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{constants as cost_constants, runtime_cost, CostTracker, MemoryConsumer}; use crate::vm::errors::{ - check_argument_count, check_arguments_at_least, CheckErrors, InterpreterError, - InterpreterResult as Result, RuntimeErrorType, + check_argument_count, check_arguments_at_least, CheckErrorKind, InterpreterResult as Result, + RuntimeError, VmInternalError, }; use crate::vm::representations::{SymbolicExpression, SymbolicExpressionType}; use crate::vm::types::{ @@ -69,7 +69,7 @@ pub fn special_contract_call( // is checked in callables::DefinedFunction::execute_apply. runtime_cost(ClarityCostFunction::ContractCall, env, 0)?; - let function_name = args[1].match_atom().ok_or(CheckErrors::ExpectedName)?; + let function_name = args[1].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let rest_args_slice = &args[2..]; let rest_args_len = rest_args_slice.len(); let mut rest_args = Vec::with_capacity(rest_args_len); @@ -93,7 +93,7 @@ pub fn special_contract_call( Some(trait_data) => { // Ensure that contract-call is used for inter-contract calls only if trait_data.contract_identifier == env.contract_context.contract_identifier { - return Err(CheckErrors::CircularReference(vec![trait_data + return Err(CheckErrorKind::CircularReference(vec![trait_data .contract_identifier .name .to_string()]) @@ -105,7 +105,9 @@ pub fn special_contract_call( .database .get_contract(&trait_data.contract_identifier) .map_err(|_e| { - CheckErrors::NoSuchContract(trait_data.contract_identifier.to_string()) + CheckErrorKind::NoSuchContract( + trait_data.contract_identifier.to_string(), + ) })?; let contract_context_to_check = contract_to_check.contract_context; @@ -114,7 +116,7 @@ pub fn special_contract_call( let trait_identifier = trait_data .trait_identifier .as_ref() - .ok_or(CheckErrors::ExpectedTraitIdentifier)?; + .ok_or(CheckErrorKind::ExpectedTraitIdentifier)?; // Attempt to short circuit the dynamic dispatch checks: // If the contract is explicitely implementing the trait with `impl-trait`, @@ -131,7 +133,7 @@ pub fn special_contract_call( .database .get_contract(&trait_identifier.contract_identifier) .map_err(|_e| { - CheckErrors::NoSuchContract( + CheckErrorKind::NoSuchContract( trait_identifier.contract_identifier.to_string(), ) })?; @@ -141,19 +143,19 @@ pub fn special_contract_call( // Retrieve the function that will be invoked let function_to_check = contract_context_to_check .lookup_function(function_name) - .ok_or(CheckErrors::BadTraitImplementation( + .ok_or(CheckErrorKind::BadTraitImplementation( trait_name.clone(), function_name.to_string(), ))?; // Check read/write compatibility if env.global_context.is_read_only() { - return Err(CheckErrors::TraitBasedContractCallInReadOnly.into()); + return Err(CheckErrorKind::TraitBasedContractCallInReadOnly.into()); } // Check visibility if function_to_check.define_type == DefineType::Private { - return Err(CheckErrors::NoSuchPublicFunction( + return Err(CheckErrorKind::NoSuchPublicFunction( trait_data.contract_identifier.to_string(), function_name.to_string(), ) @@ -169,9 +171,12 @@ pub fn special_contract_call( // Retrieve the expected method signature let constraining_trait = contract_context_defining_trait .lookup_trait_definition(&trait_name) - .ok_or(CheckErrors::TraitReferenceUnknown(trait_name.clone()))?; + .ok_or(CheckErrorKind::TraitReferenceUnknown(trait_name.clone()))?; let expected_sig = constraining_trait.get(function_name).ok_or( - CheckErrors::TraitMethodUnknown(trait_name, function_name.to_string()), + CheckErrorKind::TraitMethodUnknown( + trait_name, + function_name.to_string(), + ), )?; ( &trait_data.contract_identifier, @@ -179,10 +184,10 @@ pub fn special_contract_call( ) } } - _ => return Err(CheckErrors::ContractCallExpectName.into()), + _ => return Err(CheckErrorKind::ContractCallExpectName.into()), } } - _ => return Err(CheckErrors::ContractCallExpectName.into()), + _ => return Err(CheckErrorKind::ContractCallExpectName.into()), }; let contract_principal = env.contract_context.contract_identifier.clone().into(); @@ -203,14 +208,14 @@ pub fn special_contract_call( // sanitize contract-call outputs in epochs >= 2.4 let result_type = TypeSignature::type_of(&result)?; let (result, _) = Value::sanitize_value(env.epoch(), &result_type, result) - .ok_or_else(|| CheckErrors::CouldNotDetermineType)?; + .ok_or_else(|| CheckErrorKind::CouldNotDetermineType)?; // Ensure that the expected type from the trait spec admits // the type of the value returned by the dynamic dispatch. if let Some(returns_type_signature) = type_returns_constraint { let actual_returns = TypeSignature::type_of(&result)?; if !returns_type_signature.admits_type(env.epoch(), &actual_returns)? { - return Err(CheckErrors::ReturnTypesMustMatch( + return Err(CheckErrorKind::ReturnTypesMustMatch( Box::new(returns_type_signature), Box::new(actual_returns), ) @@ -228,7 +233,7 @@ pub fn special_fetch_variable_v200( ) -> Result { check_argument_count(1, args)?; - let var_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let var_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -236,7 +241,7 @@ pub fn special_fetch_variable_v200( .contract_context .meta_data_var .get(var_name) - .ok_or(CheckErrors::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; runtime_cost( ClarityCostFunction::FetchVar, @@ -259,7 +264,7 @@ pub fn special_fetch_variable_v205( ) -> Result { check_argument_count(1, args)?; - let var_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let var_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -267,7 +272,7 @@ pub fn special_fetch_variable_v205( .contract_context .meta_data_var .get(var_name) - .ok_or(CheckErrors::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; let epoch = *env.epoch(); let result = env @@ -291,14 +296,14 @@ pub fn special_set_variable_v200( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(2, args)?; let value = eval(&args[1], env, context)?; - let var_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let var_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -306,7 +311,7 @@ pub fn special_set_variable_v200( .contract_context .meta_data_var .get(var_name) - .ok_or(CheckErrors::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; runtime_cost( ClarityCostFunction::SetVar, @@ -331,14 +336,14 @@ pub fn special_set_variable_v205( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(2, args)?; let value = eval(&args[1], env, context)?; - let var_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let var_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -346,7 +351,7 @@ pub fn special_set_variable_v205( .contract_context .meta_data_var .get(var_name) - .ok_or(CheckErrors::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; let epoch = *env.epoch(); let result = env @@ -373,7 +378,7 @@ pub fn special_fetch_entry_v200( ) -> Result { check_argument_count(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let key = eval(&args[1], env, context)?; @@ -383,7 +388,7 @@ pub fn special_fetch_entry_v200( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::FetchEntry, @@ -406,7 +411,7 @@ pub fn special_fetch_entry_v205( ) -> Result { check_argument_count(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let key = eval(&args[1], env, context)?; @@ -416,7 +421,7 @@ pub fn special_fetch_entry_v205( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; let epoch = *env.epoch(); let result = env @@ -446,13 +451,15 @@ pub fn special_at_block( let bhh = match eval(&args[0], env, context)? { Value::Sequence(SequenceData::Buffer(BuffData { data })) => { if data.len() != 32 { - return Err(RuntimeErrorType::BadBlockHash(data).into()); + return Err(RuntimeError::BadBlockHash(data).into()); } else { StacksBlockId::from(data.as_slice()) } } x => { - return Err(CheckErrors::TypeValueError(Box::new(BUFF_32.clone()), Box::new(x)).into()) + return Err( + CheckErrorKind::TypeValueError(Box::new(BUFF_32.clone()), Box::new(x)).into(), + ) } }; @@ -469,7 +476,7 @@ pub fn special_set_entry_v200( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(3, args)?; @@ -478,7 +485,7 @@ pub fn special_set_entry_v200( let value = eval(&args[2], env, context)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -486,7 +493,7 @@ pub fn special_set_entry_v200( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::SetEntry, @@ -512,7 +519,7 @@ pub fn special_set_entry_v205( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(3, args)?; @@ -521,7 +528,7 @@ pub fn special_set_entry_v205( let value = eval(&args[2], env, context)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -529,7 +536,7 @@ pub fn special_set_entry_v205( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; let epoch = *env.epoch(); let result = env @@ -555,7 +562,7 @@ pub fn special_insert_entry_v200( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(3, args)?; @@ -564,7 +571,7 @@ pub fn special_insert_entry_v200( let value = eval(&args[2], env, context)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -572,7 +579,7 @@ pub fn special_insert_entry_v200( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::SetEntry, @@ -599,7 +606,7 @@ pub fn special_insert_entry_v205( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(3, args)?; @@ -608,7 +615,7 @@ pub fn special_insert_entry_v205( let value = eval(&args[2], env, context)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -616,7 +623,7 @@ pub fn special_insert_entry_v205( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; let epoch = *env.epoch(); let result = env @@ -642,14 +649,14 @@ pub fn special_delete_entry_v200( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(2, args)?; let key = eval(&args[1], env, context)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -657,7 +664,7 @@ pub fn special_delete_entry_v200( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::SetEntry, @@ -682,14 +689,14 @@ pub fn special_delete_entry_v205( context: &LocalContext, ) -> Result { if env.global_context.is_read_only() { - return Err(CheckErrors::WriteAttemptedInReadOnly.into()); + return Err(CheckErrorKind::WriteAttemptedInReadOnly.into()); } check_argument_count(2, args)?; let key = eval(&args[1], env, context)?; - let map_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let map_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let contract = &env.contract_context.contract_identifier; @@ -697,7 +704,7 @@ pub fn special_delete_entry_v205( .contract_context .meta_data_map .get(map_name) - .ok_or(CheckErrors::NoSuchMap(map_name.to_string()))?; + .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; let epoch = *env.epoch(); let result = env @@ -731,10 +738,10 @@ pub fn special_delete_entry_v205( /// - `block-reward` returns the block reward for the block at `block-height` /// /// # Errors: -/// - CheckErrors::IncorrectArgumentCount if there aren't 2 arguments. -/// - CheckErrors::GetStacksBlockInfoExpectPropertyName if `args[0]` isn't a ClarityName. -/// - CheckErrors::NoSuchStacksBlockInfoProperty if `args[0]` isn't a StacksBlockInfoProperty. -/// - CheckErrors::TypeValueError if `args[1]` isn't a `uint`. +/// - CheckErrorKind::IncorrectArgumentCount if there aren't 2 arguments. +/// - CheckErrorKind::GetStacksBlockInfoExpectPropertyName if `args[0]` isn't a ClarityName. +/// - CheckErrorKind::NoSuchStacksBlockInfoProperty if `args[0]` isn't a StacksBlockInfoProperty. +/// - CheckErrorKind::TypeValueError if `args[1]` isn't a `uint`. pub fn special_get_block_info( args: &[SymbolicExpression], env: &mut Environment, @@ -748,18 +755,18 @@ pub fn special_get_block_info( // Handle the block property name input arg. let property_name = args[0] .match_atom() - .ok_or(CheckErrors::GetBlockInfoExpectPropertyName)?; + .ok_or(CheckErrorKind::GetBlockInfoExpectPropertyName)?; let version = env.contract_context.get_clarity_version(); let block_info_prop = BlockInfoProperty::lookup_by_name_at_version(property_name, version) - .ok_or(CheckErrors::GetBlockInfoExpectPropertyName)?; + .ok_or(CheckErrorKind::GetBlockInfoExpectPropertyName)?; // Handle the block-height input arg clause. let height_eval = eval(&args[1], env, context)?; let height_value = match height_eval { Value::UInt(result) => Ok(result), - x => Err(CheckErrors::TypeValueError( + x => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(x), )), @@ -883,10 +890,10 @@ pub fn special_get_block_info( /// - `pox_addrs` returns the list of PoX addresses paid out at `burn_block_height` /// /// # Errors: -/// - CheckErrors::IncorrectArgumentCount if there aren't 2 arguments. -/// - CheckErrors::GetBlockInfoExpectPropertyName if `args[0]` isn't a ClarityName. -/// - CheckErrors::NoSuchBurnBlockInfoProperty if `args[0]` isn't a BurnBlockInfoProperty. -/// - CheckErrors::TypeValueError if `args[1]` isn't a `uint`. +/// - CheckErrorKind::IncorrectArgumentCount if there aren't 2 arguments. +/// - CheckErrorKind::GetBlockInfoExpectPropertyName if `args[0]` isn't a ClarityName. +/// - CheckErrorKind::NoSuchBurnBlockInfoProperty if `args[0]` isn't a BurnBlockInfoProperty. +/// - CheckErrorKind::TypeValueError if `args[1]` isn't a `uint`. pub fn special_get_burn_block_info( args: &[SymbolicExpression], env: &mut Environment, @@ -899,10 +906,10 @@ pub fn special_get_burn_block_info( // Handle the block property name input arg. let property_name = args[0] .match_atom() - .ok_or(CheckErrors::GetBlockInfoExpectPropertyName)?; + .ok_or(CheckErrorKind::GetBlockInfoExpectPropertyName)?; let block_info_prop = BurnBlockInfoProperty::lookup_by_name(property_name).ok_or( - CheckErrors::NoSuchBurnBlockInfoProperty(property_name.to_string()), + CheckErrorKind::NoSuchBurnBlockInfoProperty(property_name.to_string()), )?; // Handle the block-height input arg clause. @@ -910,7 +917,7 @@ pub fn special_get_burn_block_info( let height_value = match height_eval { Value::UInt(result) => result, x => { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(x), ) @@ -956,7 +963,7 @@ pub fn special_get_burn_block_info( env.epoch(), ) .map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "FATAL: could not convert address list to Value".into(), ) })?, @@ -964,12 +971,12 @@ pub fn special_get_burn_block_info( ("payout".into(), Value::UInt(payout)), ]) .map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "FATAL: failed to build pox addrs and payout tuple".into(), ) })?, )) - .map_err(|_| InterpreterError::Expect("FATAL: could not build Some(..)".into()))?), + .map_err(|_| VmInternalError::Expect("FATAL: could not build Some(..)".into()))?), None => Ok(Value::none()), } } @@ -984,10 +991,10 @@ pub fn special_get_burn_block_info( /// - `time` returns the block time at `block-height` /// /// # Errors: -/// - CheckErrors::IncorrectArgumentCount if there aren't 2 arguments. -/// - CheckErrors::GetStacksBlockInfoExpectPropertyName if `args[0]` isn't a ClarityName. -/// - CheckErrors::NoSuchStacksBlockInfoProperty if `args[0]` isn't a StacksBlockInfoProperty. -/// - CheckErrors::TypeValueError if `args[1]` isn't a `uint`. +/// - CheckErrorKind::IncorrectArgumentCount if there aren't 2 arguments. +/// - CheckErrorKind::GetStacksBlockInfoExpectPropertyName if `args[0]` isn't a ClarityName. +/// - CheckErrorKind::NoSuchStacksBlockInfoProperty if `args[0]` isn't a StacksBlockInfoProperty. +/// - CheckErrorKind::TypeValueError if `args[1]` isn't a `uint`. pub fn special_get_stacks_block_info( args: &[SymbolicExpression], env: &mut Environment, @@ -1001,17 +1008,17 @@ pub fn special_get_stacks_block_info( // Handle the block property name input arg. let property_name = args[0] .match_atom() - .ok_or(CheckErrors::GetStacksBlockInfoExpectPropertyName)?; + .ok_or(CheckErrorKind::GetStacksBlockInfoExpectPropertyName)?; let block_info_prop = StacksBlockInfoProperty::lookup_by_name(property_name).ok_or( - CheckErrors::NoSuchStacksBlockInfoProperty(property_name.to_string()), + CheckErrorKind::NoSuchStacksBlockInfoProperty(property_name.to_string()), )?; // Handle the block-height input arg. let height_eval = eval(&args[1], env, context)?; let height_value = match height_eval { Value::UInt(result) => Ok(result), - x => Err(CheckErrors::TypeValueError( + x => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(x), )), @@ -1066,10 +1073,10 @@ pub fn special_get_stacks_block_info( /// - `block-reward` returns the block reward for the tenure of which `block-height` is a part /// /// # Errors: -/// - CheckErrors::IncorrectArgumentCount if there aren't 2 arguments. -/// - CheckErrors::GetTenureInfoExpectPropertyName if `args[0]` isn't a ClarityName. -/// - CheckErrors::NoSuchTenureInfoProperty if `args[0]` isn't a TenureInfoProperty. -/// - CheckErrors::TypeValueError if `args[1]` isn't a `uint`. +/// - CheckErrorKind::IncorrectArgumentCount if there aren't 2 arguments. +/// - CheckErrorKind::GetTenureInfoExpectPropertyName if `args[0]` isn't a ClarityName. +/// - CheckErrorKind::NoSuchTenureInfoProperty if `args[0]` isn't a TenureInfoProperty. +/// - CheckErrorKind::TypeValueError if `args[1]` isn't a `uint`. pub fn special_get_tenure_info( args: &[SymbolicExpression], env: &mut Environment, @@ -1083,16 +1090,16 @@ pub fn special_get_tenure_info( // Handle the block property name input arg. let property_name = args[0] .match_atom() - .ok_or(CheckErrors::GetTenureInfoExpectPropertyName)?; + .ok_or(CheckErrorKind::GetTenureInfoExpectPropertyName)?; let block_info_prop = TenureInfoProperty::lookup_by_name(property_name) - .ok_or(CheckErrors::GetTenureInfoExpectPropertyName)?; + .ok_or(CheckErrorKind::GetTenureInfoExpectPropertyName)?; // Handle the block-height input arg. let height_eval = eval(&args[1], env, context)?; let height_value = match height_eval { Value::UInt(result) => Ok(result), - x => Err(CheckErrors::TypeValueError( + x => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(x), )), @@ -1176,7 +1183,7 @@ pub fn special_contract_hash( check_argument_count(1, args)?; let contract_expr = args .first() - .ok_or(CheckErrors::IncorrectArgumentCount(1, 0))?; + .ok_or(CheckErrorKind::IncorrectArgumentCount(1, 0))?; let contract_value = eval(contract_expr, env, context)?; let contract_identifier = match contract_value { Value::Principal(PrincipalData::Standard(_)) => { @@ -1187,7 +1194,7 @@ pub fn special_contract_hash( _ => { // If the value is not a principal, we return a check error. return Err( - CheckErrors::ExpectedContractPrincipalValue(Box::new(contract_value)).into(), + CheckErrorKind::ExpectedContractPrincipalValue(Box::new(contract_value)).into(), ); } }; diff --git a/clarity/src/vm/functions/define.rs b/clarity/src/vm/functions/define.rs index 7fc3ba77b62..30094737998 100644 --- a/clarity/src/vm/functions/define.rs +++ b/clarity/src/vm/functions/define.rs @@ -19,7 +19,7 @@ use std::collections::BTreeMap; use crate::vm::callables::{DefineType, DefinedFunction}; use crate::vm::contexts::{ContractContext, Environment, LocalContext}; use crate::vm::errors::{ - check_argument_count, check_arguments_at_least, CheckErrors, InterpreterResult as Result, + check_argument_count, check_arguments_at_least, CheckErrorKind, InterpreterResult as Result, SyntaxBindingErrorType, }; use crate::vm::eval; @@ -110,7 +110,7 @@ pub enum DefineResult { fn check_legal_define(name: &str, contract_context: &ContractContext) -> Result<()> { if contract_context.is_name_used(name) { - Err(CheckErrors::NameAlreadyUsed(name.to_string()).into()) + Err(CheckErrorKind::NameAlreadyUsed(name.to_string()).into()) } else { Ok(()) } @@ -136,15 +136,15 @@ fn handle_define_function( ) -> Result { let (function_symbol, arg_symbols) = signature .split_first() - .ok_or(CheckErrors::DefineFunctionBadSignature)?; + .ok_or(CheckErrorKind::DefineFunctionBadSignature)?; let function_name = function_symbol .match_atom() - .ok_or(CheckErrors::ExpectedName)?; + .ok_or(CheckErrorKind::ExpectedName)?; check_legal_define(function_name, env.contract_context)?; - let arguments = parse_name_type_pairs::<_, CheckErrors>( + let arguments = parse_name_type_pairs::<_, CheckErrorKind>( *env.epoch(), arg_symbols, SyntaxBindingErrorType::Eval, @@ -217,7 +217,7 @@ fn handle_define_fungible_token( Some(total_supply_int), )) } else { - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(total_supply_value), ) @@ -288,7 +288,7 @@ impl<'a> DefineFunctionsParsed<'a> { /// a define-statement, returns None if the supplied expression is not a define. pub fn try_parse( expression: &'a SymbolicExpression, - ) -> std::result::Result>, CheckErrors> { + ) -> std::result::Result>, CheckErrorKind> { let (define_type, args) = match DefineFunctions::try_parse(expression) { Some(x) => x, None => return Ok(None), @@ -296,7 +296,7 @@ impl<'a> DefineFunctionsParsed<'a> { let result = match define_type { DefineFunctions::Constant => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; DefineFunctionsParsed::Constant { name, value: &args[1], @@ -306,7 +306,7 @@ impl<'a> DefineFunctionsParsed<'a> { check_argument_count(2, args)?; let signature = args[0] .match_list() - .ok_or(CheckErrors::DefineFunctionBadSignature)?; + .ok_or(CheckErrorKind::DefineFunctionBadSignature)?; DefineFunctionsParsed::PrivateFunction { signature, body: &args[1], @@ -316,7 +316,7 @@ impl<'a> DefineFunctionsParsed<'a> { check_argument_count(2, args)?; let signature = args[0] .match_list() - .ok_or(CheckErrors::DefineFunctionBadSignature)?; + .ok_or(CheckErrorKind::DefineFunctionBadSignature)?; DefineFunctionsParsed::ReadOnlyFunction { signature, body: &args[1], @@ -326,7 +326,7 @@ impl<'a> DefineFunctionsParsed<'a> { check_argument_count(2, args)?; let signature = args[0] .match_list() - .ok_or(CheckErrors::DefineFunctionBadSignature)?; + .ok_or(CheckErrorKind::DefineFunctionBadSignature)?; DefineFunctionsParsed::PublicFunction { signature, body: &args[1], @@ -334,7 +334,7 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::NonFungibleToken => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; DefineFunctionsParsed::NonFungibleToken { name, nft_type: &args[1], @@ -342,7 +342,7 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::FungibleToken => { check_arguments_at_least(1, args)?; - let name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; if args.len() == 1 { DefineFunctionsParsed::UnboundedFungibleToken { name } } else if args.len() == 2 { @@ -351,12 +351,12 @@ impl<'a> DefineFunctionsParsed<'a> { max_supply: &args[1], } } else { - return Err(CheckErrors::IncorrectArgumentCount(1, args.len())); + return Err(CheckErrorKind::IncorrectArgumentCount(1, args.len())); } } DefineFunctions::Map => { check_argument_count(3, args)?; - let name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; DefineFunctionsParsed::Map { name, key_type: &args[1], @@ -365,7 +365,7 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::PersistedVariable => { check_argument_count(3, args)?; - let name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; DefineFunctionsParsed::PersistedVariable { name, data_type: &args[1], @@ -374,7 +374,7 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::Trait => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; DefineFunctionsParsed::Trait { name, functions: &args[1..], @@ -382,13 +382,13 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::UseTrait => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; match &args[1].expr { Field(ref field) => DefineFunctionsParsed::UseTrait { name, trait_identifier: field, }, - _ => return Err(CheckErrors::ExpectedTraitIdentifier), + _ => return Err(CheckErrorKind::ExpectedTraitIdentifier), } } DefineFunctions::ImplTrait => { @@ -397,7 +397,7 @@ impl<'a> DefineFunctionsParsed<'a> { Field(ref field) => DefineFunctionsParsed::ImplTrait { trait_identifier: field, }, - _ => return Err(CheckErrors::ExpectedTraitIdentifier), + _ => return Err(CheckErrorKind::ExpectedTraitIdentifier), } } }; diff --git a/clarity/src/vm/functions/mod.rs b/clarity/src/vm/functions/mod.rs index f458c282e6c..b82a028aeb3 100644 --- a/clarity/src/vm/functions/mod.rs +++ b/clarity/src/vm/functions/mod.rs @@ -20,8 +20,8 @@ use crate::vm::callables::{cost_input_sized_vararg, CallableType, NativeHandle}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{constants as cost_constants, runtime_cost, CostTracker, MemoryConsumer}; use crate::vm::errors::{ - check_argument_count, check_arguments_at_least, CheckErrors, Error, - InterpreterResult as Result, ShortReturnType, SyntaxBindingError, SyntaxBindingErrorType, + check_argument_count, check_arguments_at_least, CheckErrorKind, EarlyReturnError, + InterpreterResult as Result, SyntaxBindingError, SyntaxBindingErrorType, VmExecutionError, }; pub use crate::vm::functions::assets::stx_transfer_consolidated; use crate::vm::representations::{ClarityName, SymbolicExpression, SymbolicExpressionType}; @@ -65,7 +65,7 @@ macro_rules! switch_on_global_epoch { }; } -use super::errors::InterpreterError; +use super::errors::VmInternalError; use crate::vm::ClarityVersion; mod arithmetic; @@ -600,7 +600,7 @@ fn native_eq(args: Vec, env: &mut Environment) -> Result { fn native_begin(mut args: Vec) -> Result { match args.pop() { Some(v) => Ok(v), - None => Err(CheckErrors::RequiresAtLeastArguments(1, 0).into()), + None => Err(CheckErrorKind::RequiresAtLeastArguments(1, 0).into()), } } @@ -610,7 +610,7 @@ fn special_print( context: &LocalContext, ) -> Result { let arg = args.first().ok_or_else(|| { - InterpreterError::BadSymbolicRepresentation("Print should have an argument".into()) + VmInternalError::BadSymbolicRepresentation("Print should have an argument".into()) })?; let input = eval(arg, env, context)?; @@ -642,7 +642,7 @@ fn special_if( eval(&args[2], env, context) } } - _ => Err(CheckErrors::TypeValueError( + _ => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::BoolType), Box::new(conditional), ) @@ -667,10 +667,10 @@ fn special_asserts( Ok(conditional) } else { let thrown = eval(&args[1], env, context)?; - Err(ShortReturnType::AssertionFailed(Box::new(thrown)).into()) + Err(EarlyReturnError::AssertionFailed(Box::new(thrown)).into()) } } - _ => Err(CheckErrors::TypeValueError( + _ => Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::BoolType), Box::new(conditional), ) @@ -685,7 +685,7 @@ pub fn handle_binding_list( ) -> std::result::Result<(), E> where F: FnMut(&ClarityName, &SymbolicExpression) -> std::result::Result<(), E>, - E: for<'a> From<(CheckErrors, &'a SymbolicExpression)>, + E: for<'a> From<(CheckErrorKind, &'a SymbolicExpression)>, { for (i, binding) in bindings.iter().enumerate() { let binding_expression = binding.match_list().ok_or_else(|| { @@ -739,7 +739,7 @@ fn special_let( check_arguments_at_least(2, args)?; // parse and eval the bindings. - let bindings = args[0].match_list().ok_or(CheckErrors::BadLetSyntax)?; + let bindings = args[0].match_list().ok_or(CheckErrorKind::BadLetSyntax)?; runtime_cost(ClarityCostFunction::Let, env, bindings.len())?; @@ -749,11 +749,11 @@ fn special_let( let mut memory_use = 0; finally_drop_memory!( env, memory_use; { - handle_binding_list::<_, Error>(bindings, SyntaxBindingErrorType::Let, |binding_name, var_sexp| { + handle_binding_list::<_, VmExecutionError>(bindings, SyntaxBindingErrorType::Let, |binding_name, var_sexp| { if is_reserved(binding_name, env.contract_context.get_clarity_version()) || env.contract_context.lookup_function(binding_name).is_some() || inner_context.lookup_variable(binding_name).is_some() { - return Err(CheckErrors::NameAlreadyUsed(binding_name.clone().into()).into()) + return Err(CheckErrorKind::NameAlreadyUsed(binding_name.clone().into()).into()) } let binding_value = eval(var_sexp, env, &inner_context)?; @@ -777,7 +777,7 @@ fn special_let( last_result.replace(body_result); } // last_result should always be Some(...), because of the arg len check above. - last_result.ok_or_else(|| InterpreterError::Expect("Failed to get let result".into()).into()) + last_result.ok_or_else(|| VmInternalError::Expect("Failed to get let result".into()).into()) }) } @@ -821,7 +821,7 @@ fn special_contract_of( let contract_ref = match &args[0].expr { SymbolicExpressionType::Atom(contract_ref) => contract_ref, - _ => return Err(CheckErrors::ContractOfExpectsTrait.into()), + _ => return Err(CheckErrorKind::ContractOfExpectsTrait.into()), }; let contract_identifier = match context.lookup_callable_contract(contract_ref) { @@ -830,12 +830,12 @@ fn special_contract_of( .database .get_contract(&trait_data.contract_identifier) .map_err(|_e| { - CheckErrors::NoSuchContract(trait_data.contract_identifier.to_string()) + CheckErrorKind::NoSuchContract(trait_data.contract_identifier.to_string()) })?; &trait_data.contract_identifier } - _ => return Err(CheckErrors::ContractOfExpectsTrait.into()), + _ => return Err(CheckErrorKind::ContractOfExpectsTrait.into()), }; let contract_principal = Value::Principal(PrincipalData::Contract(contract_identifier.clone())); diff --git a/clarity/src/vm/functions/options.rs b/clarity/src/vm/functions/options.rs index c47dae91ccd..94f55a517ab 100644 --- a/clarity/src/vm/functions/options.rs +++ b/clarity/src/vm/functions/options.rs @@ -18,8 +18,8 @@ use crate::vm::contexts::{Environment, LocalContext}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{runtime_cost, CostTracker, MemoryConsumer}; use crate::vm::errors::{ - check_arguments_at_least, CheckErrors, InterpreterError, InterpreterResult as Result, - RuntimeErrorType, ShortReturnType, + check_arguments_at_least, CheckErrorKind, EarlyReturnError, InterpreterResult as Result, + RuntimeError, VmInternalError, }; use crate::vm::types::{CallableData, OptionalData, ResponseData, TypeSignature, Value}; use crate::vm::Value::CallableContract; @@ -35,7 +35,9 @@ fn inner_unwrap(to_unwrap: Value) -> Result> { None } } - _ => return Err(CheckErrors::ExpectedOptionalOrResponseValue(Box::new(to_unwrap)).into()), + _ => { + return Err(CheckErrorKind::ExpectedOptionalOrResponseValue(Box::new(to_unwrap)).into()) + } }; Ok(result) @@ -50,7 +52,7 @@ fn inner_unwrap_err(to_unwrap: Value) -> Result> { None } } - _ => return Err(CheckErrors::ExpectedResponseValue(Box::new(to_unwrap)).into()), + _ => return Err(CheckErrorKind::ExpectedResponseValue(Box::new(to_unwrap)).into()), }; Ok(result) @@ -59,28 +61,28 @@ fn inner_unwrap_err(to_unwrap: Value) -> Result> { pub fn native_unwrap(input: Value) -> Result { inner_unwrap(input).and_then(|opt_value| match opt_value { Some(v) => Ok(v), - None => Err(RuntimeErrorType::UnwrapFailure.into()), + None => Err(RuntimeError::UnwrapFailure.into()), }) } pub fn native_unwrap_or_ret(input: Value, thrown: Value) -> Result { inner_unwrap(input).and_then(|opt_value| match opt_value { Some(v) => Ok(v), - None => Err(ShortReturnType::ExpectedValue(Box::new(thrown)).into()), + None => Err(EarlyReturnError::UnwrapFailed(Box::new(thrown)).into()), }) } pub fn native_unwrap_err(input: Value) -> Result { inner_unwrap_err(input).and_then(|opt_value| match opt_value { Some(v) => Ok(v), - None => Err(RuntimeErrorType::UnwrapFailure.into()), + None => Err(RuntimeError::UnwrapFailure.into()), }) } pub fn native_unwrap_err_or_ret(input: Value, thrown: Value) -> Result { inner_unwrap_err(input).and_then(|opt_value| match opt_value { Some(v) => Ok(v), - None => Err(ShortReturnType::ExpectedValue(Box::new(thrown)).into()), + None => Err(EarlyReturnError::UnwrapFailed(Box::new(thrown)).into()), }) } @@ -88,21 +90,21 @@ pub fn native_try_ret(input: Value) -> Result { match input { Value::Optional(data) => match data.data { Some(data) => Ok(*data), - None => Err(ShortReturnType::ExpectedValue(Box::new(Value::none())).into()), + None => Err(EarlyReturnError::UnwrapFailed(Box::new(Value::none())).into()), }, Value::Response(data) => { if data.committed { Ok(*data.data) } else { let short_return_val = Value::error(*data.data).map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "BUG: Failed to construct new response type from old response type".into(), ) })?; - Err(ShortReturnType::ExpectedValue(Box::new(short_return_val)).into()) + Err(EarlyReturnError::UnwrapFailed(Box::new(short_return_val)).into()) } } - _ => Err(CheckErrors::ExpectedOptionalOrResponseValue(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedOptionalOrResponseValue(Box::new(input)).into()), } } @@ -118,7 +120,7 @@ fn eval_with_new_binding( || env.contract_context.lookup_function(&bind_name).is_some() || inner_context.lookup_variable(&bind_name).is_some() { - return Err(CheckErrors::NameAlreadyUsed(bind_name.into()).into()); + return Err(CheckErrorKind::NameAlreadyUsed(bind_name.into()).into()); } let memory_use = bind_value.get_memory_use()?; @@ -150,14 +152,16 @@ fn special_match_opt( context: &LocalContext, ) -> Result { if args.len() != 3 { - Err(CheckErrors::BadMatchOptionSyntax(Box::new( - CheckErrors::IncorrectArgumentCount(4, args.len() + 1), + Err(CheckErrorKind::BadMatchOptionSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(4, args.len() + 1), )))?; } let bind_name = args[0] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchOptionSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let some_branch = &args[1]; let none_branch = &args[2]; @@ -175,19 +179,23 @@ fn special_match_resp( context: &LocalContext, ) -> Result { if args.len() != 4 { - Err(CheckErrors::BadMatchResponseSyntax(Box::new( - CheckErrors::IncorrectArgumentCount(5, args.len() + 1), + Err(CheckErrorKind::BadMatchResponseSyntax(Box::new( + CheckErrorKind::IncorrectArgumentCount(5, args.len() + 1), )))?; } let ok_bind_name = args[0] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let ok_branch = &args[1]; let err_bind_name = args[2] .match_atom() - .ok_or_else(|| CheckErrors::BadMatchResponseSyntax(Box::new(CheckErrors::ExpectedName)))? + .ok_or_else(|| { + CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + })? .clone(); let err_branch = &args[3]; @@ -212,7 +220,7 @@ pub fn special_match( match input { Value::Response(data) => special_match_resp(data, &args[1..], env, context), Value::Optional(data) => special_match_opt(data, &args[1..], env, context), - _ => Err(CheckErrors::BadMatchInput(Box::new(TypeSignature::type_of(&input)?)).into()), + _ => Err(CheckErrorKind::BadMatchInput(Box::new(TypeSignature::type_of(&input)?)).into()), } } @@ -223,14 +231,14 @@ pub fn native_some(input: Value) -> Result { fn is_some(input: Value) -> Result { match input { Value::Optional(ref data) => Ok(data.data.is_some()), - _ => Err(CheckErrors::ExpectedOptionalValue(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedOptionalValue(Box::new(input)).into()), } } fn is_okay(input: Value) -> Result { match input { Value::Response(data) => Ok(data.committed), - _ => Err(CheckErrors::ExpectedResponseValue(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedResponseValue(Box::new(input)).into()), } } @@ -264,6 +272,6 @@ pub fn native_default_to(default: Value, input: Value) -> Result { Some(data) => Ok(*data), None => Ok(default), }, - _ => Err(CheckErrors::ExpectedOptionalValue(Box::new(input)).into()), + _ => Err(CheckErrorKind::ExpectedOptionalValue(Box::new(input)).into()), } } diff --git a/clarity/src/vm/functions/principals.rs b/clarity/src/vm/functions/principals.rs index 51fc33136f2..55098aa2514 100644 --- a/clarity/src/vm/functions/principals.rs +++ b/clarity/src/vm/functions/principals.rs @@ -7,8 +7,8 @@ use crate::vm::contexts::GlobalContext; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::errors::{ - check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrors, - InterpreterError, InterpreterResult as Result, + check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, + InterpreterResult as Result, VmInternalError, }; use crate::vm::representations::{ SymbolicExpression, CONTRACT_MAX_NAME_LENGTH, CONTRACT_MIN_NAME_LENGTH, @@ -61,7 +61,7 @@ pub fn special_is_standard( let version = if let Value::Principal(ref p) = owner { p.version() } else { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::PrincipalType), Box::new(owner), ) @@ -102,7 +102,7 @@ fn create_principal_destruct_tuple( }), ), ]) - .map_err(|_| InterpreterError::Expect("FAIL: Failed to initialize tuple.".into()))?, + .map_err(|_| VmInternalError::Expect("FAIL: Failed to initialize tuple.".into()))?, )) } @@ -116,10 +116,10 @@ fn create_principal_true_error_response(error_int: PrincipalConstructErrorCode) ("error_code".into(), Value::UInt(error_int as u128)), ("value".into(), Value::none()), ]) - .map_err(|_| InterpreterError::Expect("FAIL: Failed to initialize tuple.".into()))?, + .map_err(|_| VmInternalError::Expect("FAIL: Failed to initialize tuple.".into()))?, )) .map_err(|_| { - InterpreterError::Expect("FAIL: Failed to initialize (err ..) response".into()).into() + VmInternalError::Expect("FAIL: Failed to initialize (err ..) response".into()).into() }) } @@ -138,14 +138,14 @@ fn create_principal_value_error_response( ( "value".into(), Value::some(value).map_err(|_| { - InterpreterError::Expect("Unexpected problem creating Value.".into()) + VmInternalError::Expect("Unexpected problem creating Value.".into()) })?, ), ]) - .map_err(|_| InterpreterError::Expect("FAIL: Failed to initialize tuple.".into()))?, + .map_err(|_| VmInternalError::Expect("FAIL: Failed to initialize tuple.".into()))?, )) .map_err(|_| { - InterpreterError::Expect("FAIL: Failed to initialize (err ..) response".into()).into() + VmInternalError::Expect("FAIL: Failed to initialize (err ..) response".into()).into() }) } @@ -169,7 +169,7 @@ pub fn special_principal_destruct( (issuer.0, issuer.1, Some(name)) } _ => { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::PrincipalType), Box::new(principal), ) @@ -211,7 +211,10 @@ pub fn special_principal_construct( _ => { return { // This is an aborting error because this should have been caught in analysis pass. - Err(CheckErrors::TypeValueError(Box::new(BUFF_1.clone()), Box::new(version)).into()) + Err( + CheckErrorKind::TypeValueError(Box::new(BUFF_1.clone()), Box::new(version)) + .into(), + ) }; } }; @@ -219,7 +222,7 @@ pub fn special_principal_construct( let version_byte = if verified_version.len() > 1 { // should have been caught by the type-checker return Err( - CheckErrors::TypeValueError(Box::new(BUFF_1.clone()), Box::new(version)).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_1.clone()), Box::new(version)).into(), ); } else if verified_version.is_empty() { // the type checker does not check the actual length of the buffer, but a 0-length buffer @@ -244,7 +247,7 @@ pub fn special_principal_construct( let verified_hash_bytes = match hash_bytes { Value::Sequence(SequenceData::Buffer(BuffData { ref data })) => data, _ => { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(BUFF_20.clone()), Box::new(hash_bytes), ) @@ -255,9 +258,11 @@ pub fn special_principal_construct( // This must have been a (buff 20). // This is an aborting error because this should have been caught in analysis pass. if verified_hash_bytes.len() > 20 { - return Err( - CheckErrors::TypeValueError(Box::new(BUFF_20.clone()), Box::new(hash_bytes)).into(), - ); + return Err(CheckErrorKind::TypeValueError( + Box::new(BUFF_20.clone()), + Box::new(hash_bytes), + ) + .into()); } // If the hash-bytes buffer has less than 20 bytes, this is a runtime error, because it @@ -277,7 +282,7 @@ pub fn special_principal_construct( let name_bytes = match name { Value::Sequence(SequenceData::String(CharType::ASCII(ascii_data))) => ascii_data, _ => { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::contract_name_string_ascii_type()?), Box::new(name), ) @@ -294,7 +299,7 @@ pub fn special_principal_construct( // if it's too long, then this should have been caught by the type-checker if name_bytes.data.len() > CONTRACT_MAX_NAME_LENGTH { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::contract_name_string_ascii_type()?), Box::new(Value::from(name_bytes)), ) @@ -305,7 +310,7 @@ pub fn special_principal_construct( // it here at runtime. If it's not valid, then it warrants this function evaluating to // (err ..). let name_string = String::from_utf8(name_bytes.data).map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "FAIL: could not convert bytes of type (string-ascii 40) back to a UTF-8 string" .into(), ) @@ -332,7 +337,7 @@ pub fn special_principal_construct( if version_byte_is_valid { Ok(Value::okay(principal).map_err(|_| { - InterpreterError::Expect("FAIL: failed to build an (ok ..) response".into()) + VmInternalError::Expect("FAIL: failed to build an (ok ..) response".into()) })?) } else { create_principal_value_error_response(PrincipalConstructErrorCode::VERSION_BYTE, principal) diff --git a/clarity/src/vm/functions/sequences.rs b/clarity/src/vm/functions/sequences.rs index cafc795d362..ebc6a6f7dc6 100644 --- a/clarity/src/vm/functions/sequences.rs +++ b/clarity/src/vm/functions/sequences.rs @@ -21,8 +21,8 @@ use stacks_common::types::StacksEpochId; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{runtime_cost, CostOverflowingMath}; use crate::vm::errors::{ - check_argument_count, check_arguments_at_least, CheckErrors, InterpreterResult as Result, - RuntimeErrorType, + check_argument_count, check_arguments_at_least, CheckErrorKind, InterpreterResult as Result, + RuntimeError, }; use crate::vm::representations::SymbolicExpression; use crate::vm::types::signatures::ListTypeData; @@ -57,7 +57,7 @@ pub fn special_filter( runtime_cost(ClarityCostFunction::Filter, env, 0)?; - let function_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let function_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let mut sequence = eval(&args[1], env, context)?; let function = lookup_function(function_name, env)?; @@ -71,7 +71,7 @@ pub fn special_filter( Ok(include) } else { Err( - CheckErrors::TypeValueError(Box::new(BoolType), Box::new(filter_eval)) + CheckErrorKind::TypeValueError(Box::new(BoolType), Box::new(filter_eval)) .into(), ) } @@ -79,7 +79,8 @@ pub fn special_filter( } _ => { return Err( - CheckErrors::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into(), + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)) + .into(), ) } }; @@ -95,7 +96,7 @@ pub fn special_fold( runtime_cost(ClarityCostFunction::Fold, env, 0)?; - let function_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let function_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let function = lookup_function(function_name, env)?; let mut sequence = eval(&args[1], env, context)?; @@ -113,9 +114,9 @@ pub fn special_fold( context, ) }), - _ => { - Err(CheckErrors::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into()) - } + _ => Err( + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into(), + ), } } @@ -128,7 +129,7 @@ pub fn special_map( runtime_cost(ClarityCostFunction::Map, env, args.len())?; - let function_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let function_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let function = lookup_function(function_name, env)?; // Let's consider a function f (f a b c ...) @@ -154,7 +155,7 @@ pub fn special_map( } _ => { return Err( - CheckErrors::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)) + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)) .into(), ) } @@ -210,7 +211,7 @@ pub fn special_append( TypeSignature::least_supertype(env.epoch(), &entry_type, &element_type) { let (element, _) = Value::sanitize_value(env.epoch(), &next_entry_type, element) - .ok_or_else(|| CheckErrors::ListTypesMustMatch)?; + .ok_or_else(|| CheckErrorKind::ListTypesMustMatch)?; let next_type_signature = ListTypeData::new_list(next_entry_type, size + 1)?; data.push(element); @@ -219,10 +220,10 @@ pub fn special_append( data, }))) } else { - Err(CheckErrors::TypeValueError(Box::new(entry_type), Box::new(element)).into()) + Err(CheckErrorKind::TypeValueError(Box::new(entry_type), Box::new(element)).into()) } } - _ => Err(CheckErrors::ExpectedListApplication.into()), + _ => Err(CheckErrorKind::ExpectedListApplication.into()), } } @@ -248,7 +249,7 @@ pub fn special_concat_v200( (Value::Sequence(ref mut seq), Value::Sequence(other_seq)) => { seq.concat(env.epoch(), other_seq) } - _ => Err(RuntimeErrorType::BadTypeConstruction.into()), + _ => Err(RuntimeError::BadTypeConstruction.into()), }?; Ok(wrapped_seq) @@ -276,7 +277,7 @@ pub fn special_concat_v205( } _ => { runtime_cost(ClarityCostFunction::Concat, env, 1)?; - Err(RuntimeErrorType::BadTypeConstruction.into()) + Err(RuntimeError::BadTypeConstruction.into()) } }?; @@ -299,7 +300,7 @@ pub fn special_as_max_len( Value::Sequence(ref sequence_data) => sequence_data.len() as u128, _ => { return Err( - CheckErrors::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)) + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)) .into(), ) } @@ -314,7 +315,7 @@ pub fn special_as_max_len( } } else { let actual_len = eval(&args[1], env, context)?; - Err(CheckErrors::TypeError( + Err(CheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::type_of(&actual_len)?), ) @@ -325,9 +326,9 @@ pub fn special_as_max_len( pub fn native_len(sequence: Value) -> Result { match sequence { Value::Sequence(sequence_data) => Ok(Value::UInt(sequence_data.len() as u128)), - _ => { - Err(CheckErrors::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into()) - } + _ => Err( + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into(), + ), } } @@ -338,7 +339,7 @@ pub fn native_index_of(sequence: Value, to_find: Value) -> Result { None => Ok(Value::none()), } } else { - Err(CheckErrors::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into()) + Err(CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into()) } } @@ -347,7 +348,7 @@ pub fn native_element_at(sequence: Value, index: Value) -> Result { sequence_data } else { return Err( - CheckErrors::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into(), + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::type_of(&sequence)?)).into(), ); }; @@ -358,7 +359,7 @@ pub fn native_element_at(sequence: Value, index: Value) -> Result { return Ok(Value::none()); } } else { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(index), ) @@ -410,7 +411,7 @@ pub fn special_slice( seq.slice(env.epoch(), left_position as usize, right_position as usize)?; Value::some(seq_value) } - _ => Err(RuntimeErrorType::BadTypeConstruction.into()), + _ => Err(RuntimeError::BadTypeConstruction.into()), } })(); @@ -439,7 +440,7 @@ pub fn special_replace_at( let expected_elem_type = if let TypeSignature::SequenceType(seq_subtype) = &seq_type { seq_subtype.unit_type()? } else { - return Err(CheckErrors::ExpectedSequence(Box::new(seq_type)).into()); + return Err(CheckErrorKind::ExpectedSequence(Box::new(seq_type)).into()); }; let index_val = eval(&args[1], env, context)?; let new_element = eval(&args[2], env, context)?; @@ -447,7 +448,7 @@ pub fn special_replace_at( if expected_elem_type != TypeSignature::NoType && !expected_elem_type.admits(env.epoch(), &new_element)? { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(expected_elem_type), Box::new(new_element), ) @@ -461,7 +462,7 @@ pub fn special_replace_at( return Ok(Value::none()); } } else { - return Err(CheckErrors::TypeValueError( + return Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(index_val), ) @@ -475,6 +476,6 @@ pub fn special_replace_at( } data.replace_at(env.epoch(), index, new_element) } else { - Err(CheckErrors::ExpectedSequence(Box::new(seq_type)).into()) + Err(CheckErrorKind::ExpectedSequence(Box::new(seq_type)).into()) } } diff --git a/clarity/src/vm/functions/tuples.rs b/clarity/src/vm/functions/tuples.rs index 7db8f13959a..325bef9d458 100644 --- a/clarity/src/vm/functions/tuples.rs +++ b/clarity/src/vm/functions/tuples.rs @@ -16,8 +16,8 @@ use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::errors::{ - check_argument_count, check_arguments_at_least, CheckErrors, InterpreterError, - InterpreterResult as Result, SyntaxBindingErrorType, + check_argument_count, check_arguments_at_least, CheckErrorKind, InterpreterResult as Result, + SyntaxBindingErrorType, VmInternalError, }; use crate::vm::representations::SymbolicExpression; use crate::vm::types::{TupleData, TypeSignature, Value}; @@ -49,7 +49,7 @@ pub fn tuple_get( // if the tuple argument is an option type, then return option(field-name). check_argument_count(2, args)?; - let arg_name = args[0].match_atom().ok_or(CheckErrors::ExpectedName)?; + let arg_name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; let value = eval(&args[1], env, context)?; @@ -60,13 +60,13 @@ pub fn tuple_get( if let Value::Tuple(tuple_data) = *data { runtime_cost(ClarityCostFunction::TupleGet, env, tuple_data.len())?; Ok(Value::some(tuple_data.get_owned(arg_name)?).map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "Tuple contents should *always* fit in a some wrapper".into(), ) })?) } else { Err( - CheckErrors::ExpectedTuple(Box::new(TypeSignature::type_of(&data)?)) + CheckErrorKind::ExpectedTuple(Box::new(TypeSignature::type_of(&data)?)) .into(), ) } @@ -78,21 +78,21 @@ pub fn tuple_get( runtime_cost(ClarityCostFunction::TupleGet, env, tuple_data.len())?; tuple_data.get_owned(arg_name) } - _ => Err(CheckErrors::ExpectedTuple(Box::new(TypeSignature::type_of(&value)?)).into()), + _ => Err(CheckErrorKind::ExpectedTuple(Box::new(TypeSignature::type_of(&value)?)).into()), } } pub fn tuple_merge(base: Value, update: Value) -> Result { let initial_values = match base { Value::Tuple(initial_values) => Ok(initial_values), - _ => Err(CheckErrors::ExpectedTuple(Box::new( + _ => Err(CheckErrorKind::ExpectedTuple(Box::new( TypeSignature::type_of(&base)?, ))), }?; let new_values = match update { Value::Tuple(new_values) => Ok(new_values), - _ => Err(CheckErrors::ExpectedTuple(Box::new( + _ => Err(CheckErrorKind::ExpectedTuple(Box::new( TypeSignature::type_of(&update)?, ))), }?; diff --git a/clarity/src/vm/mod.rs b/clarity/src/vm/mod.rs index 0ef0875be8d..0ec71c3af6c 100644 --- a/clarity/src/vm/mod.rs +++ b/clarity/src/vm/mod.rs @@ -73,7 +73,7 @@ use crate::vm::costs::{ // publish the non-generic StacksEpoch form for use throughout module pub use crate::vm::database::clarity_db::StacksEpoch; use crate::vm::errors::{ - CheckErrors, Error, InterpreterError, InterpreterResult as Result, RuntimeErrorType, + CheckErrorKind, InterpreterResult as Result, RuntimeError, VmExecutionError, VmInternalError, }; use crate::vm::events::StacksTransactionEvent; use crate::vm::functions::define::DefineResult; @@ -155,7 +155,7 @@ pub trait EvalHook { _env: &mut Environment, _context: &LocalContext, _expr: &SymbolicExpression, - _res: &core::result::Result, + _res: &core::result::Result, ); // Called upon completion of the execution @@ -164,10 +164,10 @@ pub trait EvalHook { fn lookup_variable(name: &str, context: &LocalContext, env: &mut Environment) -> Result { if name.starts_with(char::is_numeric) || name.starts_with('\'') { - Err(InterpreterError::BadSymbolicRepresentation(format!( - "Unexpected variable name: {name}" - )) - .into()) + Err( + VmInternalError::BadSymbolicRepresentation(format!("Unexpected variable name: {name}")) + .into(), + ) } else if let Some(value) = variables::lookup_reserved_variable(name, context, env)? { Ok(value) } else { @@ -183,7 +183,7 @@ fn lookup_variable(name: &str, context: &LocalContext, env: &mut Environment) -> runtime_cost(ClarityCostFunction::LookupVariableSize, env, value.size()?)?; let (value, _) = Value::sanitize_value(env.epoch(), &TypeSignature::type_of(&value)?, value) - .ok_or_else(|| CheckErrors::CouldNotDetermineType)?; + .ok_or_else(|| CheckErrorKind::CouldNotDetermineType)?; Ok(value) } else if let Some(callable_data) = context.lookup_callable_contract(name) { if env.contract_context.get_clarity_version() < &ClarityVersion::Clarity2 { @@ -192,7 +192,7 @@ fn lookup_variable(name: &str, context: &LocalContext, env: &mut Environment) -> Ok(Value::CallableContract(callable_data.clone())) } } else { - Err(CheckErrors::UndefinedVariable(name.to_string()).into()) + Err(CheckErrorKind::UndefinedVariable(name.to_string()).into()) } } } @@ -208,13 +208,13 @@ pub fn lookup_function(name: &str, env: &mut Environment) -> Result, env: &Environment) { - if let Err(Error::Runtime(_, ref mut stack_trace)) = result { + if let Err(VmExecutionError::Runtime(_, ref mut stack_trace)) = result { if stack_trace.is_none() { stack_trace.replace(env.call_stack.make_stack_trace()); } @@ -234,11 +234,11 @@ pub fn apply( // do recursion check on user functions. let track_recursion = matches!(function, CallableType::UserFunction(_)); if track_recursion && env.call_stack.contains(&identifier) { - return Err(CheckErrors::CircularReference(vec![identifier.to_string()]).into()); + return Err(CheckErrorKind::CircularReference(vec![identifier.to_string()]).into()); } if env.call_stack.depth() >= MAX_CALL_STACK_DEPTH { - return Err(RuntimeErrorType::MaxStackDepthReached.into()); + return Err(RuntimeError::MaxStackDepthReached.into()); } if let CallableType::SpecialFunction(_, function) = function { @@ -266,7 +266,7 @@ pub fn apply( Err(e) => { env.drop_memory(used_memory)?; env.call_stack.decr_apply_depth(); - return Err(Error::from(e)); + return Err(VmExecutionError::from(e)); } }; used_memory += arg_value.get_memory_use()?; @@ -278,7 +278,7 @@ pub fn apply( let mut resp = match function { CallableType::NativeFunction(_, function, cost_function) => { runtime_cost(cost_function.clone(), env, evaluated_args.len()) - .map_err(Error::from) + .map_err(VmExecutionError::from) .and_then(|_| function.apply(evaluated_args, env)) } CallableType::NativeFunction205(_, function, cost_function, cost_input_handle) => { @@ -288,11 +288,11 @@ pub fn apply( evaluated_args.len() as u64 }; runtime_cost(cost_function.clone(), env, cost_input) - .map_err(Error::from) + .map_err(VmExecutionError::from) .and_then(|_| function.apply(evaluated_args, env)) } CallableType::UserFunction(function) => function.apply(&evaluated_args, env), - _ => return Err(InterpreterError::Expect("Should be unreachable.".into()).into()), + _ => return Err(VmInternalError::Expect("Should be unreachable.".into()).into()), }; add_stack_trace(&mut resp, env); env.drop_memory(used_memory)?; @@ -341,16 +341,16 @@ pub fn eval( List(ref children) => { let (function_variable, rest) = children .split_first() - .ok_or(CheckErrors::NonFunctionApplication)?; + .ok_or(CheckErrorKind::NonFunctionApplication)?; let function_name = function_variable .match_atom() - .ok_or(CheckErrors::BadFunctionName)?; + .ok_or(CheckErrorKind::BadFunctionName)?; let f = lookup_function(function_name, env)?; apply(&f, rest, env, context) } TraitReference(_, _) | Field(_) => { - return Err(InterpreterError::BadSymbolicRepresentation( + return Err(VmInternalError::BadSymbolicRepresentation( "Unexpected trait reference".into(), ) .into()) @@ -414,7 +414,7 @@ pub fn eval_all( contract_context.persisted_names.insert(name.clone()); global_context.add_memory(value_type.type_size() - .map_err(|_| InterpreterError::Expect("Type size should be realizable".into()))? as u64)?; + .map_err(|_| VmInternalError::Expect("Type size should be realizable".into()))? as u64)?; global_context.add_memory(value.size()? as u64)?; @@ -430,9 +430,9 @@ pub fn eval_all( contract_context.persisted_names.insert(name.clone()); global_context.add_memory(key_type.type_size() - .map_err(|_| InterpreterError::Expect("Type size should be realizable".into()))? as u64)?; + .map_err(|_| VmInternalError::Expect("Type size should be realizable".into()))? as u64)?; global_context.add_memory(value_type.type_size() - .map_err(|_| InterpreterError::Expect("Type size should be realizable".into()))? as u64)?; + .map_err(|_| VmInternalError::Expect("Type size should be realizable".into()))? as u64)?; let data_type = global_context.database.create_map(&contract_context.contract_identifier, &name, key_type, value_type)?; @@ -443,7 +443,7 @@ pub fn eval_all( contract_context.persisted_names.insert(name.clone()); global_context.add_memory(TypeSignature::UIntType.type_size() - .map_err(|_| InterpreterError::Expect("Type size should be realizable".into()))? as u64)?; + .map_err(|_| VmInternalError::Expect("Type size should be realizable".into()))? as u64)?; let data_type = global_context.database.create_fungible_token(&contract_context.contract_identifier, &name, &total_supply)?; @@ -454,7 +454,7 @@ pub fn eval_all( contract_context.persisted_names.insert(name.clone()); global_context.add_memory(asset_type.type_size() - .map_err(|_| InterpreterError::Expect("Type size should be realizable".into()))? as u64)?; + .map_err(|_| VmInternalError::Expect("Type size should be realizable".into()))? as u64)?; let data_type = global_context.database.create_non_fungible_token(&contract_context.contract_identifier, &name, &asset_type)?; diff --git a/clarity/src/vm/tests/assets.rs b/clarity/src/vm/tests/assets.rs index a6e953cd4c0..15a6522061f 100644 --- a/clarity/src/vm/tests/assets.rs +++ b/clarity/src/vm/tests/assets.rs @@ -17,7 +17,7 @@ use stacks_common::types::StacksEpochId; use crate::vm::contexts::{AssetMap, OwnedEnvironment}; -use crate::vm::errors::Error; +use crate::vm::errors::VmExecutionError; use crate::vm::events::StacksTransactionEvent; use crate::vm::representations::SymbolicExpression; use crate::vm::tests::{test_clarity_versions, test_epochs}; @@ -25,7 +25,7 @@ use crate::vm::types::{PrincipalData, QualifiedContractIdentifier, Value}; #[cfg(test)] use crate::vm::{ contexts::AssetMapEntry, - errors::{CheckErrors, RuntimeErrorType}, + errors::{CheckErrorKind, RuntimeError}, tests::{ execute, is_committed, is_err_code, symbols_from_values, tl_env_factory as env_factory, TopLevelMemoryEnvironmentGenerator, @@ -136,7 +136,7 @@ fn execute_transaction( contract_identifier: &QualifiedContractIdentifier, tx: &str, args: &[SymbolicExpression], -) -> Result<(Value, AssetMap, Vec), Error> { +) -> Result<(Value, AssetMap, Vec), VmExecutionError> { env.execute_transaction(issuer, None, contract_identifier.clone(), tx, args) } @@ -296,7 +296,7 @@ fn test_native_stx_ops(epoch: StacksEpochId, mut env_factory: TopLevelMemoryEnvi // &symbols_from_values(vec![Value::UInt(2), p2.clone(), p1.clone()]) // ) // .unwrap_err(), - // RuntimeErrorType::ArithmeticOverflow.into() + // RuntimeError::ArithmeticOverflow.into() // ); // test 6: check balance @@ -606,7 +606,7 @@ fn test_simple_token_system( assert!(matches!( err, - Error::Unchecked(CheckErrors::TypeValueError(_, _)) + VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(_, _)) )); let (result, asset_map, _events) = execute_transaction( @@ -835,7 +835,7 @@ fn test_total_supply(epoch: StacksEpochId, mut env_factory: TopLevelMemoryEnviro .unwrap_err(); assert!(matches!( err, - Error::Unchecked(CheckErrors::TypeValueError(_, _)) + VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(_, _)) )); let err = owned_env @@ -843,7 +843,7 @@ fn test_total_supply(epoch: StacksEpochId, mut env_factory: TopLevelMemoryEnviro .unwrap_err(); assert!(matches!( err, - Error::Unchecked(CheckErrors::TypeValueError(_, _)) + VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(_, _)) )); owned_env @@ -890,7 +890,7 @@ fn test_total_supply(epoch: StacksEpochId, mut env_factory: TopLevelMemoryEnviro .unwrap_err(); println!("{err}"); assert!(match err { - Error::Runtime(RuntimeErrorType::SupplyOverflow(x, y), _) => (x, y) == (6, 5), + VmExecutionError::Runtime(RuntimeError::SupplyOverflow(x, y), _) => (x, y) == (6, 5), _ => false, }); } diff --git a/clarity/src/vm/tests/contracts.rs b/clarity/src/vm/tests/contracts.rs index 090e2872e84..225f6656e3c 100644 --- a/clarity/src/vm/tests/contracts.rs +++ b/clarity/src/vm/tests/contracts.rs @@ -26,8 +26,8 @@ use crate::vm::tests::{test_clarity_versions, test_epochs}; use crate::vm::types::{PrincipalData, QualifiedContractIdentifier, StandardPrincipalData, Value}; #[cfg(test)] use crate::vm::{ - ast::errors::ParseErrors, - errors::{CheckErrors, Error, RuntimeErrorType}, + ast::errors::ParseErrorKind, + errors::{CheckErrorKind, RuntimeError, VmExecutionError}, tests::{ env_factory, execute, is_committed, is_err_code_i128 as is_err_code, symbols_from_values, tl_env_factory, MemoryEnvironmentGenerator, TopLevelMemoryEnvironmentGenerator, @@ -114,12 +114,12 @@ fn test_get_block_info_eval( Ok(Value::none()), Ok(Value::none()), Ok(Value::none()), - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(Value::Int(-1)), ) .into()), - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::UIntType), Box::new(Value::Bool(true)), ) @@ -961,7 +961,7 @@ fn test_factorial_contract(epoch: StacksEpochId, mut env_factory: MemoryEnvironm .unwrap_err(); assert!(matches!( err_result, - Error::Unchecked(CheckErrors::NoSuchPublicFunction(_, _)) + VmExecutionError::Unchecked(CheckErrorKind::NoSuchPublicFunction(_, _)) )); let err_result = env @@ -974,7 +974,7 @@ fn test_factorial_contract(epoch: StacksEpochId, mut env_factory: MemoryEnvironm .unwrap_err(); assert!(matches!( err_result, - Error::Unchecked(CheckErrors::TypeValueError(_, _)) + VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(_, _)) )); } @@ -996,11 +996,9 @@ fn test_at_unknown_block( .unwrap_err(); eprintln!("{err}"); match err { - Error::Runtime(x, _) => assert_eq!( + VmExecutionError::Runtime(x, _) => assert_eq!( x, - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash::from( - vec![2_u8; 32].as_slice() - )) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash::from(vec![2_u8; 32].as_slice())) ), _ => panic!("Unexpected error"), } @@ -1038,8 +1036,8 @@ fn test_ast_stack_depth() { "; assert_eq!( vm_execute(program).unwrap_err(), - RuntimeErrorType::ASTError(Box::new( - ParseErrors::VaryExpressionStackDepthTooDeep.into(), + RuntimeError::ASTError(Box::new( + ParseErrorKind::VaryExpressionStackDepthTooDeep.into(), )) .into() ); @@ -1061,7 +1059,7 @@ fn test_arg_stack_depth() { "; assert_eq!( vm_execute(program).unwrap_err(), - RuntimeErrorType::MaxStackDepthReached.into() + RuntimeError::MaxStackDepthReached.into() ); } @@ -1098,7 +1096,7 @@ fn test_cc_stack_depth( assert_eq!( env.initialize_contract(contract_identifier, contract_two) .unwrap_err(), - RuntimeErrorType::MaxStackDepthReached.into() + RuntimeError::MaxStackDepthReached.into() ); } @@ -1139,7 +1137,7 @@ fn test_cc_trait_stack_depth( assert_eq!( env.initialize_contract(contract_identifier, contract_two) .unwrap_err(), - RuntimeErrorType::MaxStackDepthReached.into() + RuntimeError::MaxStackDepthReached.into() ); } @@ -1167,7 +1165,7 @@ fn test_eval_with_non_existing_contract( ); assert_eq!( result.as_ref().unwrap_err(), - &Error::Unchecked(CheckErrors::NoSuchContract( + &VmExecutionError::Unchecked(CheckErrorKind::NoSuchContract( QualifiedContractIdentifier::local("absent") .unwrap() .to_string() @@ -1357,7 +1355,7 @@ fn test_contract_hash_type_check( .unwrap_err(); assert_eq!( err, - Error::Unchecked(CheckErrors::ExpectedContractPrincipalValue(Box::new( + VmExecutionError::Unchecked(CheckErrorKind::ExpectedContractPrincipalValue(Box::new( Value::UInt(123) ))) ); @@ -1411,6 +1409,8 @@ fn test_contract_hash_pre_clarity4( assert_eq!( err, - Error::Unchecked(CheckErrors::UndefinedFunction("contract-hash?".to_string())) + VmExecutionError::Unchecked(CheckErrorKind::UndefinedFunction( + "contract-hash?".to_string() + )) ); } diff --git a/clarity/src/vm/tests/conversions.rs b/clarity/src/vm/tests/conversions.rs index 322eaff9310..4f3c8cda57e 100644 --- a/clarity/src/vm/tests/conversions.rs +++ b/clarity/src/vm/tests/conversions.rs @@ -16,7 +16,7 @@ use stacks_common::types::StacksEpochId; -pub use crate::vm::analysis::errors::CheckErrors; +pub use crate::vm::analysis::errors::CheckErrorKind; use crate::vm::tests::test_clarity_versions; use crate::vm::types::signatures::MAX_TO_ASCII_BUFFER_LEN; use crate::vm::types::SequenceSubtype::BufferType; @@ -48,14 +48,14 @@ fn test_simple_buff_to_int_le() { "(buff-to-int-le \"not-needed\" 0xfffffffffffffffffffffffffffffffe)"; assert_eq!( execute_v2(bad_wrong_number_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 2).into() + CheckErrorKind::IncorrectArgumentCount(1, 2).into() ); // Right number of arguments, but wrong type. let bad_wrong_type_test = "(buff-to-int-le \"wrong-type\")"; assert_eq!( execute_v2(bad_wrong_type_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -72,7 +72,7 @@ fn test_simple_buff_to_int_le() { let bad_too_large_test = "(buff-to-int-le 0x000102030405060708090a0b0c0d0e0f00)"; assert_eq!( execute_v2(bad_too_large_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -106,14 +106,14 @@ fn test_simple_buff_to_uint_le() { "(buff-to-uint-le \"not-needed\" 0xfffffffffffffffffffffffffffffffe)"; assert_eq!( execute_v2(bad_wrong_number_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 2).into() + CheckErrorKind::IncorrectArgumentCount(1, 2).into() ); // Right number of arguments, but wrong type. let bad_wrong_type_test = "(buff-to-uint-le \"wrong-type\")"; assert_eq!( execute_v2(bad_wrong_type_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -130,7 +130,7 @@ fn test_simple_buff_to_uint_le() { let bad_too_large_test = "(buff-to-uint-le 0x000102030405060708090a0b0c0d0e0f00)"; assert_eq!( execute_v2(bad_too_large_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -164,14 +164,14 @@ fn test_simple_buff_to_int_be() { "(buff-to-int-be \"not-needed\" 0xfffffffffffffffffffffffffffffffe)"; assert_eq!( execute_v2(bad_wrong_number_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 2).into() + CheckErrorKind::IncorrectArgumentCount(1, 2).into() ); // Right number of arguments, but wrong type. let bad_wrong_type_test = "(buff-to-int-be \"wrong-type\")"; assert_eq!( execute_v2(bad_wrong_type_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -188,7 +188,7 @@ fn test_simple_buff_to_int_be() { let bad_too_large_test = "(buff-to-int-be 0x000102030405060708090a0b0c0d0e0f00)"; assert_eq!( execute_v2(bad_too_large_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -222,14 +222,14 @@ fn test_simple_buff_to_uint_be() { "(buff-to-uint-be \"not-needed\" 0xfffffffffffffffffffffffffffffffe)"; assert_eq!( execute_v2(bad_wrong_number_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 2).into() + CheckErrorKind::IncorrectArgumentCount(1, 2).into() ); // Right number of arguments, but wrong type. let bad_wrong_type_test = "(buff-to-uint-be \"wrong-type\")"; assert_eq!( execute_v2(bad_wrong_type_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -246,7 +246,7 @@ fn test_simple_buff_to_uint_be() { let bad_too_large_test = "(buff-to-uint-be 0x000102030405060708090a0b0c0d0e0f00)"; assert_eq!( execute_v2(bad_too_large_test).unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap() ))), @@ -306,13 +306,13 @@ fn test_simple_string_to_int() { let no_args_test = r#"(string-to-int?)"#; assert_eq!( execute_v2(no_args_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 0).into() + CheckErrorKind::IncorrectArgumentCount(1, 0).into() ); let wrong_type_error_test = r#"(string-to-int? 1)"#; assert_eq!( execute_v2(wrong_type_error_test).unwrap_err(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::max_string_ascii().unwrap(), TypeSignature::max_string_utf8().unwrap(), @@ -371,13 +371,13 @@ fn test_simple_string_to_uint() { let no_args_test = r#"(string-to-uint?)"#; assert_eq!( execute_v2(no_args_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 0).into() + CheckErrorKind::IncorrectArgumentCount(1, 0).into() ); let wrong_type_error_test = r#"(string-to-uint? 1)"#; assert_eq!( execute_v2(wrong_type_error_test).unwrap_err(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::max_string_ascii().unwrap(), TypeSignature::max_string_utf8().unwrap(), @@ -405,13 +405,13 @@ fn test_simple_int_to_ascii() { let no_args_test = r#"(int-to-ascii)"#; assert_eq!( execute_v2(no_args_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 0).into() + CheckErrorKind::IncorrectArgumentCount(1, 0).into() ); let wrong_type_error_test = r#"(int-to-ascii "1")"#; assert_eq!( execute_v2(wrong_type_error_test).unwrap_err(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Sequence(SequenceData::String(CharType::ASCII( ASCIIData { @@ -440,13 +440,13 @@ fn test_simple_int_to_utf8() { let no_args_test = r#"(int-to-utf8)"#; assert_eq!( execute_v2(no_args_test).unwrap_err(), - CheckErrors::IncorrectArgumentCount(1, 0).into() + CheckErrorKind::IncorrectArgumentCount(1, 0).into() ); let wrong_type_error_test = r#"(int-to-utf8 "1")"#; assert_eq!( execute_v2(wrong_type_error_test).unwrap_err(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Sequence(SequenceData::String(CharType::ASCII( ASCIIData { diff --git a/clarity/src/vm/tests/datamaps.rs b/clarity/src/vm/tests/datamaps.rs index 83fef9ab764..ae71745a30b 100644 --- a/clarity/src/vm/tests/datamaps.rs +++ b/clarity/src/vm/tests/datamaps.rs @@ -16,12 +16,12 @@ use crate::vm::types::{TupleData, Value}; #[cfg(test)] use crate::vm::{ - errors::{CheckErrors, ShortReturnType, SyntaxBindingError}, + errors::{CheckErrorKind, EarlyReturnError, SyntaxBindingError}, types::{ListData, SequenceData, TupleTypeSignature, TypeSignature}, }; -use crate::vm::{execute, ClarityName, Error}; +use crate::vm::{execute, ClarityName, VmExecutionError}; -fn assert_executes(expected: Result, input: &str) { +fn assert_executes(expected: Result, input: &str) { assert_eq!(expected.unwrap(), execute(input).unwrap().unwrap()); } @@ -296,7 +296,7 @@ fn test_set_response_variable() { "#; let contract_src = contract_src.to_string(); assert_eq!( - Err(ShortReturnType::ExpectedValue(Box::new(Value::Int(5))).into()), + Err(EarlyReturnError::UnwrapFailed(Box::new(Value::Int(5))).into()), execute(&contract_src) ); } @@ -474,7 +474,7 @@ fn datamap_errors() { for program in tests.iter() { assert_eq!( execute(program).unwrap_err(), - CheckErrors::NoSuchMap("non-existent".to_string()).into() + CheckErrorKind::NoSuchMap("non-existent".to_string()).into() ); } } @@ -495,7 +495,7 @@ fn lists_system_2() { matches!( execute(test), - Err(Error::Unchecked(CheckErrors::TypeError(_, _))) + Err(VmExecutionError::Unchecked(CheckErrorKind::TypeError(_, _))) ); } @@ -560,7 +560,10 @@ fn lists_system() { println!("{test:#?}"); assert!(matches!( test, - Err(Error::Unchecked(CheckErrors::TypeValueError(_, _))) + Err(VmExecutionError::Unchecked(CheckErrorKind::TypeValueError( + _, + _ + ))) )); } } @@ -623,7 +626,7 @@ fn tuples_system() { for test in type_error_tests.iter() { let expected_type_error = match execute(test) { - Err(Error::Unchecked(CheckErrors::TypeValueError(_, _))) => true, + Err(VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(_, _))) => true, _ => { println!("{:?}", execute(test)); false @@ -643,12 +646,12 @@ fn bad_define_maps() { "(define-map lists { name: int } contents 5)", "(define-map lists { name: int } { contents: (list 5 0 int) })", ]; - let expected: Vec = vec![ - CheckErrors::BadSyntaxBinding(SyntaxBindingError::tuple_cons_invalid_length(0)).into(), - CheckErrors::UnknownTypeName("contents".to_string()).into(), - CheckErrors::ExpectedName.into(), - CheckErrors::IncorrectArgumentCount(3, 4).into(), - CheckErrors::InvalidTypeDescription.into(), + let expected: Vec = vec![ + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_invalid_length(0)).into(), + CheckErrorKind::UnknownTypeName("contents".to_string()).into(), + CheckErrorKind::ExpectedName.into(), + CheckErrorKind::IncorrectArgumentCount(3, 4).into(), + CheckErrorKind::InvalidTypeDescription.into(), ]; for (test, expected_err) in tests.iter().zip(expected.into_iter()) { @@ -668,15 +671,15 @@ fn bad_tuples() { "(get 1234 (tuple (name 1)))", ]; let expected = vec![ - CheckErrors::NameAlreadyUsed("name".into()), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_list(0)), - CheckErrors::BadSyntaxBinding(SyntaxBindingError::tuple_cons_invalid_length(1)), - CheckErrors::NoSuchTupleField( + CheckErrorKind::NameAlreadyUsed("name".into()), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_list(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_invalid_length(1)), + CheckErrorKind::NoSuchTupleField( "value".into(), TupleTypeSignature::try_from(vec![("name".into(), TypeSignature::IntType)]).unwrap(), ), - CheckErrors::IncorrectArgumentCount(2, 3), - CheckErrors::ExpectedName, + CheckErrorKind::IncorrectArgumentCount(2, 3), + CheckErrorKind::ExpectedName, ]; for (test, expected_err) in tests.iter().zip(expected.into_iter()) { @@ -769,7 +772,7 @@ fn test_non_tuple_map_get_set() { for test in type_error_tests.iter() { let expected_type_error = match execute(test) { - Err(Error::Unchecked(CheckErrors::TypeValueError(_, _))) => true, + Err(VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(_, _))) => true, _ => { println!("{:?}", execute(test)); false diff --git a/clarity/src/vm/tests/defines.rs b/clarity/src/vm/tests/defines.rs index 2cd874f2c31..7ff718cae36 100644 --- a/clarity/src/vm/tests/defines.rs +++ b/clarity/src/vm/tests/defines.rs @@ -21,19 +21,19 @@ use rstest_reuse::{self, *}; #[cfg(test)] use stacks_common::types::StacksEpochId; -use crate::vm::errors::{CheckErrors, Error}; +use crate::vm::errors::{CheckErrorKind, VmExecutionError}; use crate::vm::tests::test_clarity_versions; #[cfg(test)] use crate::vm::{ analysis::errors::SyntaxBindingError, - ast::{build_ast, errors::ParseErrors}, - errors::RuntimeErrorType, + ast::{build_ast, errors::ParseErrorKind}, + errors::RuntimeError, types::{QualifiedContractIdentifier, TypeSignature, TypeSignatureExt as _, Value}, {execute, ClarityVersion}, }; -fn assert_eq_err(e1: CheckErrors, e2: Error) { - let e1: Error = e1.into(); +fn assert_eq_err(e1: CheckErrorKind, e2: VmExecutionError) { + let e1: VmExecutionError = e1.into(); assert_eq!(e1, e2) } @@ -51,7 +51,7 @@ fn test_defines() { assert_eq!( execute(tests).unwrap_err(), - CheckErrors::IncorrectArgumentCount(2, 3).into() + CheckErrorKind::IncorrectArgumentCount(2, 3).into() ); let tests = "1"; @@ -67,10 +67,10 @@ fn test_accept_options(#[case] version: ClarityVersion, #[case] epoch: StacksEpo format!("{defun} (f (some 1))"), format!("{defun} (f (some true))"), ]; - let expectations: &[Result<_, Error>] = &[ + let expectations: &[Result<_, VmExecutionError>] = &[ Ok(Some(Value::Int(0))), Ok(Some(Value::Int(10))), - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::from_string("(optional int)", version, epoch)), Box::new(Value::some(Value::Bool(true)).unwrap()), ) @@ -84,7 +84,7 @@ fn test_accept_options(#[case] version: ClarityVersion, #[case] epoch: StacksEpo let bad_defun = "(define-private (f (b (optional int int))) (* 10 (default-to 0 b)))"; assert_eq!( execute(bad_defun).unwrap_err(), - CheckErrors::InvalidTypeDescription.into() + CheckErrorKind::InvalidTypeDescription.into() ); } @@ -101,16 +101,16 @@ fn test_bad_define_names() { (+ foo foo)"; assert_eq_err( - CheckErrors::NameAlreadyUsed("tx-sender".to_string()), + CheckErrorKind::NameAlreadyUsed("tx-sender".to_string()), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::NameAlreadyUsed("*".to_string()), + CheckErrorKind::NameAlreadyUsed("*".to_string()), execute(test1).unwrap_err(), ); - assert_eq_err(CheckErrors::ExpectedName, execute(test2).unwrap_err()); + assert_eq_err(CheckErrorKind::ExpectedName, execute(test2).unwrap_err()); assert_eq_err( - CheckErrors::NameAlreadyUsed("foo".to_string()), + CheckErrorKind::NameAlreadyUsed("foo".to_string()), execute(test3).unwrap_err(), ); } @@ -126,20 +126,20 @@ fn test_unwrap_ret() { assert_eq!(Ok(Some(Value::Int(1))), execute(test0)); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), execute(test1).unwrap_err(), ); assert_eq_err( - CheckErrors::ExpectedOptionalOrResponseValue(Box::new(Value::Int(1))), + CheckErrorKind::ExpectedOptionalOrResponseValue(Box::new(Value::Int(1))), execute(test2).unwrap_err(), ); assert_eq_err( - CheckErrors::ExpectedResponseValue(Box::new(Value::Int(1))), + CheckErrorKind::ExpectedResponseValue(Box::new(Value::Int(1))), execute(test3).unwrap_err(), ); assert_eq!(Ok(Some(Value::Int(1))), execute(test4)); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), execute(test5).unwrap_err(), ); } @@ -155,15 +155,15 @@ fn test_define_read_only() { assert_eq!(Ok(Some(Value::Int(1))), execute(test0)); assert_eq_err( - CheckErrors::WriteAttemptedInReadOnly, + CheckErrorKind::WriteAttemptedInReadOnly, execute(test1).unwrap_err(), ); assert_eq_err( - CheckErrors::WriteAttemptedInReadOnly, + CheckErrorKind::WriteAttemptedInReadOnly, execute(test2).unwrap_err(), ); assert_eq_err( - CheckErrors::WriteAttemptedInReadOnly, + CheckErrorKind::WriteAttemptedInReadOnly, execute(test3).unwrap_err(), ); } @@ -187,7 +187,10 @@ fn test_stack_depth() { assert_eq!(Ok(Some(Value::Int(64))), execute(&test0)); assert!(matches!( execute(&test1), - Err(Error::Runtime(RuntimeErrorType::MaxStackDepthReached, _)) + Err(VmExecutionError::Runtime( + RuntimeError::MaxStackDepthReached, + _ + )) )) } @@ -207,25 +210,25 @@ fn test_recursive_panic(#[case] version: ClarityVersion, #[case] epoch: StacksEp epoch, ) .unwrap_err(); - assert!(matches!(*err.err, ParseErrors::CircularReference(_))); + assert!(matches!(*err.err, ParseErrorKind::CircularReference(_))); } #[test] fn test_bad_variables() { let test0 = "(+ a 1)"; - let expected = CheckErrors::UndefinedVariable("a".to_string()); + let expected = CheckErrorKind::UndefinedVariable("a".to_string()); assert_eq_err(expected, execute(test0).unwrap_err()); let test1 = "(foo 2 1)"; - let expected = CheckErrors::UndefinedFunction("foo".to_string()); + let expected = CheckErrorKind::UndefinedFunction("foo".to_string()); assert_eq_err(expected, execute(test1).unwrap_err()); let test2 = "((lambda (x y) 1) 2 1)"; - let expected = CheckErrors::BadFunctionName; + let expected = CheckErrorKind::BadFunctionName; assert_eq_err(expected, execute(test2).unwrap_err()); let test4 = "()"; - let expected = CheckErrors::NonFunctionApplication; + let expected = CheckErrorKind::NonFunctionApplication; assert_eq_err(expected, execute(test4).unwrap_err()); } @@ -249,19 +252,19 @@ fn test_variable_shadowing() { "#; assert_eq_err( - CheckErrors::NameAlreadyUsed("cursor".to_string()), + CheckErrorKind::NameAlreadyUsed("cursor".to_string()), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::NameAlreadyUsed("cursor".to_string()), + CheckErrorKind::NameAlreadyUsed("cursor".to_string()), execute(test1).unwrap_err(), ); assert_eq_err( - CheckErrors::NameAlreadyUsed("cursor".to_string()), + CheckErrorKind::NameAlreadyUsed("cursor".to_string()), execute(test2).unwrap_err(), ); assert_eq_err( - CheckErrors::NameAlreadyUsed("cursor".to_string()), + CheckErrorKind::NameAlreadyUsed("cursor".to_string()), execute(test3).unwrap_err(), ); } @@ -269,7 +272,7 @@ fn test_variable_shadowing() { #[test] fn test_define_parse_panic() { let tests = "(define-private () 1)"; - let expected = CheckErrors::DefineFunctionBadSignature; + let expected = CheckErrorKind::DefineFunctionBadSignature; assert_eq_err(expected, execute(tests).unwrap_err()); } @@ -277,7 +280,7 @@ fn test_define_parse_panic() { fn test_define_parse_panic_2() { let tests = "(define-private (a b (d)) 1)"; assert_eq_err( - CheckErrors::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_list(0)), + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_list(0)), execute(tests).unwrap_err(), ); } @@ -290,16 +293,16 @@ fn test_define_constant_arg_count() { let test3 = "(define-constant foo u2 u3)"; assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), execute(test1).unwrap_err(), ); execute(test2).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), execute(test3).unwrap_err(), ); } @@ -312,16 +315,16 @@ fn test_define_private_arg_count() { let test3 = "(define-private (foo) u2 u3)"; assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), execute(test1).unwrap_err(), ); execute(test2).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), execute(test3).unwrap_err(), ); } @@ -334,16 +337,16 @@ fn test_define_public_arg_count() { let test3 = "(define-public (foo) (ok u2) u3)"; assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), execute(test1).unwrap_err(), ); execute(test2).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), execute(test3).unwrap_err(), ); } @@ -356,16 +359,16 @@ fn test_define_read_only_arg_count() { let test3 = "(define-read-only (foo) u2 u3)"; assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), execute(test1).unwrap_err(), ); execute(test2).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), execute(test3).unwrap_err(), ); } @@ -379,20 +382,20 @@ fn test_define_map_arg_count() { let test4 = "(define-map foo uint uint uint)"; assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 0), + CheckErrorKind::IncorrectArgumentCount(3, 0), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 1), + CheckErrorKind::IncorrectArgumentCount(3, 1), execute(test1).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 2), + CheckErrorKind::IncorrectArgumentCount(3, 2), execute(test2).unwrap_err(), ); execute(test3).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 4), + CheckErrorKind::IncorrectArgumentCount(3, 4), execute(test4).unwrap_err(), ); } @@ -406,20 +409,20 @@ fn test_define_data_var_arg_count() { let test4 = "(define-data-var foo uint u3 u4)"; assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 0), + CheckErrorKind::IncorrectArgumentCount(3, 0), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 1), + CheckErrorKind::IncorrectArgumentCount(3, 1), execute(test1).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 2), + CheckErrorKind::IncorrectArgumentCount(3, 2), execute(test2).unwrap_err(), ); execute(test3).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(3, 4), + CheckErrorKind::IncorrectArgumentCount(3, 4), execute(test4).unwrap_err(), ); } @@ -432,13 +435,13 @@ fn test_define_fungible_token_arg_count() { let test3 = "(define-fungible-token foo u2 u3)"; assert_eq_err( - CheckErrors::RequiresAtLeastArguments(1, 0), + CheckErrorKind::RequiresAtLeastArguments(1, 0), execute(test0).unwrap_err(), ); execute(test1).unwrap(); execute(test2).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(1, 3), + CheckErrorKind::IncorrectArgumentCount(1, 3), execute(test3).unwrap_err(), ); } @@ -451,16 +454,16 @@ fn test_define_non_fungible_token_arg_count() { let test3 = "(define-non-fungible-token foo uint uint)"; assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 0), + CheckErrorKind::IncorrectArgumentCount(2, 0), execute(test0).unwrap_err(), ); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 1), + CheckErrorKind::IncorrectArgumentCount(2, 1), execute(test1).unwrap_err(), ); execute(test2).unwrap(); assert_eq_err( - CheckErrors::IncorrectArgumentCount(2, 3), + CheckErrorKind::IncorrectArgumentCount(2, 3), execute(test3).unwrap_err(), ); } @@ -474,19 +477,19 @@ fn test_define_trait_arg_count() { // These errors are hit in the trait resolver, before reaching the type-checker match execute(test0).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::DefineTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::DefineTraitBadSignature => {} e => panic!("{e:?}"), }; match execute(test1).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::DefineTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::DefineTraitBadSignature => {} e => panic!("{e}"), }; execute(test2).unwrap(); match execute(test3).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::DefineTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::DefineTraitBadSignature => {} e => panic!("{e}"), }; } @@ -500,19 +503,19 @@ fn test_use_trait_arg_count() { // These errors are hit in the trait resolver, before reaching the type-checker match execute(test0).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::ImportTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::ImportTraitBadSignature => {} e => panic!("{e:?}"), }; match execute(test1).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::ImportTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::ImportTraitBadSignature => {} e => panic!("{e}"), }; execute(test2).unwrap(); match execute(test3).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::ImportTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::ImportTraitBadSignature => {} e => panic!("{e}"), }; } @@ -525,14 +528,14 @@ fn test_impl_trait_arg_count() { // These errors are hit in the trait resolver, before reaching the type-checker match execute(test0).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::ImplTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::ImplTraitBadSignature => {} e => panic!("{e:?}"), }; execute(test1).unwrap(); match execute(test2).unwrap_err() { - Error::Runtime(RuntimeErrorType::ASTError(parse_err), _) - if *parse_err.err == ParseErrors::ImplTraitBadSignature => {} + VmExecutionError::Runtime(RuntimeError::ASTError(parse_err), _) + if *parse_err.err == ParseErrorKind::ImplTraitBadSignature => {} e => panic!("{e}"), }; } diff --git a/clarity/src/vm/tests/principals.rs b/clarity/src/vm/tests/principals.rs index 82b427b23b1..49a3eaf86f0 100644 --- a/clarity/src/vm/tests/principals.rs +++ b/clarity/src/vm/tests/principals.rs @@ -7,7 +7,7 @@ use crate::vm::types::{ }; #[cfg(test)] use crate::vm::{ - errors::CheckErrors, + errors::CheckErrorKind, functions::principals::PrincipalConstructErrorCode, types::TypeSignature::PrincipalType, types::{ResponseData, TypeSignature, BUFF_1, BUFF_20}, @@ -25,7 +25,7 @@ fn test_simple_is_standard_check_inputs() { true ) .unwrap_err(), - CheckErrors::TypeValueError(Box::new(PrincipalType), Box::new(Value::UInt(10)),).into() + CheckErrorKind::TypeValueError(Box::new(PrincipalType), Box::new(Value::UInt(10)),).into() ); } @@ -898,14 +898,14 @@ fn test_principal_construct_version_byte_future() { } #[test] -// Test cases where the wrong type should be a `CheckErrors` error, because it should have been +// Test cases where the wrong type should be a `CheckErrorKind` error, because it should have been // caught by the type checker. fn test_principal_construct_check_errors() { // The version bytes 0x5904934 are invalid. Should have been caught by type checker so use - // `CheckErrors`. + // `CheckErrorKind`. let input = r#"(principal-construct? 0x590493 0x0102030405060708091011121314151617181920)"#; assert_eq!( - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(BUFF_1.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("590493").unwrap() @@ -921,11 +921,11 @@ fn test_principal_construct_check_errors() { ); // u22 is not a byte buffer, so is invalid. Should have been caught by type checker so use - // `CheckErrors`. + // `CheckErrorKind`. let input = r#"(principal-construct? u22 0x0102030405060708091011121314151617181920)"#; assert_eq!( Err( - CheckErrors::TypeValueError(Box::new(BUFF_1.clone()), Box::new(Value::UInt(22)),) + CheckErrorKind::TypeValueError(Box::new(BUFF_1.clone()), Box::new(Value::UInt(22)),) .into() ), execute_with_parameters( @@ -936,7 +936,7 @@ fn test_principal_construct_check_errors() { ) ); - // Hash key part is too large, should have length 20. This is a `CheckErrors` error because it + // Hash key part is too large, should have length 20. This is a `CheckErrorKind` error because it // should have been caught by the type checker. let input = r#"(principal-construct? 0x16 0x010203040506070809101112131415161718192021)"#; assert_eq!( @@ -947,7 +947,7 @@ fn test_principal_construct_check_errors() { false ) .unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(BUFF_20.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("010203040506070809101112131415161718192021").unwrap() @@ -959,7 +959,7 @@ fn test_principal_construct_check_errors() { // Name is too long, which should have been caught by the type-checker let input = r#"(principal-construct? 0x16 0x0102030405060708091011121314151617181920 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")"#; assert_eq!( - Err(CheckErrors::TypeValueError( + Err(CheckErrorKind::TypeValueError( Box::new(TypeSignature::contract_name_string_ascii_type().unwrap()), Box::new(Value::Sequence(SequenceData::String(CharType::ASCII( ASCIIData { diff --git a/clarity/src/vm/tests/representations.rs b/clarity/src/vm/tests/representations.rs index bed3ba78496..e96db9ba73f 100644 --- a/clarity/src/vm/tests/representations.rs +++ b/clarity/src/vm/tests/representations.rs @@ -17,7 +17,7 @@ use proptest::prelude::*; use proptest::string::string_regex; use stacks_common::codec::StacksMessageCodec; -use crate::vm::errors::RuntimeErrorType; +use crate::vm::errors::RuntimeError; use crate::vm::representations::{ CLARITY_NAME_REGEX_STRING, CONTRACT_MAX_NAME_LENGTH, CONTRACT_MIN_NAME_LENGTH, CONTRACT_NAME_REGEX_STRING, MAX_STRING_LEN, @@ -164,7 +164,7 @@ fn prop_clarity_name_invalid_patterns() { prop_assert!(result.is_err(), "Expected invalid name '{}' to be rejected", name); prop_assert!(matches!( result.unwrap_err(), - RuntimeErrorType::BadNameValue(_, _) + RuntimeError::BadNameValue(_, _) ), "Expected BadNameValue error for invalid name '{}'", name); }); } @@ -302,7 +302,7 @@ fn prop_contract_name_invalid_patterns() { prop_assert!(result.is_err(), "Expected invalid contract name '{}' to be rejected", name); prop_assert!(matches!( result.unwrap_err(), - RuntimeErrorType::BadNameValue(_, _) + RuntimeError::BadNameValue(_, _) ), "Expected BadNameValue error for invalid contract name '{}'", name); }); } diff --git a/clarity/src/vm/tests/sequences.rs b/clarity/src/vm/tests/sequences.rs index 3ea779b7d67..fab241d294c 100644 --- a/clarity/src/vm/tests/sequences.rs +++ b/clarity/src/vm/tests/sequences.rs @@ -22,7 +22,7 @@ use stacks_common::types::StacksEpochId; use crate::vm::tests::test_clarity_versions; #[cfg(test)] use crate::vm::{ - errors::{CheckErrors, Error, RuntimeErrorType}, + errors::{CheckErrorKind, RuntimeError, VmExecutionError}, execute, execute_v2, types::{ signatures::{ @@ -59,7 +59,7 @@ fn test_simple_list_admission() { ); let err = execute(&t3).unwrap_err(); assert!(match err { - Error::Unchecked(CheckErrors::TypeValueError(_, _)) => true, + VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(_, _)) => true, _ => { eprintln!("Expected TypeError, but found: {err:?}"); false @@ -112,16 +112,16 @@ fn test_index_of() { ]; let bad_expected = [ - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrors::TypeValueError( + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::TypeValueError( Box::new(TypeSignature::min_buffer().unwrap()), Box::new(execute("\"a\"").unwrap().unwrap()), ), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(TypeSignature::min_string_utf8().unwrap()), Box::new(execute("\"a\"").unwrap().unwrap()), ), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(TypeSignature::min_string_ascii().unwrap()), Box::new(execute("u\"a\"").unwrap().unwrap()), ), @@ -129,7 +129,7 @@ fn test_index_of() { for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { match execute(bad_test).unwrap_err() { - Error::Unchecked(check_error) => { + VmExecutionError::Unchecked(check_error) => { assert_eq!(&check_error, expected); } _ => unreachable!("Should have raised unchecked errors"), @@ -173,13 +173,13 @@ fn test_element_at() { let bad = ["(element-at 3 u1)", "(element-at (list 1 2 3) 1)"]; let bad_expected = [ - CheckErrors::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrors::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(Value::Int(1))), + CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + CheckErrorKind::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(Value::Int(1))), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { match execute(bad_test).unwrap_err() { - Error::Unchecked(check_error) => { + VmExecutionError::Unchecked(check_error) => { assert_eq!(&check_error, expected); } _ => unreachable!("Should have raised unchecked errors"), @@ -451,7 +451,7 @@ fn test_simple_map_append() { assert_eq!( execute("(append (append (list) 1) u2)").unwrap_err(), - CheckErrors::TypeValueError(Box::new(IntType), Box::new(Value::UInt(2))).into() + CheckErrorKind::TypeValueError(Box::new(IntType), Box::new(Value::UInt(2))).into() ); } @@ -587,17 +587,17 @@ fn test_simple_list_concat() { assert_eq!( execute("(concat (list 1) (list u4 u8))").unwrap_err(), - CheckErrors::TypeError(Box::new(IntType), Box::new(UIntType)).into() + CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)).into() ); assert_eq!( execute("(concat (list 1) 3)").unwrap_err(), - RuntimeErrorType::BadTypeConstruction.into() + RuntimeError::BadTypeConstruction.into() ); assert_eq!( execute("(concat (list 1) \"1\")").unwrap_err(), - RuntimeErrorType::BadTypeConstruction.into() + RuntimeError::BadTypeConstruction.into() ); } @@ -623,12 +623,12 @@ fn test_simple_buff_concat() { assert_eq!( execute("(concat 0x31 3)").unwrap_err(), - RuntimeErrorType::BadTypeConstruction.into() + RuntimeError::BadTypeConstruction.into() ); assert_eq!( execute("(concat 0x31 (list 1))").unwrap_err(), - RuntimeErrorType::BadTypeConstruction.into() + RuntimeError::BadTypeConstruction.into() ); } @@ -710,25 +710,26 @@ fn test_simple_list_replace_at() { // The sequence input has the wrong type assert_eq!( execute_v2("(replace-at? 0 u0 (list 0))").unwrap_err(), - CheckErrors::ExpectedSequence(Box::new(IntType)).into() + CheckErrorKind::ExpectedSequence(Box::new(IntType)).into() ); // The type of the index should be uint. assert_eq!( execute_v2("(replace-at? (list 1) 0 0)").unwrap_err(), - CheckErrors::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() + CheckErrorKind::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() ); // The element input has the wrong type assert_eq!( execute_v2("(replace-at? (list 2 3) u0 true)").unwrap_err(), - CheckErrors::TypeValueError(Box::new(IntType), Box::new(Value::Bool(true))).into() + CheckErrorKind::TypeValueError(Box::new(IntType), Box::new(Value::Bool(true))).into() ); // The element input has the wrong type assert_eq!( execute_v2("(replace-at? (list 2 3) u0 0x00)").unwrap_err(), - CheckErrors::TypeValueError(Box::new(IntType), Box::new(Value::buff_from_byte(0))).into() + CheckErrorKind::TypeValueError(Box::new(IntType), Box::new(Value::buff_from_byte(0))) + .into() ); } @@ -768,20 +769,20 @@ fn test_simple_buff_replace_at() { // The sequence input has the wrong type assert_eq!( execute_v2("(replace-at? 33 u0 0x00)").unwrap_err(), - CheckErrors::ExpectedSequence(Box::new(IntType)).into() + CheckErrorKind::ExpectedSequence(Box::new(IntType)).into() ); // The type of the index should be uint. assert_eq!( execute_v2("(replace-at? 0x002244 0 0x99)").unwrap_err(), - CheckErrors::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() + CheckErrorKind::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() ); // The element input has the wrong type let buff_len = BufferLength::try_from(1u32).unwrap(); assert_eq!( execute_v2("(replace-at? 0x445522 u0 55)").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType(buff_len.clone()))), Box::new(Value::Int(55)) ) @@ -791,7 +792,7 @@ fn test_simple_buff_replace_at() { // The element input has the wrong type assert_eq!( execute_v2("(replace-at? 0x445522 u0 (list 5))").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType(buff_len.clone()))), Box::new(Value::list_from(vec![Value::Int(5)]).unwrap()) ) @@ -801,7 +802,7 @@ fn test_simple_buff_replace_at() { // The element input has the wrong type (not length 1) assert_eq!( execute_v2("(replace-at? 0x445522 u0 0x0044)").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(BufferType(buff_len))), Box::new(Value::buff_from(vec![0, 68]).unwrap()) ) @@ -845,20 +846,20 @@ fn test_simple_string_ascii_replace_at() { // The sequence input has the wrong type assert_eq!( execute_v2("(replace-at? 33 u0 \"c\")").unwrap_err(), - CheckErrors::ExpectedSequence(Box::new(IntType)).into() + CheckErrorKind::ExpectedSequence(Box::new(IntType)).into() ); // The type of the index should be uint. assert_eq!( execute_v2("(replace-at? \"abc\" 0 \"c\")").unwrap_err(), - CheckErrors::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() + CheckErrorKind::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() ); // The element input has the wrong type let buff_len = BufferLength::try_from(1u32).unwrap(); assert_eq!( execute_v2("(replace-at? \"abc\" u0 55)").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), Box::new(Value::Int(55)) ) @@ -868,7 +869,7 @@ fn test_simple_string_ascii_replace_at() { // The element input has the wrong type assert_eq!( execute_v2("(replace-at? \"abc\" u0 0x00)").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), Box::new(Value::buff_from_byte(0)) ) @@ -878,7 +879,7 @@ fn test_simple_string_ascii_replace_at() { // The element input has the wrong type assert_eq!( execute_v2("(replace-at? \"abc\" u0 \"de\")").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(SequenceType(StringType(ASCII(buff_len)))), Box::new(Value::string_ascii_from_bytes("de".into()).unwrap()) ) @@ -926,20 +927,20 @@ fn test_simple_string_utf8_replace_at() { // The sequence input has the wrong type assert_eq!( execute_v2("(replace-at? 33 u0 u\"c\")").unwrap_err(), - CheckErrors::ExpectedSequence(Box::new(IntType)).into() + CheckErrorKind::ExpectedSequence(Box::new(IntType)).into() ); // The type of the index should be uint. assert_eq!( execute_v2("(replace-at? u\"abc\" 0 u\"c\")").unwrap_err(), - CheckErrors::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() + CheckErrorKind::TypeValueError(Box::new(UIntType), Box::new(Value::Int(0))).into() ); // The element input has the wrong type let str_len = StringUTF8Length::try_from(1u32).unwrap(); assert_eq!( execute_v2("(replace-at? u\"abc\" u0 55)").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(TypeSignature::SequenceType(StringType( StringSubtype::UTF8(str_len.clone()) ))), @@ -951,7 +952,7 @@ fn test_simple_string_utf8_replace_at() { // The element input has the wrong type assert_eq!( execute_v2("(replace-at? u\"abc\" u0 0x00)").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(TypeSignature::SequenceType(StringType( StringSubtype::UTF8(str_len.clone()) ))), @@ -963,7 +964,7 @@ fn test_simple_string_utf8_replace_at() { // The element input has the wrong type assert_eq!( execute_v2("(replace-at? u\"abc\" u0 u\"de\")").unwrap_err(), - CheckErrors::TypeValueError( + CheckErrorKind::TypeValueError( Box::new(TypeSignature::SequenceType(StringType( StringSubtype::UTF8(str_len) ))), @@ -993,22 +994,22 @@ fn test_simple_buff_assert_max_len() { assert_eq!( execute("(as-max-len? 0x313233)").unwrap_err(), - CheckErrors::IncorrectArgumentCount(2, 1).into() + CheckErrorKind::IncorrectArgumentCount(2, 1).into() ); assert_eq!( execute("(as-max-len? 0x313233 3)").unwrap_err(), - CheckErrors::TypeError(Box::new(UIntType), Box::new(IntType)).into() + CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)).into() ); assert_eq!( execute("(as-max-len? 1 u3)").unwrap_err(), - CheckErrors::ExpectedSequence(Box::new(IntType)).into() + CheckErrorKind::ExpectedSequence(Box::new(IntType)).into() ); assert_eq!( execute("(as-max-len? 0x313233 0x31)").unwrap_err(), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(UIntType), Box::new(SequenceType(SequenceSubtype::BufferType( 1_u32.try_into().unwrap() @@ -1175,14 +1176,14 @@ fn test_construct_bad_list(#[case] version: ClarityVersion, #[case] epoch: Stack let test1 = "(list 1 2 3 true)"; assert_eq!( execute(test1).unwrap_err(), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)).into() + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)).into() ); let test2 = "(define-private (bad-function (x int)) (if (is-eq x 1) true x)) (map bad-function (list 0 1 2 3))"; assert_eq!( execute(test2).unwrap_err(), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)).into() + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)).into() ); let bad_2d_list = "(list (list 1 2 3) (list true false true))"; @@ -1190,11 +1191,11 @@ fn test_construct_bad_list(#[case] version: ClarityVersion, #[case] epoch: Stack assert_eq!( execute(bad_2d_list).unwrap_err(), - CheckErrors::TypeError(Box::new(IntType), Box::new(BoolType)).into() + CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)).into() ); assert_eq!( execute(bad_high_order_list).unwrap_err(), - CheckErrors::TypeError( + CheckErrorKind::TypeError( Box::new(IntType), Box::new(TypeSignature::from_string("(list 3 int)", version, epoch)) ) @@ -1205,23 +1206,23 @@ fn test_construct_bad_list(#[case] version: ClarityVersion, #[case] epoch: Stack #[test] fn test_eval_func_arg_panic() { let test1 = "(fold (lambda (x y) (* x y)) (list 1 2 3 4) 1)"; - let e: Error = CheckErrors::ExpectedName.into(); + let e: VmExecutionError = CheckErrorKind::ExpectedName.into(); assert_eq!(e, execute(test1).unwrap_err()); let test2 = "(map (lambda (x) (* x x)) (list 1 2 3 4))"; - let e: Error = CheckErrors::ExpectedName.into(); + let e: VmExecutionError = CheckErrorKind::ExpectedName.into(); assert_eq!(e, execute(test2).unwrap_err()); let test3 = "(map square (list 1 2 3 4) 2)"; - let e: Error = CheckErrors::UndefinedFunction("square".to_string()).into(); + let e: VmExecutionError = CheckErrorKind::UndefinedFunction("square".to_string()).into(); assert_eq!(e, execute(test3).unwrap_err()); let test4 = "(define-private (multiply-all (x int) (acc int)) (* x acc)) (fold multiply-all (list 1 2 3 4))"; - let e: Error = CheckErrors::IncorrectArgumentCount(3, 2).into(); + let e: VmExecutionError = CheckErrorKind::IncorrectArgumentCount(3, 2).into(); assert_eq!(e, execute(test4).unwrap_err()); let test5 = "(map + (list 1 2 3 4) 2)"; - let e: Error = CheckErrors::ExpectedSequence(Box::new(IntType)).into(); + let e: VmExecutionError = CheckErrorKind::ExpectedSequence(Box::new(IntType)).into(); assert_eq!(e, execute(test5).unwrap_err()); } diff --git a/clarity/src/vm/tests/simple_apply_eval.rs b/clarity/src/vm/tests/simple_apply_eval.rs index 6bb533e9c72..d798c83baa3 100644 --- a/clarity/src/vm/tests/simple_apply_eval.rs +++ b/clarity/src/vm/tests/simple_apply_eval.rs @@ -31,7 +31,7 @@ use crate::vm::callables::DefinedFunction; use crate::vm::contexts::OwnedEnvironment; use crate::vm::costs::LimitedCostTracker; use crate::vm::database::MemoryBackingStore; -use crate::vm::errors::{CheckErrors, Error, RuntimeErrorType, ShortReturnType}; +use crate::vm::errors::{CheckErrorKind, EarlyReturnError, RuntimeError, VmExecutionError}; use crate::vm::tests::{execute, test_clarity_versions}; use crate::vm::types::signatures::*; use crate::vm::types::{ @@ -55,7 +55,7 @@ fn test_doubly_defined_persisted_vars() { for p in tests.iter() { assert_eq!( vm_execute(p).unwrap_err(), - CheckErrors::NameAlreadyUsed("cursor".into()).into() + CheckErrorKind::NameAlreadyUsed("cursor".into()).into() ); } } @@ -576,19 +576,19 @@ fn test_secp256k1_errors() { "(principal-of?)", ]; - let expectations: &[Error] = &[ - CheckErrors::TypeValueError(Box::new(BUFF_32.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("de5b9eb9e7c5592930eb2e30a01369c36586d872082ed8181ee83d2a0ec20f").unwrap() })))).into(), - CheckErrors::TypeValueError(Box::new(BUFF_65.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("8738487ebe69b93d8e51583be8eee50bb4213fc49c767d329632730cc193b873554428fc936ca3569afc15f1c9365f6591d6251a89fee9c9ac661116824d3a130100").unwrap() })))).into(), - CheckErrors::IncorrectArgumentCount(2, 1).into(), - CheckErrors::IncorrectArgumentCount(2, 3).into(), + let expectations: &[VmExecutionError] = &[ + CheckErrorKind::TypeValueError(Box::new(BUFF_32.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("de5b9eb9e7c5592930eb2e30a01369c36586d872082ed8181ee83d2a0ec20f").unwrap() })))).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_65.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("8738487ebe69b93d8e51583be8eee50bb4213fc49c767d329632730cc193b873554428fc936ca3569afc15f1c9365f6591d6251a89fee9c9ac661116824d3a130100").unwrap() })))).into(), + CheckErrorKind::IncorrectArgumentCount(2, 1).into(), + CheckErrorKind::IncorrectArgumentCount(2, 3).into(), - CheckErrors::TypeValueError(Box::new(BUFF_32.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("de5b9eb9e7c5592930eb2e30a01369c36586d872082ed8181ee83d2a0ec20f").unwrap() })))).into(), - CheckErrors::TypeValueError(Box::new(BUFF_65.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("8738487ebe69b93d8e51583be8eee50bb4213fc49c767d329632730cc193b873554428fc936ca3569afc15f1c9365f6591d6251a89fee9c9ac661116824d3a130111").unwrap() })))).into(), - CheckErrors::TypeValueError(Box::new(BUFF_33.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("03adb8de4bfb65db2cfd6120d55c6526ae9c52e675db7e47308636534ba7").unwrap() })))).into(), - CheckErrors::IncorrectArgumentCount(3, 2).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_32.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("de5b9eb9e7c5592930eb2e30a01369c36586d872082ed8181ee83d2a0ec20f").unwrap() })))).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_65.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("8738487ebe69b93d8e51583be8eee50bb4213fc49c767d329632730cc193b873554428fc936ca3569afc15f1c9365f6591d6251a89fee9c9ac661116824d3a130111").unwrap() })))).into(), + CheckErrorKind::TypeValueError(Box::new(BUFF_33.clone()), Box::new(Value::Sequence(SequenceData::Buffer(BuffData { data: hex_bytes("03adb8de4bfb65db2cfd6120d55c6526ae9c52e675db7e47308636534ba7").unwrap() })))).into(), + CheckErrorKind::IncorrectArgumentCount(3, 2).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::IncorrectArgumentCount(1, 0).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::IncorrectArgumentCount(1, 0).into(), ]; for (program, expectation) in secp256k1_evals.iter().zip(expectations.iter()) { @@ -873,8 +873,8 @@ fn test_sequence_comparisons_clarity1() { "(>= \"baa\" \"aaa\")", "(<= \"baa\" \"aaa\")", ]; - let error_expectations: &[Error] = &[ - CheckErrors::UnionTypeValueError( + let error_expectations: &[VmExecutionError] = &[ + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Sequence(SequenceData::String(CharType::ASCII( ASCIIData { @@ -883,7 +883,7 @@ fn test_sequence_comparisons_clarity1() { )))), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Sequence(SequenceData::String(CharType::ASCII( ASCIIData { @@ -892,7 +892,7 @@ fn test_sequence_comparisons_clarity1() { )))), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Sequence(SequenceData::String(CharType::ASCII( ASCIIData { @@ -901,7 +901,7 @@ fn test_sequence_comparisons_clarity1() { )))), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Sequence(SequenceData::String(CharType::ASCII( ASCIIData { @@ -984,13 +984,13 @@ fn test_sequence_comparisons_clarity2() { fn test_sequence_comparisons_mismatched_types() { // Tests that comparing objects of different types results in an error in Clarity1. let error_tests = ["(> 0 u1)", "(< 0 u1)"]; - let v1_error_expectations: &[Error] = &[ - CheckErrors::UnionTypeValueError( + let v1_error_expectations: &[VmExecutionError] = &[ + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Int(0)), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::Int(0)), ) @@ -1005,8 +1005,8 @@ fn test_sequence_comparisons_mismatched_types() { assert_eq!(*expectation, vm_execute(program).unwrap_err()) }); - let v2_error_expectations: &[Error] = &[ - CheckErrors::UnionTypeValueError( + let v2_error_expectations: &[VmExecutionError] = &[ + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1017,7 +1017,7 @@ fn test_sequence_comparisons_mismatched_types() { Box::new(Value::Int(0)), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1039,8 +1039,8 @@ fn test_sequence_comparisons_mismatched_types() { // Tests that comparing objects of different types results in an error in Clarity2. let error_tests = ["(> \"baa\" u\"aaa\")", "(> \"baa\" 0x0001)"]; - let error_expectations: &[Error] = &[ - CheckErrors::UnionTypeValueError( + let error_expectations: &[VmExecutionError] = &[ + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1055,7 +1055,7 @@ fn test_sequence_comparisons_mismatched_types() { )))), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1108,39 +1108,35 @@ fn test_simple_arithmetic_errors(#[case] version: ClarityVersion, #[case] epoch: "(is-eq (some 1) (some true))", ]; - let expectations: &[Error] = &[ - CheckErrors::IncorrectArgumentCount(2, 1).into(), - CheckErrors::TypeValueError( + let expectations: &[VmExecutionError] = &[ + CheckErrorKind::IncorrectArgumentCount(2, 1).into(), + CheckErrorKind::TypeValueError( Box::new(TypeSignature::IntType), Box::new(Value::Bool(true)), ) .into(), - RuntimeErrorType::DivisionByZero.into(), - RuntimeErrorType::DivisionByZero.into(), - RuntimeErrorType::ArithmeticOverflow.into(), - RuntimeErrorType::ArithmeticOverflow.into(), - RuntimeErrorType::ArithmeticOverflow.into(), - RuntimeErrorType::ArithmeticUnderflow.into(), - CheckErrors::IncorrectArgumentCount(1, 0).into(), - CheckErrors::IncorrectArgumentCount(1, 0).into(), - CheckErrors::IncorrectArgumentCount(2, 1).into(), - CheckErrors::IncorrectArgumentCount(2, 1).into(), - CheckErrors::IncorrectArgumentCount(1, 0).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - RuntimeErrorType::Arithmetic("sqrti must be passed a positive integer".to_string()).into(), - CheckErrors::IncorrectArgumentCount(1, 0).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - RuntimeErrorType::Arithmetic("log2 must be passed a positive integer".to_string()).into(), - CheckErrors::IncorrectArgumentCount(2, 1).into(), - RuntimeErrorType::Arithmetic( - "Power argument to (pow ...) must be a u32 integer".to_string(), - ) - .into(), - RuntimeErrorType::Arithmetic( - "Power argument to (pow ...) must be a u32 integer".to_string(), - ) - .into(), - CheckErrors::TypeError( + RuntimeError::DivisionByZero.into(), + RuntimeError::DivisionByZero.into(), + RuntimeError::ArithmeticOverflow.into(), + RuntimeError::ArithmeticOverflow.into(), + RuntimeError::ArithmeticOverflow.into(), + RuntimeError::ArithmeticUnderflow.into(), + CheckErrorKind::IncorrectArgumentCount(1, 0).into(), + CheckErrorKind::IncorrectArgumentCount(1, 0).into(), + CheckErrorKind::IncorrectArgumentCount(2, 1).into(), + CheckErrorKind::IncorrectArgumentCount(2, 1).into(), + CheckErrorKind::IncorrectArgumentCount(1, 0).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + RuntimeError::Arithmetic("sqrti must be passed a positive integer".to_string()).into(), + CheckErrorKind::IncorrectArgumentCount(1, 0).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + RuntimeError::Arithmetic("log2 must be passed a positive integer".to_string()).into(), + CheckErrorKind::IncorrectArgumentCount(2, 1).into(), + RuntimeError::Arithmetic("Power argument to (pow ...) must be a u32 integer".to_string()) + .into(), + RuntimeError::Arithmetic("Power argument to (pow ...) must be a u32 integer".to_string()) + .into(), + CheckErrorKind::TypeError( Box::new(TypeSignature::from_string("bool", version, epoch)), Box::new(TypeSignature::from_string("int", version, epoch)), ) @@ -1163,18 +1159,18 @@ fn test_unsigned_arithmetic() { "(to-int (pow u2 u127))", ]; - let expectations: &[Error] = &[ - RuntimeErrorType::ArithmeticUnderflow.into(), - RuntimeErrorType::ArithmeticUnderflow.into(), - CheckErrors::UnionTypeValueError( + let expectations: &[VmExecutionError] = &[ + RuntimeError::ArithmeticUnderflow.into(), + RuntimeError::ArithmeticUnderflow.into(), + CheckErrorKind::UnionTypeValueError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(Value::UInt(10)), ) .into(), - CheckErrors::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(Value::Int(80))) + CheckErrorKind::TypeValueError(Box::new(TypeSignature::UIntType), Box::new(Value::Int(80))) .into(), - RuntimeErrorType::ArithmeticUnderflow.into(), - RuntimeErrorType::ArithmeticOverflow.into(), + RuntimeError::ArithmeticUnderflow.into(), + RuntimeError::ArithmeticOverflow.into(), ]; for (program, expectation) in tests.iter().zip(expectations.iter()) { @@ -1202,22 +1198,22 @@ fn test_options_errors() { "(get field-0 1)", ]; - let expectations: &[Error] = &[ - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::ExpectedOptionalValue(Box::new(Value::Bool(true))).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::ExpectedResponseValue(Box::new(Value::Bool(true))).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::ExpectedResponseValue(Box::new(Value::Bool(true))).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::ExpectedOptionalValue(Box::new(Value::Bool(true))).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::IncorrectArgumentCount(2, 3).into(), - CheckErrors::ExpectedOptionalValue(Box::new(Value::Bool(true))).into(), - CheckErrors::ExpectedTuple(Box::new(TypeSignature::IntType)).into(), - CheckErrors::ExpectedTuple(Box::new(TypeSignature::IntType)).into(), + let expectations: &[VmExecutionError] = &[ + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::ExpectedOptionalValue(Box::new(Value::Bool(true))).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::ExpectedResponseValue(Box::new(Value::Bool(true))).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::ExpectedResponseValue(Box::new(Value::Bool(true))).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::ExpectedOptionalValue(Box::new(Value::Bool(true))).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::IncorrectArgumentCount(2, 3).into(), + CheckErrorKind::ExpectedOptionalValue(Box::new(Value::Bool(true))).into(), + CheckErrorKind::ExpectedTuple(Box::new(TypeSignature::IntType)).into(), + CheckErrorKind::ExpectedTuple(Box::new(TypeSignature::IntType)).into(), ]; for (program, expectation) in tests.iter().zip(expectations.iter()) { @@ -1240,17 +1236,17 @@ fn test_stx_ops_errors() { "(stx-burn? 4 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)", ]; - let expectations: &[Error] = &[ - CheckErrors::IncorrectArgumentCount(3, 2).into(), - CheckErrors::BadTransferSTXArguments.into(), - CheckErrors::BadTransferSTXArguments.into(), - CheckErrors::BadTransferSTXArguments.into(), - CheckErrors::IncorrectArgumentCount(4, 3).into(), - CheckErrors::BadTransferSTXArguments.into(), - CheckErrors::BadTransferSTXArguments.into(), - CheckErrors::BadTransferSTXArguments.into(), - CheckErrors::IncorrectArgumentCount(2, 1).into(), - CheckErrors::BadTransferSTXArguments.into(), + let expectations: &[VmExecutionError] = &[ + CheckErrorKind::IncorrectArgumentCount(3, 2).into(), + CheckErrorKind::BadTransferSTXArguments.into(), + CheckErrorKind::BadTransferSTXArguments.into(), + CheckErrorKind::BadTransferSTXArguments.into(), + CheckErrorKind::IncorrectArgumentCount(4, 3).into(), + CheckErrorKind::BadTransferSTXArguments.into(), + CheckErrorKind::BadTransferSTXArguments.into(), + CheckErrorKind::BadTransferSTXArguments.into(), + CheckErrorKind::IncorrectArgumentCount(2, 1).into(), + CheckErrorKind::BadTransferSTXArguments.into(), ]; for (program, expectation) in tests.iter().zip(expectations.iter()) { @@ -1313,7 +1309,7 @@ fn test_bitwise() { "(bit-shift-left -64 u121)", // -170141183460469231731687303715884105728 ]; - let expectations: &[Result] = &[ + let expectations: &[Result] = &[ Ok(Value::Int(16)), // (bit-and 24 16) Ok(Value::UInt(16)), // (bit-and u24 u16) Ok(Value::Int(28)), // (bit-xor 24 4)y @@ -1418,33 +1414,33 @@ fn test_option_destructs() { "(try! 1)", ]; - let expectations: &[Result] = &[ + let expectations: &[Result] = &[ Ok(Value::Int(1)), Ok(Value::Int(1)), Err( - CheckErrors::ExpectedResponseValue(Box::new(Value::some(Value::Int(2)).unwrap())) + CheckErrorKind::ExpectedResponseValue(Box::new(Value::some(Value::Int(2)).unwrap())) .into(), ), Ok(Value::Int(3)), - Err(ShortReturnType::ExpectedValue(Box::new(Value::Int(2))).into()), + Err(EarlyReturnError::UnwrapFailed(Box::new(Value::Int(2))).into()), Ok(Value::Int(3)), Ok(Value::Int(3)), Ok(Value::Int(3)), - Err(RuntimeErrorType::UnwrapFailure.into()), - Err(RuntimeErrorType::UnwrapFailure.into()), - Err(RuntimeErrorType::UnwrapFailure.into()), + Err(RuntimeError::UnwrapFailure.into()), + Err(RuntimeError::UnwrapFailure.into()), + Err(RuntimeError::UnwrapFailure.into()), Ok(Value::Int(2)), Ok(Value::Int(9)), Ok(Value::Int(2)), Ok(Value::Int(8)), - Err(CheckErrors::BadMatchInput(Box::new(TypeSignature::IntType)).into()), - Err(CheckErrors::BadMatchInput(Box::new(TypeSignature::IntType)).into()), - Err(ShortReturnType::ExpectedValue(Box::new(Value::error(Value::UInt(1)).unwrap())).into()), + Err(CheckErrorKind::BadMatchInput(Box::new(TypeSignature::IntType)).into()), + Err(CheckErrorKind::BadMatchInput(Box::new(TypeSignature::IntType)).into()), + Err(EarlyReturnError::UnwrapFailed(Box::new(Value::error(Value::UInt(1)).unwrap())).into()), Ok(Value::Int(3)), - Err(ShortReturnType::ExpectedValue(Box::new(Value::none())).into()), + Err(EarlyReturnError::UnwrapFailed(Box::new(Value::none())).into()), Ok(Value::Bool(true)), - Err(CheckErrors::IncorrectArgumentCount(1, 2).into()), - Err(CheckErrors::ExpectedOptionalOrResponseValue(Box::new(Value::Int(1))).into()), + Err(CheckErrorKind::IncorrectArgumentCount(1, 2).into()), + Err(CheckErrorKind::ExpectedOptionalOrResponseValue(Box::new(Value::Int(1))).into()), ]; for (program, expectation) in tests.iter().zip(expectations.iter()) { @@ -1467,11 +1463,11 @@ fn test_hash_errors() { "(sha512/256 1 2)", ]; - let expectations: &[Error] = &[ - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::UnionTypeValueError( + let expectations: &[VmExecutionError] = &[ + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1480,7 +1476,7 @@ fn test_hash_errors() { Box::new(Value::Bool(true)), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1489,7 +1485,7 @@ fn test_hash_errors() { Box::new(Value::Bool(true)), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1498,7 +1494,7 @@ fn test_hash_errors() { Box::new(Value::Bool(true)), ) .into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1507,8 +1503,8 @@ fn test_hash_errors() { Box::new(Value::Bool(true)), ) .into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), - CheckErrors::UnionTypeValueError( + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::UnionTypeValueError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -1517,7 +1513,7 @@ fn test_hash_errors() { Box::new(Value::Bool(true)), ) .into(), - CheckErrors::IncorrectArgumentCount(1, 2).into(), + CheckErrorKind::IncorrectArgumentCount(1, 2).into(), ]; for (program, expectation) in tests.iter().zip(expectations.iter()) { @@ -1568,13 +1564,13 @@ fn test_bad_lets() { "(let ((false 1)) false)", ]; - let expectations: &[Error] = &[ - CheckErrors::NameAlreadyUsed("tx-sender".to_string()).into(), - CheckErrors::NameAlreadyUsed("*".to_string()).into(), - CheckErrors::NameAlreadyUsed("a".to_string()).into(), - CheckErrors::NoSuchDataVariable("cursor".to_string()).into(), - CheckErrors::NameAlreadyUsed("true".to_string()).into(), - CheckErrors::NameAlreadyUsed("false".to_string()).into(), + let expectations: &[VmExecutionError] = &[ + CheckErrorKind::NameAlreadyUsed("tx-sender".to_string()).into(), + CheckErrorKind::NameAlreadyUsed("*".to_string()).into(), + CheckErrorKind::NameAlreadyUsed("a".to_string()).into(), + CheckErrorKind::NoSuchDataVariable("cursor".to_string()).into(), + CheckErrorKind::NameAlreadyUsed("true".to_string()).into(), + CheckErrorKind::NameAlreadyUsed("false".to_string()).into(), ]; tests @@ -1669,11 +1665,11 @@ fn test_asserts_short_circuit() { "(begin (asserts! (is-eq 1 1) (err 0)) (asserts! (is-eq 2 1) (err 1)) (ok 2))", ]; - let expectations: &[Error] = &[ - Error::ShortReturn(ShortReturnType::AssertionFailed(Box::new( + let expectations: &[VmExecutionError] = &[ + VmExecutionError::EarlyReturn(EarlyReturnError::AssertionFailed(Box::new( Value::error(Value::Int(0)).unwrap(), ))), - Error::ShortReturn(ShortReturnType::AssertionFailed(Box::new( + VmExecutionError::EarlyReturn(EarlyReturnError::AssertionFailed(Box::new( Value::error(Value::Int(1)).unwrap(), ))), ]; diff --git a/clarity/src/vm/tests/traits.rs b/clarity/src/vm/tests/traits.rs index a01fa11bf0a..bc612613144 100644 --- a/clarity/src/vm/tests/traits.rs +++ b/clarity/src/vm/tests/traits.rs @@ -21,7 +21,7 @@ use super::MemoryEnvironmentGenerator; use crate::vm::tests::{test_clarity_versions, test_epochs}; #[cfg(test)] use crate::vm::{ - errors::{CheckErrors, Error}, + errors::{CheckErrorKind, VmExecutionError}, tests::{env_factory, execute, symbols_from_values}, types::{PrincipalData, QualifiedContractIdentifier, Value}, version::ClarityVersion, @@ -242,7 +242,7 @@ fn test_dynamic_dispatch_intra_contract_call( ) .unwrap_err(); match err_result { - Error::Unchecked(CheckErrors::CircularReference(_)) => {} + VmExecutionError::Unchecked(CheckErrorKind::CircularReference(_)) => {} _ => panic!("{err_result:?}"), } } @@ -557,7 +557,7 @@ fn test_dynamic_dispatch_mismatched_args( ) .unwrap_err(); match err_result { - Error::Unchecked(CheckErrors::BadTraitImplementation(_, _)) => {} + VmExecutionError::Unchecked(CheckErrorKind::BadTraitImplementation(_, _)) => {} _ => panic!("{err_result:?}"), } } @@ -612,7 +612,7 @@ fn test_dynamic_dispatch_mismatched_returned( ) .unwrap_err(); match err_result { - Error::Unchecked(CheckErrors::ReturnTypesMustMatch(_, _)) => {} + VmExecutionError::Unchecked(CheckErrorKind::ReturnTypesMustMatch(_, _)) => {} _ => panic!("{err_result:?}"), } } @@ -670,7 +670,7 @@ fn test_reentrant_dynamic_dispatch( ) .unwrap_err(); match err_result { - Error::Unchecked(CheckErrors::CircularReference(_)) => {} + VmExecutionError::Unchecked(CheckErrorKind::CircularReference(_)) => {} _ => panic!("{err_result:?}"), } } @@ -725,7 +725,7 @@ fn test_readwrite_dynamic_dispatch( ) .unwrap_err(); match err_result { - Error::Unchecked(CheckErrors::TraitBasedContractCallInReadOnly) => {} + VmExecutionError::Unchecked(CheckErrorKind::TraitBasedContractCallInReadOnly) => {} _ => panic!("{err_result:?}"), } } @@ -780,7 +780,7 @@ fn test_readwrite_violation_dynamic_dispatch( ) .unwrap_err(); match err_result { - Error::Unchecked(CheckErrors::TraitBasedContractCallInReadOnly) => {} + VmExecutionError::Unchecked(CheckErrorKind::TraitBasedContractCallInReadOnly) => {} _ => panic!("{err_result:?}"), } } diff --git a/clarity/src/vm/tests/variables.rs b/clarity/src/vm/tests/variables.rs index 7ce50958465..80449dd69e3 100644 --- a/clarity/src/vm/tests/variables.rs +++ b/clarity/src/vm/tests/variables.rs @@ -25,7 +25,7 @@ use crate::vm::{ analysis::type_checker::v2_1::tests::contracts::type_check_version, ast::parse, database::MemoryBackingStore, - errors::{CheckErrors, Error}, + errors::{CheckErrorKind, VmExecutionError}, tests::{tl_env_factory, TopLevelMemoryEnvironmentGenerator}, types::{PrincipalData, QualifiedContractIdentifier, Value}, ClarityVersion, ContractContext, @@ -54,7 +54,7 @@ fn test_block_height( if version >= ClarityVersion::Clarity3 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrors::UndefinedVariable("block-height".to_string()), + CheckErrorKind::UndefinedVariable("block-height".to_string()), *err.err ); } else { @@ -80,7 +80,9 @@ fn test_block_height( if version >= ClarityVersion::Clarity3 { let err = eval_result.unwrap_err(); assert_eq!( - Error::Unchecked(CheckErrors::UndefinedVariable("block-height".to_string(),)), + VmExecutionError::Unchecked(CheckErrorKind::UndefinedVariable( + "block-height".to_string(), + )), err ); } else { @@ -111,7 +113,7 @@ fn test_stacks_block_height( if version < ClarityVersion::Clarity3 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrors::UndefinedVariable("stacks-block-height".to_string()), + CheckErrorKind::UndefinedVariable("stacks-block-height".to_string()), *err.err ); } else { @@ -137,7 +139,7 @@ fn test_stacks_block_height( if version < ClarityVersion::Clarity3 { let err = eval_result.unwrap_err(); assert_eq!( - Error::Unchecked(CheckErrors::UndefinedVariable( + VmExecutionError::Unchecked(CheckErrorKind::UndefinedVariable( "stacks-block-height".to_string(), )), err @@ -170,7 +172,7 @@ fn test_tenure_height( if version < ClarityVersion::Clarity3 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrors::UndefinedVariable("tenure-height".to_string()), + CheckErrorKind::UndefinedVariable("tenure-height".to_string()), *err.err ); } else { @@ -196,7 +198,9 @@ fn test_tenure_height( if version < ClarityVersion::Clarity3 { let err = eval_result.unwrap_err(); assert_eq!( - Error::Unchecked(CheckErrors::UndefinedVariable("tenure-height".to_string(),)), + VmExecutionError::Unchecked(CheckErrorKind::UndefinedVariable( + "tenure-height".to_string(), + )), err ); } else { @@ -223,7 +227,7 @@ fn expect_contract_error( expected_errors: &[( WhenError, fn(ClarityVersion, StacksEpochId) -> bool, - CheckErrors, + CheckErrorKind, )], expected_success: Value, ) { @@ -269,7 +273,7 @@ fn expect_contract_error( for (when, err_condition, expected_error) in expected_errors { if *when == WhenError::Initialization && err_condition(version, epoch) { let err = init_result.unwrap_err(); - if let Error::Unchecked(inner_err) = &err { + if let VmExecutionError::Unchecked(inner_err) = &err { assert_eq!(expected_error, inner_err); } else { panic!("Expected an Unchecked error, but got a different error"); @@ -288,7 +292,7 @@ fn expect_contract_error( for (when, err_condition, expected_error) in expected_errors { if *when == WhenError::Runtime && err_condition(version, epoch) { let err = eval_result.unwrap_err(); - if let Error::Unchecked(inner_err) = &err { + if let VmExecutionError::Unchecked(inner_err) = &err { assert_eq!(expected_error, inner_err); } else { panic!("Expected an Unchecked error, but got a different error"); @@ -324,12 +328,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::UInt(1234), @@ -351,12 +355,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Bool(true), @@ -379,12 +383,12 @@ fn reuse_block_height( ( WhenError::Runtime, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Int(32), @@ -410,12 +414,12 @@ fn reuse_block_height( ( WhenError::Runtime, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Int(3), @@ -435,12 +439,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Bool(true), @@ -460,12 +464,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::UInt(1234), @@ -485,12 +489,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Bool(false), @@ -525,12 +529,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Bool(false), @@ -550,12 +554,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Bool(false), @@ -575,12 +579,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Bool(true), @@ -600,12 +604,12 @@ fn reuse_block_height( ( WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("block-height".to_string()), ), ( WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::ReservedWord("block-height".to_string()), + CheckErrorKind::ReservedWord("block-height".to_string()), ), ], Value::Bool(true), @@ -633,7 +637,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::UInt(1234), ); @@ -653,7 +657,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Bool(true), ); @@ -674,7 +678,7 @@ fn reuse_stacks_block_height( &[( WhenError::Runtime, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Int(32), ); @@ -698,7 +702,7 @@ fn reuse_stacks_block_height( &[( WhenError::Runtime, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Int(3), ); @@ -716,7 +720,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Bool(true), ); @@ -734,7 +738,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::UInt(1234), ); @@ -752,7 +756,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Bool(false), ); @@ -785,7 +789,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Bool(false), ); @@ -803,7 +807,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Bool(false), ); @@ -821,7 +825,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Bool(true), ); @@ -839,7 +843,7 @@ fn reuse_stacks_block_height( &[( WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrors::NameAlreadyUsed("stacks-block-height".to_string()), + CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), )], Value::Bool(true), ); @@ -870,7 +874,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::UInt(1234), ); @@ -892,7 +896,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Bool(true), ); @@ -915,7 +919,7 @@ fn reuse_builtin_name( &[( WhenError::Runtime, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Int(32), ); @@ -941,7 +945,7 @@ fn reuse_builtin_name( &[( WhenError::Runtime, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Int(3), ); @@ -961,7 +965,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Bool(true), ); @@ -981,7 +985,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::UInt(1234), ); @@ -1001,7 +1005,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Bool(false), ); @@ -1038,7 +1042,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Bool(false), ); @@ -1058,7 +1062,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Bool(false), ); @@ -1078,7 +1082,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Bool(true), ); @@ -1098,7 +1102,7 @@ fn reuse_builtin_name( &[( WhenError::Initialization, version_check, - CheckErrors::NameAlreadyUsed(name.to_string()), + CheckErrorKind::NameAlreadyUsed(name.to_string()), )], Value::Bool(true), ); @@ -1129,7 +1133,7 @@ fn test_block_time( if version < ClarityVersion::Clarity4 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrors::UndefinedVariable("block-time".to_string()), + CheckErrorKind::UndefinedVariable("block-time".to_string()), *err.err ); } else { @@ -1156,7 +1160,9 @@ fn test_block_time( if version < ClarityVersion::Clarity4 { let err = eval_result.unwrap_err(); assert_eq!( - Error::Unchecked(CheckErrors::UndefinedVariable("block-time".to_string(),)), + VmExecutionError::Unchecked(CheckErrorKind::UndefinedVariable( + "block-time".to_string(), + )), err ); } else { @@ -1254,7 +1260,7 @@ fn test_current_contract( if version < ClarityVersion::Clarity4 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrors::UndefinedVariable("current-contract".to_string()), + CheckErrorKind::UndefinedVariable("current-contract".to_string()), *err.err ); } else { @@ -1280,7 +1286,7 @@ fn test_current_contract( if version < ClarityVersion::Clarity4 { let err = eval_result.unwrap_err(); assert_eq!( - Error::Unchecked(CheckErrors::UndefinedVariable( + VmExecutionError::Unchecked(CheckErrorKind::UndefinedVariable( "current-contract".to_string(), )), err diff --git a/clarity/src/vm/tooling/mod.rs b/clarity/src/vm/tooling/mod.rs index bd5d0a0d79f..b400f67e034 100644 --- a/clarity/src/vm/tooling/mod.rs +++ b/clarity/src/vm/tooling/mod.rs @@ -3,7 +3,7 @@ use stacks_common::types::StacksEpochId; use super::analysis::ContractAnalysis; use super::types::TypeSignature; use super::ClarityVersion; -use crate::vm::analysis::{run_analysis, CheckError}; +use crate::vm::analysis::{run_analysis, StaticCheckError}; use crate::vm::ast::build_ast; use crate::vm::costs::LimitedCostTracker; use crate::vm::database::MemoryBackingStore; @@ -14,7 +14,7 @@ pub fn mem_type_check( snippet: &str, version: ClarityVersion, epoch: StacksEpochId, -) -> Result<(Option, ContractAnalysis), CheckError> { +) -> Result<(Option, ContractAnalysis), StaticCheckError> { let contract_identifier = QualifiedContractIdentifier::transient(); let contract = build_ast(&contract_identifier, snippet, &mut (), version, epoch) .unwrap() diff --git a/clarity/src/vm/types/mod.rs b/clarity/src/vm/types/mod.rs index 5d18da01fa5..0986e160d57 100644 --- a/clarity/src/vm/types/mod.rs +++ b/clarity/src/vm/types/mod.rs @@ -28,7 +28,7 @@ pub use clarity_types::types::{ }; pub use self::std_principals::StandardPrincipalData; -use crate::vm::errors::CheckErrors; +use crate::vm::errors::CheckErrorKind; pub use crate::vm::types::signatures::{ parse_name_type_pairs, AssetIdentifier, BufferLength, FixedFunction, FunctionArg, FunctionSignature, FunctionType, ListTypeData, SequenceSubtype, StringSubtype, @@ -88,7 +88,7 @@ impl BlockInfoProperty { } impl BurnBlockInfoProperty { - pub fn type_result(&self) -> std::result::Result { + pub fn type_result(&self) -> std::result::Result { use self::BurnBlockInfoProperty::*; let result = match self { HeaderHash => BUFF_32.clone(), @@ -102,18 +102,20 @@ impl BurnBlockInfoProperty { ("hashbytes".into(), BUFF_32.clone()), ]) .map_err(|_| { - CheckErrors::Expects( + CheckErrorKind::Expects( "FATAL: bad type signature for pox addr".into(), ) })?, ), 2, ) - .map_err(|_| CheckErrors::Expects("FATAL: bad list type signature".into()))?, + .map_err(|_| { + CheckErrorKind::Expects("FATAL: bad list type signature".into()) + })?, ), ("payout".into(), TypeSignature::UIntType), ]) - .map_err(|_| CheckErrors::Expects("FATAL: bad type signature for pox addr".into()))? + .map_err(|_| CheckErrorKind::Expects("FATAL: bad type signature for pox addr".into()))? .into(), }; Ok(result) diff --git a/clarity/src/vm/types/serialization.rs b/clarity/src/vm/types/serialization.rs index 16e62f24099..e0d2cf8703b 100644 --- a/clarity/src/vm/types/serialization.rs +++ b/clarity/src/vm/types/serialization.rs @@ -22,7 +22,7 @@ pub use clarity_types::types::serialization::{ use stacks_common::util::hash::{hex_bytes, to_hex}; use crate::vm::database::{ClarityDeserializable, ClaritySerializable}; -use crate::vm::errors::{Error as ClarityError, InterpreterError}; +use crate::vm::errors::{VmExecutionError, VmInternalError}; impl ClaritySerializable for u32 { fn serialize(&self) -> String { @@ -31,13 +31,13 @@ impl ClaritySerializable for u32 { } impl ClarityDeserializable for u32 { - fn deserialize(input: &str) -> Result { + fn deserialize(input: &str) -> Result { let bytes = hex_bytes(input).map_err(|_| { - InterpreterError::Expect("u32 deserialization: failed decoding bytes.".into()) + VmInternalError::Expect("u32 deserialization: failed decoding bytes.".into()) })?; assert_eq!(bytes.len(), 4); Ok(u32::from_be_bytes(bytes[0..4].try_into().map_err( - |_| InterpreterError::Expect("u32 deserialization: failed reading.".into()), + |_| VmInternalError::Expect("u32 deserialization: failed reading.".into()), )?)) } } diff --git a/clarity/src/vm/types/signatures.rs b/clarity/src/vm/types/signatures.rs index 09e0c74be43..4d35554ca52 100644 --- a/clarity/src/vm/types/signatures.rs +++ b/clarity/src/vm/types/signatures.rs @@ -28,7 +28,7 @@ use stacks_common::types::StacksEpochId; use self::TypeSignature::SequenceType; use crate::vm::costs::{runtime_cost, CostOverflowingMath}; -use crate::vm::errors::{CheckErrors, SyntaxBindingError, SyntaxBindingErrorType}; +use crate::vm::errors::{CheckErrorKind, SyntaxBindingError, SyntaxBindingErrorType}; use crate::vm::representations::{ ClarityName, SymbolicExpression, SymbolicExpressionType, TraitDefinition, }; @@ -164,58 +164,59 @@ impl From for FunctionSignature { /// This is not included in clarity-types because it requires the /// [`CostTracker`] trait. pub trait TypeSignatureExt { - fn parse_atom_type(typename: &str) -> Result; + fn parse_atom_type(typename: &str) -> Result; fn parse_list_type_repr( epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result; + ) -> Result; fn parse_tuple_type_repr( epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result; - fn parse_buff_type_repr(type_args: &[SymbolicExpression]) - -> Result; + ) -> Result; + fn parse_buff_type_repr( + type_args: &[SymbolicExpression], + ) -> Result; fn parse_string_utf8_type_repr( type_args: &[SymbolicExpression], - ) -> Result; + ) -> Result; fn parse_string_ascii_type_repr( type_args: &[SymbolicExpression], - ) -> Result; + ) -> Result; fn parse_optional_type_repr( epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result; + ) -> Result; fn parse_response_type_repr( epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result; + ) -> Result; fn parse_type_repr( epoch: StacksEpochId, x: &SymbolicExpression, accounting: &mut A, - ) -> Result; + ) -> Result; fn parse_trait_type_repr( type_args: &[SymbolicExpression], accounting: &mut A, epoch: StacksEpochId, clarity_version: ClarityVersion, - ) -> Result, CheckErrors>; + ) -> Result, CheckErrorKind>; #[cfg(test)] fn from_string(val: &str, version: ClarityVersion, epoch: StacksEpochId) -> Self; } impl TypeSignatureExt for TypeSignature { - fn parse_atom_type(typename: &str) -> Result { + fn parse_atom_type(typename: &str) -> Result { match typename { "int" => Ok(TypeSignature::IntType), "uint" => Ok(TypeSignature::UIntType), "bool" => Ok(TypeSignature::BoolType), "principal" => Ok(TypeSignature::PrincipalType), - _ => Err(CheckErrors::UnknownTypeName(typename.into())), + _ => Err(CheckErrorKind::UnknownTypeName(typename.into())), } } @@ -225,18 +226,18 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { + ) -> Result { if type_args.len() != 2 { - return Err(CheckErrors::InvalidTypeDescription); + return Err(CheckErrorKind::InvalidTypeDescription); } if let SymbolicExpressionType::LiteralValue(Value::Int(max_len)) = &type_args[0].expr { let atomic_type_arg = &type_args[type_args.len() - 1]; let entry_type = TypeSignature::parse_type_repr(epoch, atomic_type_arg, accounting)?; - let max_len = u32::try_from(*max_len).map_err(|_| CheckErrors::ValueTooLarge)?; + let max_len = u32::try_from(*max_len).map_err(|_| CheckErrorKind::ValueTooLarge)?; ListTypeData::new_list(entry_type, max_len).map(|x| x.into()) } else { - Err(CheckErrors::InvalidTypeDescription) + Err(CheckErrorKind::InvalidTypeDescription) } } @@ -246,8 +247,8 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { - let mapped_key_types = parse_name_type_pairs::<_, CheckErrors>( + ) -> Result { + let mapped_key_types = parse_name_type_pairs::<_, CheckErrorKind>( epoch, type_args, SyntaxBindingErrorType::TupleCons, @@ -261,15 +262,15 @@ impl TypeSignatureExt for TypeSignature { // (buff 10) fn parse_buff_type_repr( type_args: &[SymbolicExpression], - ) -> Result { + ) -> Result { if type_args.len() != 1 { - return Err(CheckErrors::InvalidTypeDescription); + return Err(CheckErrorKind::InvalidTypeDescription); } if let SymbolicExpressionType::LiteralValue(Value::Int(buff_len)) = &type_args[0].expr { BufferLength::try_from(*buff_len) .map(|buff_len| SequenceType(SequenceSubtype::BufferType(buff_len))) } else { - Err(CheckErrors::InvalidTypeDescription) + Err(CheckErrorKind::InvalidTypeDescription) } } @@ -277,16 +278,16 @@ impl TypeSignatureExt for TypeSignature { // (string-utf8 10) fn parse_string_utf8_type_repr( type_args: &[SymbolicExpression], - ) -> Result { + ) -> Result { if type_args.len() != 1 { - return Err(CheckErrors::InvalidTypeDescription); + return Err(CheckErrorKind::InvalidTypeDescription); } if let SymbolicExpressionType::LiteralValue(Value::Int(utf8_len)) = &type_args[0].expr { StringUTF8Length::try_from(*utf8_len).map(|utf8_len| { SequenceType(SequenceSubtype::StringType(StringSubtype::UTF8(utf8_len))) }) } else { - Err(CheckErrors::InvalidTypeDescription) + Err(CheckErrorKind::InvalidTypeDescription) } } @@ -294,16 +295,16 @@ impl TypeSignatureExt for TypeSignature { // (string-ascii 10) fn parse_string_ascii_type_repr( type_args: &[SymbolicExpression], - ) -> Result { + ) -> Result { if type_args.len() != 1 { - return Err(CheckErrors::InvalidTypeDescription); + return Err(CheckErrorKind::InvalidTypeDescription); } if let SymbolicExpressionType::LiteralValue(Value::Int(buff_len)) = &type_args[0].expr { BufferLength::try_from(*buff_len).map(|buff_len| { SequenceType(SequenceSubtype::StringType(StringSubtype::ASCII(buff_len))) }) } else { - Err(CheckErrors::InvalidTypeDescription) + Err(CheckErrorKind::InvalidTypeDescription) } } @@ -311,9 +312,9 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { + ) -> Result { if type_args.len() != 1 { - return Err(CheckErrors::InvalidTypeDescription); + return Err(CheckErrorKind::InvalidTypeDescription); } let inner_type = TypeSignature::parse_type_repr(epoch, &type_args[0], accounting)?; @@ -324,9 +325,9 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { + ) -> Result { if type_args.len() != 2 { - return Err(CheckErrors::InvalidTypeDescription); + return Err(CheckErrorKind::InvalidTypeDescription); } let ok_type = TypeSignature::parse_type_repr(epoch, &type_args[0], accounting)?; let err_type = TypeSignature::parse_type_repr(epoch, &type_args[1], accounting)?; @@ -337,7 +338,7 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, x: &SymbolicExpression, accounting: &mut A, - ) -> Result { + ) -> Result { runtime_cost(ClarityCostFunction::TypeParseStep, accounting, 0)?; match x.expr { @@ -348,7 +349,7 @@ impl TypeSignatureExt for TypeSignature { SymbolicExpressionType::List(ref list_contents) => { let (compound_type, rest) = list_contents .split_first() - .ok_or(CheckErrors::InvalidTypeDescription)?; + .ok_or(CheckErrorKind::InvalidTypeDescription)?; if let SymbolicExpressionType::Atom(ref compound_type) = compound_type.expr { match compound_type.as_ref() { "list" => TypeSignature::parse_list_type_repr(epoch, rest, accounting), @@ -362,10 +363,10 @@ impl TypeSignatureExt for TypeSignature { "response" => { TypeSignature::parse_response_type_repr(epoch, rest, accounting) } - _ => Err(CheckErrors::InvalidTypeDescription), + _ => Err(CheckErrorKind::InvalidTypeDescription), } } else { - Err(CheckErrors::InvalidTypeDescription) + Err(CheckErrorKind::InvalidTypeDescription) } } SymbolicExpressionType::TraitReference(_, ref trait_definition) @@ -390,7 +391,7 @@ impl TypeSignatureExt for TypeSignature { )), } } - _ => Err(CheckErrors::InvalidTypeDescription), + _ => Err(CheckErrorKind::InvalidTypeDescription), } } @@ -399,43 +400,43 @@ impl TypeSignatureExt for TypeSignature { accounting: &mut A, epoch: StacksEpochId, clarity_version: ClarityVersion, - ) -> Result, CheckErrors> { + ) -> Result, CheckErrorKind> { let mut trait_signature: BTreeMap = BTreeMap::new(); let functions_types = type_args .first() - .ok_or_else(|| CheckErrors::InvalidTypeDescription)? + .ok_or_else(|| CheckErrorKind::InvalidTypeDescription)? .match_list() - .ok_or(CheckErrors::DefineTraitBadSignature)?; + .ok_or(CheckErrorKind::DefineTraitBadSignature)?; for function_type in functions_types.iter() { let args = function_type .match_list() - .ok_or(CheckErrors::DefineTraitBadSignature)?; + .ok_or(CheckErrorKind::DefineTraitBadSignature)?; if args.len() != 3 { - return Err(CheckErrors::InvalidTypeDescription); + return Err(CheckErrorKind::InvalidTypeDescription); } // Extract function's name let fn_name = args[0] .match_atom() - .ok_or(CheckErrors::DefineTraitBadSignature)?; + .ok_or(CheckErrorKind::DefineTraitBadSignature)?; // Extract function's arguments let fn_args_exprs = args[1] .match_list() - .ok_or(CheckErrors::DefineTraitBadSignature)?; + .ok_or(CheckErrorKind::DefineTraitBadSignature)?; let fn_args = fn_args_exprs .iter() .map(|arg_type| TypeSignature::parse_type_repr(epoch, arg_type, accounting)) - .collect::>()?; + .collect::>()?; // Extract function's type return - must be a response let fn_return = match TypeSignature::parse_type_repr(epoch, &args[2], accounting) { Ok(response) => match response { TypeSignature::ResponseType(_) => Ok(response), - _ => Err(CheckErrors::DefineTraitBadSignature), + _ => Err(CheckErrorKind::DefineTraitBadSignature), }, - _ => Err(CheckErrors::DefineTraitBadSignature), + _ => Err(CheckErrorKind::DefineTraitBadSignature), }?; if trait_signature @@ -449,7 +450,9 @@ impl TypeSignatureExt for TypeSignature { .is_some() && clarity_version >= ClarityVersion::Clarity2 { - return Err(CheckErrors::DefineTraitDuplicateMethod(fn_name.to_string())); + return Err(CheckErrorKind::DefineTraitDuplicateMethod( + fn_name.to_string(), + )); } } Ok(trait_signature) @@ -472,7 +475,7 @@ impl TypeSignatureExt for TypeSignature { } impl FixedFunction { - pub fn total_type_size(&self) -> Result { + pub fn total_type_size(&self) -> Result { let mut function_type_size = u64::from(self.returns.type_size()?); for arg in self.args.iter() { function_type_size = @@ -483,7 +486,7 @@ impl FixedFunction { } impl FunctionSignature { - pub fn total_type_size(&self) -> Result { + pub fn total_type_size(&self) -> Result { let mut function_type_size = u64::from(self.returns.type_size()?); for arg in self.args.iter() { function_type_size = @@ -496,7 +499,7 @@ impl FunctionSignature { &self, epoch: &StacksEpochId, args: Vec, - ) -> Result { + ) -> Result { if args.len() != self.args.len() { return Ok(false); } @@ -545,7 +548,7 @@ pub fn parse_name_type_pairs( accounting: &mut A, ) -> Result, E> where - E: for<'a> From<(CheckErrors, &'a SymbolicExpression)>, + E: for<'a> From<(CheckErrorKind, &'a SymbolicExpression)>, { // this is a pretty deep nesting here, but what we're trying to do is pick out the values of // the form: @@ -554,14 +557,14 @@ where use crate::vm::representations::SymbolicExpressionType::List; // step 1: parse it into a vec of symbolicexpression pairs. - let as_pairs: Result, (CheckErrors, &SymbolicExpression)> = name_type_pairs + let as_pairs: Result, (CheckErrorKind, &SymbolicExpression)> = name_type_pairs .iter() .enumerate() .map(|(i, key_type_pair)| { if let List(ref as_vec) = key_type_pair.expr { if as_vec.len() != 2 { Err(( - CheckErrors::BadSyntaxBinding(SyntaxBindingError::InvalidLength( + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::InvalidLength( binding_error_type, i, )), @@ -580,7 +583,7 @@ where .collect(); // step 2: turn into a vec of (name, typesignature) pairs. - let key_types: Result, (CheckErrors, &SymbolicExpression)> = (as_pairs?) + let key_types: Result, (CheckErrorKind, &SymbolicExpression)> = (as_pairs?) .iter() .enumerate() .map(|(i, (name_symbol, type_symbol))| { @@ -588,7 +591,7 @@ where .match_atom() .ok_or_else(|| { ( - CheckErrors::BadSyntaxBinding(SyntaxBindingError::NotAtom( + CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::NotAtom( binding_error_type, i, )), @@ -619,13 +622,13 @@ mod test { use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; - use super::CheckErrors::*; + use super::CheckErrorKind::*; use super::*; use crate::vm::tests::test_clarity_versions; use crate::vm::types::QualifiedContractIdentifier; use crate::vm::{execute, ClarityVersion}; - fn fail_parse(val: &str, version: ClarityVersion, epoch: StacksEpochId) -> CheckErrors { + fn fail_parse(val: &str, version: ClarityVersion, epoch: StacksEpochId) -> CheckErrorKind { use crate::vm::ast::parse; let expr = &parse( &QualifiedContractIdentifier::transient(), diff --git a/clarity/src/vm/variables.rs b/clarity/src/vm/variables.rs index cb84336dc99..455cdeb199f 100644 --- a/clarity/src/vm/variables.rs +++ b/clarity/src/vm/variables.rs @@ -17,11 +17,11 @@ use clarity_types::types::PrincipalData; use stacks_common::types::StacksEpochId; -use super::errors::InterpreterError; +use super::errors::VmInternalError; use crate::vm::contexts::{Environment, LocalContext}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; -use crate::vm::errors::{InterpreterResult as Result, RuntimeErrorType}; +use crate::vm::errors::{InterpreterResult as Result, RuntimeError}; use crate::vm::types::Value; use crate::vm::ClarityVersion; @@ -58,24 +58,18 @@ pub fn lookup_reserved_variable( { match variable { NativeVariables::TxSender => { - let sender = env - .sender - .clone() - .ok_or(RuntimeErrorType::NoSenderInContext)?; + let sender = env.sender.clone().ok_or(RuntimeError::NoSenderInContext)?; Ok(Some(Value::Principal(sender))) } NativeVariables::ContractCaller => { - let caller = env - .caller - .clone() - .ok_or(RuntimeErrorType::NoCallerInContext)?; + let caller = env.caller.clone().ok_or(RuntimeError::NoCallerInContext)?; Ok(Some(Value::Principal(caller))) } NativeVariables::TxSponsor => { let sponsor = match env.sponsor.clone() { None => Value::none(), Some(p) => Value::some(Value::Principal(p)).map_err(|_| { - InterpreterError::Expect( + VmInternalError::Expect( "ERROR: principal should be a valid Clarity object".into(), ) })?, diff --git a/clarity/src/vm/version.rs b/clarity/src/vm/version.rs index 41226cfad97..9ddf6f43f03 100644 --- a/clarity/src/vm/version.rs +++ b/clarity/src/vm/version.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use stacks_common::types::StacksEpochId; -use crate::vm::errors::{Error, RuntimeErrorType}; +use crate::vm::errors::{RuntimeError, VmExecutionError}; #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, PartialOrd)] pub enum ClarityVersion { @@ -51,9 +51,9 @@ impl ClarityVersion { } impl FromStr for ClarityVersion { - type Err = Error; + type Err = VmExecutionError; - fn from_str(version: &str) -> Result { + fn from_str(version: &str) -> Result { let s = version.to_string().to_lowercase(); if s == "clarity1" { Ok(ClarityVersion::Clarity1) @@ -64,7 +64,7 @@ impl FromStr for ClarityVersion { } else if s == "clarity4" { Ok(ClarityVersion::Clarity4) } else { - Err(RuntimeErrorType::ParseError( + Err(RuntimeError::TypeParseFailure( "Invalid clarity version. Valid versions are: Clarity1, Clarity2, Clarity3." .to_string(), ) diff --git a/contrib/stacks-cli/src/main.rs b/contrib/stacks-cli/src/main.rs index 34561c0659b..7c5d944218a 100644 --- a/contrib/stacks-cli/src/main.rs +++ b/contrib/stacks-cli/src/main.rs @@ -22,7 +22,7 @@ use std::io::Read; use std::io::prelude::*; use std::{env, fs, io}; -use clarity::vm::errors::{Error as ClarityError, RuntimeErrorType}; +use clarity::vm::errors::{RuntimeError, VmExecutionError}; use clarity::vm::types::PrincipalData; use clarity::vm::{ClarityName, ClarityVersion, ContractName, Value}; use stacks_common::address::{AddressHashMode, b58}; @@ -184,8 +184,8 @@ block's sqlite database."; #[derive(Debug)] enum CliError { - ClarityRuntimeError(RuntimeErrorType), - ClarityGeneralError(ClarityError), + ClarityRuntimeError(RuntimeError), + ClarityGeneralError(VmExecutionError), Message(String), Usage, InvalidChainId(std::num::ParseIntError), @@ -219,14 +219,14 @@ impl From<&str> for CliError { } } -impl From for CliError { - fn from(value: RuntimeErrorType) -> Self { +impl From for CliError { + fn from(value: RuntimeError) -> Self { CliError::ClarityRuntimeError(value) } } -impl From for CliError { - fn from(value: ClarityError) -> Self { +impl From for CliError { + fn from(value: VmExecutionError) -> Self { CliError::ClarityGeneralError(value) } } diff --git a/pox-locking/src/events.rs b/pox-locking/src/events.rs index 3fc16954bf2..cc4fc8f539e 100644 --- a/pox-locking/src/events.rs +++ b/pox-locking/src/events.rs @@ -16,7 +16,7 @@ use clarity::vm::contexts::GlobalContext; use clarity::vm::costs::LimitedCostTracker; -use clarity::vm::errors::Error as ClarityError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier, ResponseData, TupleData}; use clarity::vm::Value; #[cfg(any(test, feature = "testing"))] @@ -565,7 +565,7 @@ pub fn synthesize_pox_event_info( function_name: &str, args: &[Value], response: &ResponseData, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { // the first thing we do is check the current epoch. In Epochs <= 2.4, // synthesizing PoX events was an assessed cost, so event generation // must remain identical. @@ -610,7 +610,7 @@ fn inner_synthesize_pox_event_info( function_name: &str, args: &[Value], response: &ResponseData, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { let sender = match sender_opt { Some(sender) => sender, None => { @@ -687,7 +687,7 @@ fn inner_synthesize_pox_event_info( Ok(Value::Tuple(event_tuple)) }, ) - .map_err(|e: ClarityError| { + .map_err(|e: VmExecutionError| { error!("Failed to synthesize PoX event: {:?}", &e); e })?; diff --git a/pox-locking/src/events_24.rs b/pox-locking/src/events_24.rs index a23726b46e7..0a7e2b4397b 100644 --- a/pox-locking/src/events_24.rs +++ b/pox-locking/src/events_24.rs @@ -15,7 +15,7 @@ // along with this program. If not, see . use clarity::vm::contexts::GlobalContext; -use clarity::vm::errors::Error as ClarityError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier, TupleData}; use clarity::vm::Value; #[cfg(any(test, feature = "testing"))] @@ -343,7 +343,7 @@ pub fn synthesize_pox_2_or_3_event_info( sender_opt: Option<&PrincipalData>, function_name: &str, args: &[Value], -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { let sender = match sender_opt { Some(sender) => sender, None => { @@ -419,7 +419,7 @@ pub fn synthesize_pox_2_or_3_event_info( Ok(Value::Tuple(event_tuple)) }, ) - .map_err(|e: ClarityError| { + .map_err(|e: VmExecutionError| { error!("Failed to synthesize PoX event: {:?}", &e); e })?; diff --git a/pox-locking/src/lib.rs b/pox-locking/src/lib.rs index 16c11c8af26..ee67990caab 100644 --- a/pox-locking/src/lib.rs +++ b/pox-locking/src/lib.rs @@ -26,7 +26,7 @@ //! invoked. If so, it updates the PoX lock. use clarity::boot_util::boot_code_id; use clarity::vm::contexts::GlobalContext; -use clarity::vm::errors::{Error as ClarityError, RuntimeErrorType}; +use clarity::vm::errors::{RuntimeError, VmExecutionError}; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::Value; use stacks_common::types::StacksEpochId; @@ -48,11 +48,11 @@ pub enum LockingError { PoxExtendNotLocked, PoxIncreaseOnV1, PoxInvalidIncrease, - Clarity(ClarityError), + Clarity(VmExecutionError), } -impl From for LockingError { - fn from(e: ClarityError) -> LockingError { +impl From for LockingError { + fn from(e: VmExecutionError) -> LockingError { LockingError::Clarity(e) } } @@ -71,7 +71,7 @@ pub fn handle_contract_call_special_cases( function_name: &str, args: &[Value], result: &Value, -) -> Result<(), ClarityError> { +) -> Result<(), VmExecutionError> { if *contract_id == boot_code_id(POX_1_NAME, global_context.mainnet) { if !pox_1::is_read_only(function_name) && global_context.database.get_v1_unlock_height() @@ -86,8 +86,8 @@ pub fn handle_contract_call_special_cases( "function_name" => function_name, "contract_id" => %contract_id ); - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } @@ -101,8 +101,8 @@ pub fn handle_contract_call_special_cases( "function_name" => function_name, "contract_id" => %contract_id ); - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } @@ -124,8 +124,8 @@ pub fn handle_contract_call_special_cases( "function_name" => function_name, "contract_id" => %contract_id ); - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } diff --git a/pox-locking/src/pox_1.rs b/pox-locking/src/pox_1.rs index 4cc7ffe0ea5..bcb341728df 100644 --- a/pox-locking/src/pox_1.rs +++ b/pox-locking/src/pox_1.rs @@ -19,7 +19,7 @@ use clarity::vm::contexts::GlobalContext; use clarity::vm::costs::cost_functions::ClarityCostFunction; use clarity::vm::costs::runtime_cost; use clarity::vm::database::ClarityDatabase; -use clarity::vm::errors::{Error as ClarityError, RuntimeErrorType}; +use clarity::vm::errors::{RuntimeError, VmExecutionError}; use clarity::vm::events::{STXEventType, STXLockEventData, StacksTransactionEvent}; use clarity::vm::types::PrincipalData; use clarity::vm::Value; @@ -131,7 +131,7 @@ pub fn handle_contract_call( _sender_opt: Option<&PrincipalData>, function_name: &str, value: &Value, -) -> Result<(), ClarityError> { +) -> Result<(), VmExecutionError> { if !(function_name == "stack-stx" || function_name == "delegate-stack-stx") { // only have work to do if the function is `stack-stx` or `delegate-stack-stx` return Ok(()); @@ -181,15 +181,15 @@ pub fn handle_contract_call( return Ok(()); } Err(LockingError::DefunctPoxContract) => { - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } Err(LockingError::PoxAlreadyLocked) => { // the caller tried to lock tokens into both pox-1 and pox-2 - return Err(ClarityError::Runtime( - RuntimeErrorType::PoxAlreadyLocked, + return Err(VmExecutionError::Runtime( + RuntimeError::PoxAlreadyLocked, None, )); } diff --git a/pox-locking/src/pox_2.rs b/pox-locking/src/pox_2.rs index 1cbb1cd7724..3663bda19ac 100644 --- a/pox-locking/src/pox_2.rs +++ b/pox-locking/src/pox_2.rs @@ -19,7 +19,7 @@ use clarity::vm::contexts::GlobalContext; use clarity::vm::costs::cost_functions::ClarityCostFunction; use clarity::vm::costs::runtime_cost; use clarity::vm::database::{ClarityDatabase, STXBalance}; -use clarity::vm::errors::{Error as ClarityError, RuntimeErrorType}; +use clarity::vm::errors::{RuntimeError, VmExecutionError}; use clarity::vm::events::{STXEventType, STXLockEventData, StacksTransactionEvent}; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::{Environment, Value}; @@ -295,7 +295,7 @@ fn handle_stack_lockup_pox_v2( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { debug!( "Handle special-case contract-call to {:?} {} (which returned {:?})", "PoX-2 contract", function_name, value @@ -332,15 +332,15 @@ fn handle_stack_lockup_pox_v2( return Ok(Some(event)); } Err(LockingError::DefunctPoxContract) => { - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } Err(LockingError::PoxAlreadyLocked) => { // the caller tried to lock tokens into both pox-1 and pox-2 - return Err(ClarityError::Runtime( - RuntimeErrorType::PoxAlreadyLocked, + return Err(VmExecutionError::Runtime( + RuntimeError::PoxAlreadyLocked, None, )); } @@ -360,7 +360,7 @@ fn handle_stack_lockup_extension_pox_v2( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { // in this branch case, the PoX-2 contract has stored the extension information // and performed the extension checks. Now, the VM needs to update the account locks // (because the locks cannot be applied directly from the Clarity code itself) @@ -400,8 +400,8 @@ fn handle_stack_lockup_extension_pox_v2( return Ok(Some(event)); } Err(LockingError::DefunctPoxContract) => { - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } @@ -424,7 +424,7 @@ fn handle_stack_lockup_increase_pox_v2( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { // in this branch case, the PoX-2 contract has stored the increase information // and performed the increase checks. Now, the VM needs to update the account locks // (because the locks cannot be applied directly from the Clarity code itself) @@ -463,8 +463,8 @@ fn handle_stack_lockup_increase_pox_v2( return Ok(Some(event)); } Err(LockingError::DefunctPoxContract) => { - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } @@ -488,7 +488,7 @@ pub fn handle_contract_call( function_name: &str, args: &[Value], value: &Value, -) -> Result<(), ClarityError> { +) -> Result<(), VmExecutionError> { // Generate a synthetic print event for all functions that alter stacking state let print_event_opt = if let Value::Response(response) = value { if response.committed { diff --git a/pox-locking/src/pox_3.rs b/pox-locking/src/pox_3.rs index 265ec592088..1b38f9cd1b8 100644 --- a/pox-locking/src/pox_3.rs +++ b/pox-locking/src/pox_3.rs @@ -19,7 +19,7 @@ use clarity::vm::contexts::GlobalContext; use clarity::vm::costs::cost_functions::ClarityCostFunction; use clarity::vm::costs::runtime_cost; use clarity::vm::database::{ClarityDatabase, STXBalance}; -use clarity::vm::errors::{Error as ClarityError, RuntimeErrorType}; +use clarity::vm::errors::{RuntimeError, VmExecutionError}; use clarity::vm::events::{STXEventType, STXLockEventData, StacksTransactionEvent}; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::{Environment, Value}; @@ -184,7 +184,7 @@ fn handle_stack_lockup_pox_v3( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { debug!( "Handle special-case contract-call to {:?} {} (which returned {:?})", boot_code_id(POX_3_NAME, global_context.mainnet), @@ -223,15 +223,15 @@ fn handle_stack_lockup_pox_v3( return Ok(Some(event)); } Err(LockingError::DefunctPoxContract) => { - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } Err(LockingError::PoxAlreadyLocked) => { // the caller tried to lock tokens into multiple pox contracts - return Err(ClarityError::Runtime( - RuntimeErrorType::PoxAlreadyLocked, + return Err(VmExecutionError::Runtime( + RuntimeError::PoxAlreadyLocked, None, )); } @@ -251,7 +251,7 @@ fn handle_stack_lockup_extension_pox_v3( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { // in this branch case, the PoX-3 contract has stored the extension information // and performed the extension checks. Now, the VM needs to update the account locks // (because the locks cannot be applied directly from the Clarity code itself) @@ -291,8 +291,8 @@ fn handle_stack_lockup_extension_pox_v3( return Ok(Some(event)); } Err(LockingError::DefunctPoxContract) => { - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } @@ -315,7 +315,7 @@ fn handle_stack_lockup_increase_pox_v3( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { // in this branch case, the PoX-3 contract has stored the increase information // and performed the increase checks. Now, the VM needs to update the account locks // (because the locks cannot be applied directly from the Clarity code itself) @@ -353,8 +353,8 @@ fn handle_stack_lockup_increase_pox_v3( return Ok(Some(event)); } Err(LockingError::DefunctPoxContract) => { - return Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + return Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )); } @@ -378,7 +378,7 @@ pub fn handle_contract_call( function_name: &str, args: &[Value], value: &Value, -) -> Result<(), ClarityError> { +) -> Result<(), VmExecutionError> { // Generate a synthetic print event for all functions that alter stacking state let print_event_opt = if let Value::Response(response) = value { if response.committed { diff --git a/pox-locking/src/pox_4.rs b/pox-locking/src/pox_4.rs index 733d6d6c545..178362392a6 100644 --- a/pox-locking/src/pox_4.rs +++ b/pox-locking/src/pox_4.rs @@ -19,7 +19,7 @@ use clarity::vm::contexts::GlobalContext; use clarity::vm::costs::cost_functions::ClarityCostFunction; use clarity::vm::costs::runtime_cost; use clarity::vm::database::{ClarityDatabase, STXBalance}; -use clarity::vm::errors::{Error as ClarityError, RuntimeErrorType}; +use clarity::vm::errors::{RuntimeError, VmExecutionError}; use clarity::vm::events::{STXEventType, STXLockEventData, StacksTransactionEvent}; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::{Environment, Value}; @@ -154,7 +154,7 @@ fn handle_stack_lockup_pox_v4( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { debug!( "Handle special-case contract-call to {:?} {function_name} (which returned {value:?})", boot_code_id(POX_4_NAME, global_context.mainnet) @@ -190,14 +190,14 @@ fn handle_stack_lockup_pox_v4( })); Ok(Some(event)) } - Err(LockingError::DefunctPoxContract) => Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + Err(LockingError::DefunctPoxContract) => Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )), Err(LockingError::PoxAlreadyLocked) => { // the caller tried to lock tokens into multiple pox contracts - Err(ClarityError::Runtime( - RuntimeErrorType::PoxAlreadyLocked, + Err(VmExecutionError::Runtime( + RuntimeError::PoxAlreadyLocked, None, )) } @@ -215,7 +215,7 @@ fn handle_stack_lockup_extension_pox_v4( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { // in this branch case, the PoX-4 contract has stored the extension information // and performed the extension checks. Now, the VM needs to update the account locks // (because the locks cannot be applied directly from the Clarity code itself) @@ -252,8 +252,8 @@ fn handle_stack_lockup_extension_pox_v4( })); Ok(Some(event)) } - Err(LockingError::DefunctPoxContract) => Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + Err(LockingError::DefunctPoxContract) => Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )), Err(e) => { @@ -271,7 +271,7 @@ fn handle_stack_lockup_increase_pox_v4( global_context: &mut GlobalContext, function_name: &str, value: &Value, -) -> Result, ClarityError> { +) -> Result, VmExecutionError> { // in this branch case, the PoX-4 contract has stored the increase information // and performed the increase checks. Now, the VM needs to update the account locks // (because the locks cannot be applied directly from the Clarity code itself) @@ -308,8 +308,8 @@ fn handle_stack_lockup_increase_pox_v4( Ok(Some(event)) } - Err(LockingError::DefunctPoxContract) => Err(ClarityError::Runtime( - RuntimeErrorType::DefunctPoxContract, + Err(LockingError::DefunctPoxContract) => Err(VmExecutionError::Runtime( + RuntimeError::DefunctPoxContract, None, )), Err(e) => { @@ -329,7 +329,7 @@ pub fn handle_contract_call( function_name: &str, args: &[Value], value: &Value, -) -> Result<(), ClarityError> { +) -> Result<(), VmExecutionError> { // Generate a synthetic print event for all functions that alter stacking state let print_event_opt = if let Value::Response(response) = value { if response.committed { diff --git a/stacks-signer/src/client/mod.rs b/stacks-signer/src/client/mod.rs index e518ff4a7b8..50bd7bbe351 100644 --- a/stacks-signer/src/client/mod.rs +++ b/stacks-signer/src/client/mod.rs @@ -21,7 +21,7 @@ pub(crate) mod stacks_client; use std::time::Duration; -use clarity::vm::errors::Error as ClarityError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::serialization::SerializationError; use libsigner::RPCError; use libstackerdb::Error as StackerDBError; @@ -81,7 +81,7 @@ pub enum ClientError { NotConnected, /// Clarity interpreter error #[error("Clarity interpreter error: {0}")] - ClarityError(#[from] ClarityError), + ClarityError(#[from] VmExecutionError), /// Malformed reward set #[error("Malformed contract data: {0}")] MalformedContractData(String), diff --git a/stackslib/src/chainstate/coordinator/tests.rs b/stackslib/src/chainstate/coordinator/tests.rs index ac39b68aafc..efa07e698e1 100644 --- a/stackslib/src/chainstate/coordinator/tests.rs +++ b/stackslib/src/chainstate/coordinator/tests.rs @@ -23,7 +23,7 @@ use std::sync::Arc; use clarity::vm::clarity::TransactionConnection; use clarity::vm::costs::{ExecutionCost, LimitedCostTracker}; use clarity::vm::database::BurnStateDB; -use clarity::vm::errors::Error as InterpreterError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::Value; use lazy_static::lazy_static; @@ -4830,7 +4830,7 @@ fn get_total_stacked_info( parent_tip: &StacksBlockId, reward_cycle: u64, is_pox_2: bool, -) -> Result { +) -> Result { chainstate .with_read_only_clarity_tx(burn_dbconn, parent_tip, |conn| { conn.with_readonly_clarity_env( diff --git a/stackslib/src/chainstate/stacks/boot/contract_tests.rs b/stackslib/src/chainstate/stacks/boot/contract_tests.rs index e75ed604453..7aae0821e5b 100644 --- a/stackslib/src/chainstate/stacks/boot/contract_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/contract_tests.rs @@ -6,7 +6,7 @@ use clarity::vm::analysis::mem_type_check; use clarity::vm::clarity::TransactionConnection; use clarity::vm::contexts::OwnedEnvironment; use clarity::vm::database::*; -use clarity::vm::errors::{CheckErrors, Error}; +use clarity::vm::errors::{CheckErrorKind, VmExecutionError}; use clarity::vm::test_util::{execute, symbols_from_values, TEST_BURN_STATE_DB, TEST_HEADER_DB}; use clarity::vm::types::{ OptionalData, PrincipalData, QualifiedContractIdentifier, ResponseData, StandardPrincipalData, @@ -31,7 +31,7 @@ use crate::chainstate::stacks::boot::{ use crate::chainstate::stacks::index::ClarityMarfTrieId; use crate::chainstate::stacks::{C32_ADDRESS_VERSION_TESTNET_SINGLESIG, *}; use crate::clarity_vm::clarity::{ - ClarityBlockConnection, ClarityMarfStore, ClarityMarfStoreTransaction, Error as ClarityError, + ClarityBlockConnection, ClarityError, ClarityMarfStore, ClarityMarfStoreTransaction, WritableMarfStore, }; use crate::clarity_vm::database::marf::MarfedKV; @@ -1710,8 +1710,11 @@ fn simple_epoch21_test() { ) .expect_err("2.0 'bad' contract should not deploy successfully") { - ClarityError::Analysis(e) => { - assert_eq!(*e.err, CheckErrors::UnknownFunction("stx-account".into())); + ClarityError::StaticCheck(e) => { + assert_eq!( + *e.err, + CheckErrorKind::UnknownFunction("stx-account".into()) + ); } e => panic!("Should have caused an analysis error: {:#?}", e), }; @@ -1740,7 +1743,9 @@ fn simple_epoch21_test() { ClarityError::Interpreter(e) => { assert_eq!( e, - Error::Unchecked(CheckErrors::NameAlreadyUsed("stx-account".into())) + VmExecutionError::Unchecked(CheckErrorKind::NameAlreadyUsed( + "stx-account".into() + )) ); } e => panic!("Should have caused an Interpreter error: {:#?}", e), diff --git a/stackslib/src/chainstate/stacks/boot/mod.rs b/stackslib/src/chainstate/stacks/boot/mod.rs index 381dfa06c0f..4ef8b2a46f8 100644 --- a/stackslib/src/chainstate/stacks/boot/mod.rs +++ b/stackslib/src/chainstate/stacks/boot/mod.rs @@ -19,11 +19,11 @@ use std::collections::BTreeMap; use std::sync::LazyLock; use clarity::types::Address; -use clarity::vm::analysis::CheckErrors; -use clarity::vm::clarity::{Error as ClarityError, TransactionConnection}; +use clarity::vm::analysis::CheckErrorKind; +use clarity::vm::clarity::{ClarityError, TransactionConnection}; use clarity::vm::costs::LimitedCostTracker; use clarity::vm::database::{ClarityDatabase, NULL_BURN_STATE_DB, NULL_HEADER_DB}; -use clarity::vm::errors::Error as VmError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::events::StacksTransactionEvent; use clarity::vm::representations::ContractName; use clarity::vm::types::{ @@ -365,7 +365,7 @@ impl StacksChainState { fn mark_pox_cycle_handled( db: &mut ClarityDatabase, cycle_number: u64, - ) -> Result<(), clarity::vm::errors::Error> { + ) -> Result<(), VmExecutionError> { let db_key = Self::handled_pox_cycle_start_key(cycle_number); db.put_data(&db_key, &POX_CYCLE_START_HANDLED_VALUE.to_string())?; Ok(()) @@ -1358,8 +1358,8 @@ impl StacksChainState { // Catch the epoch boundary edge case where burn height >= pox 3 activation height, but // there hasn't yet been a Stacks block. match result { - Err(Error::ClarityError(ClarityError::Interpreter(VmError::Unchecked( - CheckErrors::NoSuchContract(_), + Err(Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( + CheckErrorKind::NoSuchContract(_), )))) => { warn!("Reward cycle attempted to calculate rewards before the PoX contract was instantiated"); return Ok(vec![]); diff --git a/stackslib/src/chainstate/stacks/db/blocks.rs b/stackslib/src/chainstate/stacks/db/blocks.rs index 2b8373936e8..146b3061947 100644 --- a/stackslib/src/chainstate/stacks/db/blocks.rs +++ b/stackslib/src/chainstate/stacks/db/blocks.rs @@ -19,10 +19,11 @@ use std::io::{Read, Write}; use std::path::PathBuf; use std::{cmp, fs, io}; -pub use clarity::vm::analysis::errors::{CheckError, CheckErrors}; +pub use clarity::vm::analysis::errors::{CheckErrorKind, StaticCheckError}; use clarity::vm::clarity::TransactionConnection; use clarity::vm::costs::LimitedCostTracker; use clarity::vm::database::BurnStateDB; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::{ BuffData, PrincipalData, QualifiedContractIdentifier, SequenceData, StacksAddressExtensions as ClarityStacksAddressExtensions, StandardPrincipalData, TupleData, @@ -109,7 +110,7 @@ pub enum MemPoolRejection { NotEnoughFunds(u128, u128), NoSuchContract, NoSuchPublicFunction, - BadFunctionArgument(CheckError), + BadFunctionArgument(StaticCheckError), ContractAlreadyExists(QualifiedContractIdentifier), PoisonMicroblocksDoNotConflict, NoAnchorBlockWithPubkeyHash(Hash160), @@ -306,8 +307,8 @@ impl From for MemPoolRejection { } } -impl From for MemPoolRejection { - fn from(e: clarity::vm::errors::Error) -> MemPoolRejection { +impl From for MemPoolRejection { + fn from(e: VmExecutionError) -> MemPoolRejection { MemPoolRejection::Other(e.to_string()) } } @@ -3927,7 +3928,7 @@ impl StacksChainState { ) -> Result<(bool, Vec), Error> { // is this stacks block the first of a new epoch? let (stacks_parent_epoch, sortition_epoch) = clarity_tx - .with_clarity_db_readonly::<_, Result<_, clarity::vm::errors::Error>>(|db| { + .with_clarity_db_readonly::<_, Result<_, VmExecutionError>>(|db| { Ok(( db.get_clarity_epoch_version()?, db.get_stacks_epoch(chain_tip_burn_header_height), @@ -6614,17 +6615,16 @@ impl StacksChainState { } let (block_height, v1_unlock_height, v2_unlock_height, v3_unlock_height) = - clarity_connection - .with_clarity_db_readonly::<_, Result<_, clarity::vm::errors::Error>>( - |ref mut db| { - Ok(( - db.get_current_burnchain_block_height()? as u64, - db.get_v1_unlock_height(), - db.get_v2_unlock_height()?, - db.get_v3_unlock_height()?, - )) - }, - )?; + clarity_connection.with_clarity_db_readonly::<_, Result<_, VmExecutionError>>( + |ref mut db| { + Ok(( + db.get_current_burnchain_block_height()? as u64, + db.get_v1_unlock_height(), + db.get_v2_unlock_height()?, + db.get_v3_unlock_height()?, + )) + }, + )?; // 6: the paying account must have enough funds if !payer.stx_balance.can_transfer_at_burn_block( diff --git a/stackslib/src/chainstate/stacks/db/contracts.rs b/stackslib/src/chainstate/stacks/db/contracts.rs index 11b2ee0d023..24f515805a5 100644 --- a/stackslib/src/chainstate/stacks/db/contracts.rs +++ b/stackslib/src/chainstate/stacks/db/contracts.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pub use clarity::vm::analysis::errors::CheckErrors; +pub use clarity::vm::analysis::errors::CheckErrorKind; use clarity::vm::contracts::Contract; -use clarity::vm::errors::Error as clarity_vm_error; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::{QualifiedContractIdentifier, Value}; use crate::chainstate::stacks::db::*; @@ -31,8 +31,8 @@ impl StacksChainState { clarity_tx .with_clarity_db_readonly(|ref mut db| match db.get_contract(contract_id) { Ok(c) => Ok(Some(c)), - Err(clarity_vm_error::Unchecked(CheckErrors::NoSuchContract(_))) => Ok(None), - Err(e) => Err(clarity_error::Interpreter(e)), + Err(VmExecutionError::Unchecked(CheckErrorKind::NoSuchContract(_))) => Ok(None), + Err(e) => Err(ClarityError::Interpreter(e)), }) .map_err(Error::ClarityError) } @@ -47,10 +47,10 @@ impl StacksChainState { .with_clarity_db_readonly(|ref mut db| { match db.lookup_variable_unknown_descriptor(contract_id, data_var, &epoch) { Ok(c) => Ok(Some(c)), - Err(clarity_vm_error::Unchecked(CheckErrors::NoSuchDataVariable(_))) => { + Err(VmExecutionError::Unchecked(CheckErrorKind::NoSuchDataVariable(_))) => { Ok(None) } - Err(e) => Err(clarity_error::Interpreter(e)), + Err(e) => Err(ClarityError::Interpreter(e)), } }) .map_err(Error::ClarityError) diff --git a/stackslib/src/chainstate/stacks/db/mod.rs b/stackslib/src/chainstate/stacks/db/mod.rs index a72f3f9edc9..865d4c50ff7 100644 --- a/stackslib/src/chainstate/stacks/db/mod.rs +++ b/stackslib/src/chainstate/stacks/db/mod.rs @@ -65,8 +65,8 @@ use crate::chainstate::stacks::{ C32_ADDRESS_VERSION_TESTNET_SINGLESIG, *, }; use crate::clarity_vm::clarity::{ - ClarityBlockConnection, ClarityConnection, ClarityInstance, ClarityReadOnlyConnection, - Error as clarity_error, PreCommitClarityBlock, + ClarityBlockConnection, ClarityConnection, ClarityError, ClarityInstance, + ClarityReadOnlyConnection, PreCommitClarityBlock, }; use crate::clarity_vm::database::marf::MarfedKV; use crate::clarity_vm::database::HeadersDBConn; @@ -544,7 +544,7 @@ impl<'a, 'b> ClarityTx<'a, 'b> { pub fn commit_mined_block( self, block_hash: &StacksBlockId, - ) -> Result { + ) -> Result { Ok(self.block.commit_mined_block(block_hash)?.get_total()) } @@ -1974,7 +1974,7 @@ impl StacksChainState { parent_id_bhh: &StacksBlockId, contract: &QualifiedContractIdentifier, code: &str, - ) -> Result { + ) -> Result { self.clarity_state.eval_read_only( parent_id_bhh, &HeadersDBConn(StacksDBConn::new(&self.state_index, ())), @@ -1994,7 +1994,7 @@ impl StacksChainState { contract: &QualifiedContractIdentifier, function: &str, args: &[Value], - ) -> Result { + ) -> Result { let headers_db = HeadersDBConn(StacksDBConn::new(&self.state_index, ())); let mut conn = self.clarity_state.read_only_connection_checked( parent_id_bhh, diff --git a/stackslib/src/chainstate/stacks/db/transactions.rs b/stackslib/src/chainstate/stacks/db/transactions.rs index 270f61c8425..40e858fdfb6 100644 --- a/stackslib/src/chainstate/stacks/db/transactions.rs +++ b/stackslib/src/chainstate/stacks/db/transactions.rs @@ -21,7 +21,7 @@ use clarity::vm::clarity::TransactionConnection; use clarity::vm::contexts::{AssetMap, AssetMapEntry, Environment}; use clarity::vm::costs::cost_functions::ClarityCostFunction; use clarity::vm::costs::{runtime_cost, CostTracker, ExecutionCost}; -use clarity::vm::errors::Error as InterpreterError; +use clarity::vm::errors::{VmExecutionError, VmInternalError}; use clarity::vm::representations::ClarityName; use clarity::vm::types::{ AssetIdentifier, BuffData, PrincipalData, QualifiedContractIdentifier, SequenceData, @@ -32,9 +32,7 @@ use clarity::vm::types::{ use crate::chainstate::stacks::db::*; use crate::chainstate::stacks::miner::TransactionResult; use crate::chainstate::stacks::{Error, StacksMicroblockHeader}; -use crate::clarity_vm::clarity::{ - ClarityConnection, ClarityTransactionConnection, Error as clarity_error, -}; +use crate::clarity_vm::clarity::{ClarityConnection, ClarityError, ClarityTransactionConnection}; use crate::util_lib::strings::VecDisplay; /// This is a safe-to-hash Clarity value @@ -42,12 +40,12 @@ use crate::util_lib::strings::VecDisplay; struct HashableClarityValue(Value); impl TryFrom for HashableClarityValue { - type Error = InterpreterError; + type Error = VmExecutionError; fn try_from(value: Value) -> Result { // check that serialization _will_ be successful when hashed let _bytes = value.serialize_to_vec().map_err(|_| { - InterpreterError::Interpreter(clarity::vm::errors::InterpreterError::Expect( + VmExecutionError::Internal(VmInternalError::Expect( "Failed to serialize asset in NFT during post-condition checks".into(), )) })?; @@ -191,10 +189,10 @@ impl StacksTransactionReceipt { pub fn from_analysis_failure( tx: StacksTransaction, analysis_cost: ExecutionCost, - error: clarity::vm::clarity::Error, + error: ClarityError, ) -> StacksTransactionReceipt { let error_string = match error { - clarity_error::Analysis(ref check_error) => { + ClarityError::StaticCheck(ref check_error) => { if let Some(span) = check_error.diagnostic.spans.first() { format!( ":{}:{}: {}", @@ -204,7 +202,7 @@ impl StacksTransactionReceipt { check_error.diagnostic.message.to_string() } } - clarity_error::Parse(ref parse_error) => { + ClarityError::Parse(ref parse_error) => { if let Some(span) = parse_error.diagnostic.spans.first() { format!( ":{}:{}: {}", @@ -253,7 +251,7 @@ impl StacksTransactionReceipt { tx: StacksTransaction, cost: ExecutionCost, contract_analysis: ContractAnalysis, - error: CheckErrors, + error: CheckErrorKind, ) -> StacksTransactionReceipt { StacksTransactionReceipt { transaction: tx.into(), @@ -272,7 +270,7 @@ impl StacksTransactionReceipt { pub fn from_runtime_failure_contract_call( tx: StacksTransaction, cost: ExecutionCost, - error: CheckErrors, + error: CheckErrorKind, ) -> StacksTransactionReceipt { StacksTransactionReceipt { transaction: tx.into(), @@ -352,7 +350,7 @@ impl From for MemPoolRejection { pub enum ClarityRuntimeTxError { Acceptable { - error: clarity_error, + error: ClarityError, err_type: &'static str, }, AbortedByCallback { @@ -367,35 +365,35 @@ pub enum ClarityRuntimeTxError { reason: String, }, CostError(ExecutionCost, ExecutionCost), - AnalysisError(CheckErrors), - Rejectable(clarity_error), + AnalysisError(CheckErrorKind), + Rejectable(ClarityError), } -pub fn handle_clarity_runtime_error(error: clarity_error) -> ClarityRuntimeTxError { +pub fn handle_clarity_runtime_error(error: ClarityError) -> ClarityRuntimeTxError { match error { // runtime errors are okay - clarity_error::Interpreter(InterpreterError::Runtime(_, _)) => { + ClarityError::Interpreter(VmExecutionError::Runtime(_, _)) => { ClarityRuntimeTxError::Acceptable { error, err_type: "runtime error", } } - clarity_error::Interpreter(InterpreterError::ShortReturn(_)) => { + ClarityError::Interpreter(VmExecutionError::EarlyReturn(_)) => { ClarityRuntimeTxError::Acceptable { error, err_type: "short return/panic", } } - clarity_error::Interpreter(InterpreterError::Unchecked(check_error)) => { + ClarityError::Interpreter(VmExecutionError::Unchecked(check_error)) => { if check_error.rejectable() { - ClarityRuntimeTxError::Rejectable(clarity_error::Interpreter( - InterpreterError::Unchecked(check_error), + ClarityRuntimeTxError::Rejectable(ClarityError::Interpreter( + VmExecutionError::Unchecked(check_error), )) } else { ClarityRuntimeTxError::AnalysisError(check_error) } } - clarity_error::AbortedByCallback { + ClarityError::AbortedByCallback { output, assets_modified, tx_events, @@ -406,7 +404,7 @@ pub fn handle_clarity_runtime_error(error: clarity_error) -> ClarityRuntimeTxErr tx_events, reason, }, - clarity_error::CostError(cost, budget) => ClarityRuntimeTxError::CostError(cost, budget), + ClarityError::CostError(cost, budget) => ClarityRuntimeTxError::CostError(cost, budget), unhandled_error => ClarityRuntimeTxError::Rejectable(unhandled_error), } } @@ -631,7 +629,7 @@ impl StacksChainState { origin_account: &StacksAccount, asset_map: &AssetMap, txid: Txid, - ) -> Result, InterpreterError> { + ) -> Result, VmExecutionError> { let mut checked_fungible_assets: HashMap> = HashMap::new(); let mut checked_nonfungible_assets: HashMap< @@ -960,7 +958,7 @@ impl StacksChainState { env.add_memory(u64::from( TypeSignature::PrincipalType .size() - .map_err(InterpreterError::from)?, + .map_err(VmExecutionError::from)?, )) .map_err(|e| Error::from_cost_error(e, cost_before.clone(), env.global_context))?; @@ -1209,8 +1207,8 @@ impl StacksChainState { "function_name" => %contract_call.function_name, "function_args" => %VecDisplay(&contract_call.function_args), "error" => %check_error); - return Err(Error::ClarityError(clarity_error::Interpreter( - InterpreterError::Unchecked(check_error), + return Err(Error::ClarityError(ClarityError::Interpreter( + VmExecutionError::Unchecked(check_error), ))); } } @@ -1278,7 +1276,7 @@ impl StacksChainState { Ok(x) => x, Err(e) => { match e { - clarity_error::CostError(ref cost_after, ref budget) => { + ClarityError::CostError(ref cost_after, ref budget) => { warn!("Block compute budget exceeded on {}: cost before={}, after={}, budget={}", tx.txid(), &cost_before, cost_after, budget); return Err(Error::CostOverflowError( cost_before, @@ -1287,13 +1285,13 @@ impl StacksChainState { )); } other_error => { - if let clarity_error::Parse(err) = &other_error { + if let ClarityError::Parse(err) = &other_error { if err.rejectable() { info!("Transaction {} is problematic and should have prevented this block from being relayed", tx.txid()); return Err(Error::ClarityError(other_error)); } } - if let clarity_error::Analysis(err) = &other_error { + if let ClarityError::StaticCheck(err) = &other_error { if err.err.rejectable() { info!("Transaction {} is problematic and should have prevented this block from being relayed", tx.txid()); return Err(Error::ClarityError(other_error)); @@ -1433,8 +1431,8 @@ impl StacksChainState { "txid" => %tx.txid(), "contract" => %contract_id, "error" => %check_error); - return Err(Error::ClarityError(clarity_error::Interpreter( - InterpreterError::Unchecked(check_error), + return Err(Error::ClarityError(ClarityError::Interpreter( + VmExecutionError::Unchecked(check_error), ))); } } @@ -8252,7 +8250,7 @@ pub mod test { None, ) .unwrap_err(); - let Error::ClarityError(clarity_error::BadTransaction(msg)) = &err else { + let Error::ClarityError(ClarityError::BadTransaction(msg)) = &err else { panic!("Unexpected error type"); }; assert!(msg.find("never seen in this fork").is_some()); @@ -9482,7 +9480,7 @@ pub mod test { false, ) .unwrap_err(); - if let Error::ClarityError(clarity_error::Interpreter(InterpreterError::Unchecked( + if let Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( _check_error, ))) = err { @@ -9535,7 +9533,7 @@ pub mod test { false, ) .unwrap_err(); - if let Error::ClarityError(clarity_error::Interpreter(InterpreterError::Unchecked( + if let Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( _check_error, ))) = err { @@ -9586,7 +9584,7 @@ pub mod test { false, ) .unwrap_err(); - if let Error::ClarityError(clarity_error::Interpreter(InterpreterError::Unchecked( + if let Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( _check_error, ))) = err { @@ -9638,7 +9636,7 @@ pub mod test { false, ) .unwrap_err(); - if let Error::ClarityError(clarity_error::Interpreter(InterpreterError::Unchecked( + if let Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( _check_error, ))) = err { @@ -10142,7 +10140,7 @@ pub mod test { false, ) .unwrap_err(); - if let Error::ClarityError(clarity_error::Interpreter(InterpreterError::Unchecked( + if let Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( check_error, ))) = err { @@ -10601,7 +10599,7 @@ pub mod test { false, ) .unwrap_err(); - if let Error::ClarityError(clarity_error::Interpreter(InterpreterError::Unchecked( + if let Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( check_error, ))) = err { @@ -10707,7 +10705,7 @@ pub mod test { false, ) .unwrap_err(); - if let Error::ClarityError(clarity_error::Interpreter(InterpreterError::Unchecked( + if let Error::ClarityError(ClarityError::Interpreter(VmExecutionError::Unchecked( check_error, ))) = err { diff --git a/stackslib/src/chainstate/stacks/events.rs b/stackslib/src/chainstate/stacks/events.rs index b9a716abbb9..daa4984e6b7 100644 --- a/stackslib/src/chainstate/stacks/events.rs +++ b/stackslib/src/chainstate/stacks/events.rs @@ -52,7 +52,7 @@ pub struct StacksTransactionReceipt { pub execution_cost: ExecutionCost, pub microblock_header: Option, pub tx_index: u32, - /// This is really a string-formatted CheckError (which can't be clone()'ed) + /// This is really a string-formatted CheckErrorKind or VmExecutionError (which can't be clone()'ed) pub vm_error: Option, } diff --git a/stackslib/src/chainstate/stacks/miner.rs b/stackslib/src/chainstate/stacks/miner.rs index 32dcc496fd3..470f5f36283 100644 --- a/stackslib/src/chainstate/stacks/miner.rs +++ b/stackslib/src/chainstate/stacks/miner.rs @@ -22,9 +22,9 @@ use std::sync::{Arc, Mutex}; use std::thread::ThreadId; use std::time::Instant; -use clarity::vm::ast::errors::ParseErrors; +use clarity::vm::ast::errors::ParseErrorKind; use clarity::vm::database::BurnStateDB; -use clarity::vm::errors::Error as InterpreterError; +use clarity::vm::errors::VmExecutionError; use serde::Deserialize; use stacks_common::codec::StacksMessageCodec; use stacks_common::types::chainstate::{ @@ -50,7 +50,7 @@ use crate::chainstate::stacks::db::unconfirmed::UnconfirmedState; use crate::chainstate::stacks::db::{ChainstateTx, ClarityTx, StacksChainState}; use crate::chainstate::stacks::events::StacksTransactionReceipt; use crate::chainstate::stacks::{Error, StacksBlockHeader, StacksMicroblockHeader, *}; -use crate::clarity_vm::clarity::{ClarityInstance, Error as clarity_error}; +use crate::clarity_vm::clarity::{ClarityError, ClarityInstance}; use crate::core::mempool::*; use crate::core::*; use crate::monitoring::{ @@ -655,11 +655,11 @@ impl TransactionResult { } // recover original ClarityError ClarityRuntimeTxError::Acceptable { error, .. } => { - if let clarity_error::Parse(ref parse_err) = error { + if let ClarityError::Parse(ref parse_err) = error { info!("Parse error: {}", parse_err; "txid" => %tx.txid()); match *parse_err.err { - ParseErrors::ExpressionStackDepthTooDeep - | ParseErrors::VaryExpressionStackDepthTooDeep => { + ParseErrorKind::ExpressionStackDepthTooDeep + | ParseErrorKind::VaryExpressionStackDepthTooDeep => { info!("Problematic transaction failed AST depth check"; "txid" => %tx.txid()); return (true, Error::ClarityError(error)); } @@ -669,11 +669,11 @@ impl TransactionResult { Error::ClarityError(error) } ClarityRuntimeTxError::CostError(cost, budget) => { - Error::ClarityError(clarity_error::CostError(cost, budget)) + Error::ClarityError(ClarityError::CostError(cost, budget)) } ClarityRuntimeTxError::AnalysisError(e) => { - let clarity_err = Error::ClarityError(clarity_error::Interpreter( - InterpreterError::Unchecked(e), + let clarity_err = Error::ClarityError(ClarityError::Interpreter( + VmExecutionError::Unchecked(e), )); if epoch_id < StacksEpochId::Epoch21 { // this would invalidate the block, so it's problematic @@ -688,7 +688,7 @@ impl TransactionResult { assets_modified, tx_events, reason, - } => Error::ClarityError(clarity_error::AbortedByCallback { + } => Error::ClarityError(ClarityError::AbortedByCallback { output: output.map(Box::new), assets_modified: Box::new(assets_modified), tx_events, diff --git a/stackslib/src/chainstate/stacks/mod.rs b/stackslib/src/chainstate/stacks/mod.rs index 7bf4d87c5df..1dc3d1c88a0 100644 --- a/stackslib/src/chainstate/stacks/mod.rs +++ b/stackslib/src/chainstate/stacks/mod.rs @@ -19,7 +19,7 @@ use std::{error, fmt, io}; use clarity::vm::contexts::GlobalContext; use clarity::vm::costs::{CostErrors, ExecutionCost}; -use clarity::vm::errors::Error as clarity_interpreter_error; +use clarity::vm::errors::VmExecutionError; use clarity::vm::representations::{ClarityName, ContractName}; use clarity::vm::types::{ PrincipalData, QualifiedContractIdentifier, StandardPrincipalData, Value, @@ -43,7 +43,7 @@ use crate::chainstate::burn::ConsensusHash; use crate::chainstate::stacks::db::accounts::MinerReward; use crate::chainstate::stacks::db::{MinerRewardInfo, StacksHeaderInfo}; use crate::chainstate::stacks::index::Error as marf_error; -use crate::clarity_vm::clarity::Error as clarity_error; +use crate::clarity_vm::clarity::ClarityError; use crate::net::Error as net_error; use crate::util_lib::db::Error as db_error; use crate::util_lib::strings::StacksString; @@ -99,7 +99,7 @@ pub enum Error { MicroblockStreamTooLongError, IncompatibleSpendingConditionError, CostOverflowError(ExecutionCost, ExecutionCost, ExecutionCost), - ClarityError(clarity_error), + ClarityError(ClarityError), DBError(db_error), NetError(net_error), CodecError(codec_error), @@ -128,8 +128,8 @@ impl From for Error { } } -impl From for Error { - fn from(e: clarity_error) -> Error { +impl From for Error { + fn from(e: ClarityError) -> Error { Error::ClarityError(e) } } @@ -342,9 +342,9 @@ impl From for Error { } } -impl From for Error { - fn from(e: clarity_interpreter_error) -> Error { - Error::ClarityError(clarity_error::Interpreter(e)) +impl From for Error { + fn from(e: VmExecutionError) -> Error { + Error::ClarityError(ClarityError::Interpreter(e)) } } diff --git a/stackslib/src/chainstate/stacks/tests/block_construction.rs b/stackslib/src/chainstate/stacks/tests/block_construction.rs index 6e49fcf876d..87faa6f6043 100644 --- a/stackslib/src/chainstate/stacks/tests/block_construction.rs +++ b/stackslib/src/chainstate/stacks/tests/block_construction.rs @@ -3961,7 +3961,7 @@ fn test_is_tx_problematic() { expected_txids.push(contract_call_spends_too_much_tx.txid()); // for tenure_id == 4: - // make a contract that, when called, will result in a CheckError at + // make a contract that, when called, will result in a CheckErrorKind at // runtime let runtime_checkerror_trait = " diff --git a/stackslib/src/clarity_cli.rs b/stackslib/src/clarity_cli.rs index 53dfd481cc9..3c3bd361de5 100644 --- a/stackslib/src/clarity_cli.rs +++ b/stackslib/src/clarity_cli.rs @@ -43,7 +43,7 @@ use crate::chainstate::stacks::boot::{ }; use crate::chainstate::stacks::index::ClarityMarfTrieId; use crate::clarity::vm::analysis::contract_interface_builder::build_contract_interface; -use crate::clarity::vm::analysis::errors::CheckError; +use crate::clarity::vm::analysis::errors::StaticCheckError; use crate::clarity::vm::analysis::{AnalysisDatabase, ContractAnalysis}; use crate::clarity::vm::ast::build_ast; use crate::clarity::vm::contexts::{AssetMap, GlobalContext, OwnedEnvironment}; @@ -51,7 +51,7 @@ use crate::clarity::vm::costs::{ExecutionCost, LimitedCostTracker}; use crate::clarity::vm::database::{ BurnStateDB, ClarityDatabase, HeadersDB, STXBalance, NULL_BURN_STATE_DB, }; -use crate::clarity::vm::errors::{Error, InterpreterResult, RuntimeErrorType}; +use crate::clarity::vm::errors::{InterpreterResult, RuntimeError, VmExecutionError}; use crate::clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use crate::clarity::vm::{ analysis, ast, eval_all, ClarityVersion, ContractContext, ContractName, SymbolicExpression, @@ -150,7 +150,7 @@ fn parse( contract_identifier: &QualifiedContractIdentifier, source_code: &str, clarity_version: ClarityVersion, -) -> Result, Error> { +) -> Result, VmExecutionError> { let ast = build_ast( contract_identifier, source_code, @@ -158,7 +158,7 @@ fn parse( clarity_version, DEFAULT_CLI_EPOCH, ) - .map_err(|e| RuntimeErrorType::ASTError(Box::new(e)))?; + .map_err(|e| RuntimeError::ASTError(Box::new(e)))?; Ok(ast.expressions) } @@ -205,7 +205,7 @@ fn run_analysis_free( marf_kv: &mut C, save_contract: bool, clarity_version: ClarityVersion, -) -> Result> { +) -> Result> { analysis::run_analysis( contract_identifier, expressions, @@ -226,7 +226,7 @@ fn run_analysis( marf_kv: &mut C, save_contract: bool, clarity_version: ClarityVersion, -) -> Result> { +) -> Result> { let mainnet = header_db.is_mainnet(); let cost_track = LimitedCostTracker::new( mainnet, @@ -445,7 +445,10 @@ where /// Execute program in a transient environment. To be used only by CLI tools /// for program evaluation, not by consensus critical code. -pub fn vm_execute(program: &str, clarity_version: ClarityVersion) -> Result, Error> { +pub fn vm_execute( + program: &str, + clarity_version: ClarityVersion, +) -> Result, VmExecutionError> { let contract_id = QualifiedContractIdentifier::transient(); let mut contract_context = ContractContext::new(contract_id.clone(), clarity_version); let mut marf = MemoryBackingStore::new(); diff --git a/stackslib/src/clarity_vm/clarity.rs b/stackslib/src/clarity_vm/clarity.rs index 41c60b5fd66..cc8427062f6 100644 --- a/stackslib/src/clarity_vm/clarity.rs +++ b/stackslib/src/clarity_vm/clarity.rs @@ -20,14 +20,14 @@ use std::thread; use clarity::consts::CHAIN_ID_TESTNET; use clarity::vm::analysis::AnalysisDatabase; use clarity::vm::clarity::TransactionConnection; -pub use clarity::vm::clarity::{ClarityConnection, Error}; +pub use clarity::vm::clarity::{ClarityConnection, ClarityError}; use clarity::vm::contexts::{AssetMap, OwnedEnvironment}; use clarity::vm::costs::{CostTracker, ExecutionCost, LimitedCostTracker}; use clarity::vm::database::{ BurnStateDB, ClarityBackingStore, ClarityDatabase, HeadersDB, RollbackWrapper, RollbackWrapperPersistedLog, STXBalance, NULL_BURN_STATE_DB, NULL_HEADER_DB, }; -use clarity::vm::errors::{Error as InterpreterError, InterpreterResult}; +use clarity::vm::errors::{InterpreterResult, VmExecutionError}; use clarity::vm::events::{STXEventType, STXMintEventData}; use clarity::vm::representations::SymbolicExpression; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier, Value}; @@ -273,13 +273,15 @@ pub struct ClarityReadOnlyConnection<'a> { epoch: StacksEpochId, } -impl From for Error { +impl From for ClarityError { fn from(e: ChainstateError) -> Self { match e { - ChainstateError::InvalidStacksTransaction(msg, _) => Error::BadTransaction(msg), - ChainstateError::CostOverflowError(_, after, budget) => Error::CostError(after, budget), + ChainstateError::InvalidStacksTransaction(msg, _) => ClarityError::BadTransaction(msg), + ChainstateError::CostOverflowError(_, after, budget) => { + ClarityError::CostError(after, budget) + } ChainstateError::ClarityError(x) => x, - x => Error::BadTransaction(format!("{:?}", &x)), + x => ClarityError::BadTransaction(x.to_string()), } } } @@ -357,7 +359,7 @@ impl ClarityBlockConnection<'_, '_> { pub fn get_clarity_db_epoch_version( &mut self, burn_state_db: &dyn BurnStateDB, - ) -> Result { + ) -> Result { let mut db = self.datastore.as_clarity_db(self.header_db, burn_state_db); // NOTE: the begin/roll_back shouldn't be necessary with how this gets used in practice, // but is put here defensively. @@ -658,7 +660,7 @@ impl ClarityInstance { conn } - pub fn drop_unconfirmed_state(&mut self, block: &StacksBlockId) -> Result<(), Error> { + pub fn drop_unconfirmed_state(&mut self, block: &StacksBlockId) -> Result<(), ClarityError> { let datastore = self.datastore.begin_unconfirmed(block); datastore.drop_unconfirmed()?; Ok(()) @@ -758,7 +760,7 @@ impl ClarityInstance { at_block: &StacksBlockId, header_db: &'a dyn HeadersDB, burn_state_db: &'a dyn BurnStateDB, - ) -> Result, Error> { + ) -> Result, ClarityError> { let mut datastore = self.datastore.begin_read_only_checked(Some(at_block))?; let epoch = { let mut db = datastore.as_clarity_db(header_db, burn_state_db); @@ -790,7 +792,7 @@ impl ClarityInstance { burn_state_db: &dyn BurnStateDB, contract: &QualifiedContractIdentifier, program: &str, - ) -> Result { + ) -> Result { let mut read_only_conn = self.datastore.begin_read_only(Some(at_block)); let mut clarity_db = read_only_conn.as_clarity_db(header_db, burn_state_db); let epoch_id = { @@ -803,7 +805,7 @@ impl ClarityInstance { let mut env = OwnedEnvironment::new_free(self.mainnet, self.chain_id, clarity_db, epoch_id); env.eval_read_only(contract, program) .map(|(x, _, _)| x) - .map_err(Error::from) + .map_err(ClarityError::from) } pub fn destroy(self) -> MarfedKV { @@ -948,7 +950,10 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { /// before this saves, it updates the metadata headers in /// the sidestore so that they don't get stepped on after /// a miner re-executes a constructed block. - pub fn commit_mined_block(self, bhh: &StacksBlockId) -> Result { + pub fn commit_mined_block( + self, + bhh: &StacksBlockId, + ) -> Result { debug!("Commit mined Clarity datastore to {}", bhh); self.datastore.commit_to_mined_block(bhh)?; @@ -968,7 +973,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { } /// Get the boot code account - fn get_boot_code_account(&mut self) -> Result { + fn get_boot_code_account(&mut self) -> Result { let boot_code_address = boot_code_addr(self.mainnet); let boot_code_nonce = self.with_clarity_db_readonly(|db| { db.get_account_nonce(&boot_code_address.clone().into()) @@ -978,7 +983,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { Ok(boot_code_account) } - pub fn initialize_epoch_2_05(&mut self) -> Result { + pub fn initialize_epoch_2_05(&mut self) -> Result { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1061,7 +1066,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_2_1(&mut self) -> Result, Error> { + pub fn initialize_epoch_2_1(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1247,7 +1252,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_2_2(&mut self) -> Result, Error> { + pub fn initialize_epoch_2_2(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1274,7 +1279,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_2_3(&mut self) -> Result, Error> { + pub fn initialize_epoch_2_3(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1303,7 +1308,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_2_4(&mut self) -> Result, Error> { + pub fn initialize_epoch_2_4(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1433,7 +1438,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_2_5(&mut self) -> Result, Error> { + pub fn initialize_epoch_2_5(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1672,7 +1677,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_3_0(&mut self) -> Result, Error> { + pub fn initialize_epoch_3_0(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1698,7 +1703,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_3_1(&mut self) -> Result, Error> { + pub fn initialize_epoch_3_1(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1724,7 +1729,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_3_2(&mut self) -> Result, Error> { + pub fn initialize_epoch_3_2(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -1829,7 +1834,7 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } - pub fn initialize_epoch_3_3(&mut self) -> Result, Error> { + pub fn initialize_epoch_3_3(&mut self) -> Result, ClarityError> { // use the `using!` statement to ensure that the old cost_tracker is placed // back in all branches after initialization using!(self.cost_track, "cost tracker", |old_cost_tracker| { @@ -2049,7 +2054,7 @@ impl TransactionConnection for ClarityTransactionConnection<'_, '_> { where A: FnOnce(&AssetMap, &mut ClarityDatabase) -> Option, F: FnOnce(&mut OwnedEnvironment) -> Result<(R, AssetMap, Vec), E>, - E: From, + E: From, { using!(self.log, "log", |log| { using!(self.cost_track, "cost tracker", |cost_track| { @@ -2120,9 +2125,9 @@ impl TransactionConnection for ClarityTransactionConnection<'_, '_> { impl ClarityTransactionConnection<'_, '_> { /// Do something to the underlying DB that involves writing. - pub fn with_clarity_db(&mut self, to_do: F) -> Result + pub fn with_clarity_db(&mut self, to_do: F) -> Result where - F: FnOnce(&mut ClarityDatabase) -> Result, + F: FnOnce(&mut ClarityDatabase) -> Result, { using!(self.log, "log", |log| { let rollback_wrapper = RollbackWrapper::from_persisted_log(self.store, log); @@ -2163,7 +2168,7 @@ impl ClarityTransactionConnection<'_, '_> { sender: &PrincipalData, mblock_header_1: &StacksMicroblockHeader, mblock_header_2: &StacksMicroblockHeader, - ) -> Result { + ) -> Result { self.with_abort_callback( |vm_env| { vm_env @@ -2176,7 +2181,7 @@ impl ClarityTransactionConnection<'_, '_> { ) }) }) - .map_err(Error::from) + .map_err(ClarityError::from) }, |_, _| None, ) @@ -2189,7 +2194,7 @@ impl ClarityTransactionConnection<'_, '_> { /// Commit the changes from the edit log. /// panics if there is more than one open savepoint - pub fn commit(mut self) -> Result<(), Error> { + pub fn commit(mut self) -> Result<(), ClarityError> { let log = self .log .take() @@ -2201,7 +2206,7 @@ impl ClarityTransactionConnection<'_, '_> { rollback_wrapper.depth() ); } - rollback_wrapper.commit().map_err(InterpreterError::from)?; + rollback_wrapper.commit().map_err(VmExecutionError::from)?; // now we can reset the memory usage for the edit-log self.cost_track .as_mut() @@ -2225,7 +2230,7 @@ impl ClarityTransactionConnection<'_, '_> { contract: &QualifiedContractIdentifier, method: &str, args: &[SymbolicExpression], - ) -> Result { + ) -> Result { let (result, _, _, _) = self.with_abort_callback( |vm_env| { vm_env @@ -2236,7 +2241,7 @@ impl ClarityTransactionConnection<'_, '_> { method, args, ) - .map_err(Error::from) + .map_err(ClarityError::from) }, |_, _| Some("read-only".to_string()), )?; @@ -2245,9 +2250,9 @@ impl ClarityTransactionConnection<'_, '_> { /// Evaluate a raw Clarity snippit #[cfg(test)] - pub fn clarity_eval_raw(&mut self, code: &str) -> Result { + pub fn clarity_eval_raw(&mut self, code: &str) -> Result { let (result, _, _, _) = self.with_abort_callback( - |vm_env| vm_env.eval_raw(code).map_err(Error::from), + |vm_env| vm_env.eval_raw(code).map_err(ClarityError::from), |_, _| None, )?; Ok(result) @@ -2258,9 +2263,13 @@ impl ClarityTransactionConnection<'_, '_> { &mut self, contract: &QualifiedContractIdentifier, code: &str, - ) -> Result { + ) -> Result { let (result, _, _, _) = self.with_abort_callback( - |vm_env| vm_env.eval_read_only(contract, code).map_err(Error::from), + |vm_env| { + vm_env + .eval_read_only(contract, code) + .map_err(ClarityError::from) + }, |_, _| None, )?; Ok(result) @@ -2273,7 +2282,7 @@ mod tests { use std::path::PathBuf; use clarity::types::chainstate::{BurnchainHeaderHash, SortitionId, StacksAddress}; - use clarity::vm::analysis::errors::CheckErrors; + use clarity::vm::analysis::errors::CheckErrorKind; use clarity::vm::database::{ClarityBackingStore, STXBalance, SqliteConnection}; use clarity::vm::test_util::{TEST_BURN_STATE_DB, TEST_HEADER_DB}; use clarity::vm::types::{StandardPrincipalData, TupleData, Value}; @@ -2675,7 +2684,7 @@ mod tests { // should not be in the marf. assert_eq!( conn.get_contract_hash(&contract_identifier).unwrap_err(), - CheckErrors::NoSuchContract(contract_identifier.to_string()).into() + CheckErrorKind::NoSuchContract(contract_identifier.to_string()).into() ); let sql = conn.get_side_store(); // sqlite only have entries @@ -2821,7 +2830,7 @@ mod tests { // should not be in the marf. assert_eq!( conn.get_contract_hash(&contract_identifier).unwrap_err(), - CheckErrors::NoSuchContract(contract_identifier.to_string()).into() + CheckErrorKind::NoSuchContract(contract_identifier.to_string()).into() ); let sql = conn.get_side_store(); @@ -2932,7 +2941,7 @@ mod tests { ) }) .unwrap_err(); - let result_value = if let Error::AbortedByCallback { output, .. } = e { + let result_value = if let ClarityError::AbortedByCallback { output, .. } = e { output.unwrap() } else { panic!("Expects a AbortedByCallback error") @@ -3283,7 +3292,7 @@ mod tests { )) .unwrap_err() { - Error::CostError(total, limit) => { + ClarityError::CostError(total, limit) => { eprintln!("{}, {}", total, limit); limit.runtime == 100 && total.runtime > 100 } diff --git a/stackslib/src/clarity_vm/database/ephemeral.rs b/stackslib/src/clarity_vm/database/ephemeral.rs index eb6ac7ce53b..b8b42577fae 100644 --- a/stackslib/src/clarity_vm/database/ephemeral.rs +++ b/stackslib/src/clarity_vm/database/ephemeral.rs @@ -21,7 +21,7 @@ use clarity::vm::database::sqlite::{ sqlite_insert_metadata, }; use clarity::vm::database::{ClarityBackingStore, SpecialCaseHandler, SqliteConnection}; -use clarity::vm::errors::{InterpreterError, InterpreterResult, RuntimeErrorType}; +use clarity::vm::errors::{InterpreterResult, RuntimeError, VmInternalError}; use clarity::vm::types::QualifiedContractIdentifier; use rusqlite; use rusqlite::Connection; @@ -67,7 +67,7 @@ impl ClarityMarfStoreTransaction for EphemeralMarfStore<'_> { /// disappear when this instance is dropped /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn commit_metadata_for_trie(&mut self, target: &StacksBlockId) -> InterpreterResult<()> { if let Some(tip) = self.ephemeral_marf.get_open_chain_tip() { self.teardown_views(); @@ -85,7 +85,7 @@ impl ClarityMarfStoreTransaction for EphemeralMarfStore<'_> { /// unless the RAM-only sqlite DB is experiencing problems (which is probably not recoverable). /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn drop_metadata_for_trie(&mut self, target: &StacksBlockId) -> InterpreterResult<()> { self.teardown_views(); let res = SqliteConnection::drop_metadata(self.ephemeral_marf.sqlite_tx(), target); @@ -111,7 +111,7 @@ impl ClarityMarfStoreTransaction for EphemeralMarfStore<'_> { /// transaction, so no disk I/O will be performed. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn drop_unconfirmed(mut self) -> InterpreterResult<()> { if let Some(tip) = self.ephemeral_marf.get_open_chain_tip().cloned() { debug!("Drop unconfirmed MARF trie {}", tip); @@ -127,13 +127,13 @@ impl ClarityMarfStoreTransaction for EphemeralMarfStore<'_> { /// motions just in case any errors would be reported. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn commit_to_processed_block(mut self, target: &StacksBlockId) -> InterpreterResult<()> { if self.ephemeral_marf.get_open_chain_tip().is_some() { self.commit_metadata_for_trie(target)?; let _ = self.ephemeral_marf.commit_to(target).map_err(|e| { error!("Failed to commit to ephemeral MARF block {target}: {e:?}",); - InterpreterError::Expect("Failed to commit to MARF block".into()) + VmInternalError::Expect("Failed to commit to MARF block".into()) })?; } Ok(()) @@ -145,7 +145,7 @@ impl ClarityMarfStoreTransaction for EphemeralMarfStore<'_> { /// motions just in case any errors would be reported. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn commit_to_mined_block(mut self, target: &StacksBlockId) -> InterpreterResult<()> { if let Some(tip) = self.ephemeral_marf.get_open_chain_tip().cloned() { // rollback the side_store @@ -156,7 +156,7 @@ impl ClarityMarfStoreTransaction for EphemeralMarfStore<'_> { self.drop_metadata_for_trie(&tip)?; let _ = self.ephemeral_marf.commit_mined(target).map_err(|e| { error!("Failed to commit to mined MARF block {target}: {e:?}",); - InterpreterError::Expect("Failed to commit to MARF block".into()) + VmInternalError::Expect("Failed to commit to MARF block".into()) })?; } Ok(()) @@ -246,11 +246,11 @@ impl<'a> EphemeralMarfStore<'a> { } /// Test to see if a given tip is in the ephemeral MARF - fn is_ephemeral_tip(&mut self, tip: &StacksBlockId) -> Result { + fn is_ephemeral_tip(&mut self, tip: &StacksBlockId) -> Result { match self.ephemeral_marf.get_root_hash_at(tip) { Ok(_) => Ok(true), Err(Error::NotFoundError) => Ok(false), - Err(e) => Err(InterpreterError::MarfFailure(e.to_string())), + Err(e) => Err(VmInternalError::MarfFailure(e.to_string())), } } @@ -321,7 +321,7 @@ impl<'a> EphemeralMarfStore<'a> { trace!("Ephemeral MarfedKV get not found",); Ok(None) } - Err(e) => Err(InterpreterError::Expect(format!( + Err(e) => Err(VmInternalError::Expect(format!( "ERROR: Unexpected MARF failure: {e:?}" )) .into()), @@ -334,7 +334,7 @@ impl<'a> EphemeralMarfStore<'a> { /// /// Returns Ok(Some(V)) if the key was mapped in eiher MARF /// Returns Ok(None) if the key was not mapped in either MARF - /// Returns Err(InterpreterError(..)) on failure. + /// Returns Err(VmInternalError(..)) on failure. fn get_with_fn( &mut self, key: Key, @@ -397,7 +397,7 @@ impl ClarityBackingStore for EphemeralMarfStore<'_> { .map_err(|e| match e { Error::NotFoundError => { test_debug!("No such block {:?} (NotFoundError)", &bhh); - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) } Error::NonMatchingForks(_bh1, _bh2) => { test_debug!( @@ -406,7 +406,7 @@ impl ClarityBackingStore for EphemeralMarfStore<'_> { BlockHeaderHash(_bh1), BlockHeaderHash(_bh2) ); - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) } _ => panic!("ERROR: Unexpected MARF failure: {}", e), })?; @@ -441,7 +441,7 @@ impl ClarityBackingStore for EphemeralMarfStore<'_> { let side_key = marf_value.to_hex(); let data = SqliteConnection::get(ephemeral_marf.sqlite_conn(), &side_key)? .ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {side_key}", )) })?; @@ -477,7 +477,7 @@ impl ClarityBackingStore for EphemeralMarfStore<'_> { ); let data = SqliteConnection::get(ephemeral_marf.sqlite_conn(), &side_key)? .ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: Ephemeral MARF contained value_hash not found in side storage: {}", side_key )) @@ -509,7 +509,7 @@ impl ClarityBackingStore for EphemeralMarfStore<'_> { let side_key = marf_value.to_hex(); let data = SqliteConnection::get(ephemeral_marf.sqlite_conn(), &side_key)? .ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -544,7 +544,7 @@ impl ClarityBackingStore for EphemeralMarfStore<'_> { let side_key = marf_value.to_hex(); let data = SqliteConnection::get(ephemeral_marf.sqlite_conn(), &side_key)? .ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) diff --git a/stackslib/src/clarity_vm/database/marf.rs b/stackslib/src/clarity_vm/database/marf.rs index c5832fda6aa..04748afe1d4 100644 --- a/stackslib/src/clarity_vm/database/marf.rs +++ b/stackslib/src/clarity_vm/database/marf.rs @@ -24,9 +24,7 @@ use clarity::vm::database::sqlite::{ sqlite_insert_metadata, }; use clarity::vm::database::{ClarityBackingStore, SpecialCaseHandler, SqliteConnection}; -use clarity::vm::errors::{ - IncomparableError, InterpreterError, InterpreterResult, RuntimeErrorType, -}; +use clarity::vm::errors::{IncomparableError, InterpreterResult, RuntimeError, VmInternalError}; use clarity::vm::types::QualifiedContractIdentifier; use rusqlite; use rusqlite::Connection; @@ -70,13 +68,12 @@ impl MarfedKV { ) -> InterpreterResult> { let mut path = PathBuf::from(path_str); - std::fs::create_dir_all(&path) - .map_err(|_| InterpreterError::FailedToCreateDataDirectory)?; + std::fs::create_dir_all(&path).map_err(|_| VmInternalError::FailedToCreateDataDirectory)?; path.push("marf.sqlite"); let marf_path = path .to_str() - .ok_or_else(|| InterpreterError::BadFileName)? + .ok_or_else(|| VmInternalError::BadFileName)? .to_string(); let mut marf_opts = marf_opts.unwrap_or(MARFOpenOpts::default()); @@ -84,10 +81,10 @@ impl MarfedKV { let mut marf: MARF = if unconfirmed { MARF::from_path_unconfirmed(&marf_path, marf_opts) - .map_err(|err| InterpreterError::MarfFailure(err.to_string()))? + .map_err(|err| VmInternalError::MarfFailure(err.to_string()))? } else { MARF::from_path(&marf_path, marf_opts) - .map_err(|err| InterpreterError::MarfFailure(err.to_string()))? + .map_err(|err| VmInternalError::MarfFailure(err.to_string()))? }; if SqliteConnection::check_schema(marf.sqlite_conn()).is_ok() { @@ -97,11 +94,11 @@ impl MarfedKV { let tx = marf .storage_tx() - .map_err(|err| InterpreterError::DBError(err.to_string()))?; + .map_err(|err| VmInternalError::DBError(err.to_string()))?; SqliteConnection::initialize_conn(&tx)?; tx.commit() - .map_err(|err| InterpreterError::SqliteError(IncomparableError { err }))?; + .map_err(|err| VmInternalError::SqliteError(IncomparableError { err }))?; Ok(marf) } @@ -207,7 +204,7 @@ impl MarfedKV { "Failed to open read only connection at {}: {:?}", at_block, &e ); - InterpreterError::MarfFailure(Error::NotFoundError.to_string()) + VmInternalError::MarfFailure(Error::NotFoundError.to_string()) })?; at_block.clone() } else { @@ -297,7 +294,7 @@ impl MarfedKV { "Failed to open read only connection at {}: {:?}", &base_tip, &e ); - InterpreterError::MarfFailure(Error::NotFoundError.to_string()) + VmInternalError::MarfFailure(Error::NotFoundError.to_string()) })?; // set up ephemeral MARF @@ -306,17 +303,17 @@ impl MarfedKV { MARFOpenOpts::new(TrieHashCalculationMode::Deferred, "noop", false), ) .map_err(|e| { - InterpreterError::Expect(format!("Failed to instantiate ephemeral MARF: {:?}", &e)) + VmInternalError::Expect(format!("Failed to instantiate ephemeral MARF: {:?}", &e)) })?; let mut ephemeral_marf = MARF::from_storage(ephemeral_marf_storage); let tx = ephemeral_marf .storage_tx() - .map_err(|err| InterpreterError::DBError(err.to_string()))?; + .map_err(|err| VmInternalError::DBError(err.to_string()))?; SqliteConnection::initialize_conn(&tx)?; tx.commit() - .map_err(|err| InterpreterError::SqliteError(IncomparableError { err }))?; + .map_err(|err| VmInternalError::SqliteError(IncomparableError { err }))?; self.ephemeral_marf = Some(ephemeral_marf); @@ -333,7 +330,7 @@ impl MarfedKV { // attach the disk-backed MARF to the ephemeral MARF EphemeralMarfStore::attach_read_only_marf(&ephemeral_marf, &read_only_marf).map_err( |e| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "Failed to attach read-only MARF to ephemeral MARF: {:?}", &e )) @@ -341,19 +338,19 @@ impl MarfedKV { )?; let mut tx = ephemeral_marf.begin_tx().map_err(|e| { - InterpreterError::Expect(format!("Failed to open ephemeral MARF tx: {:?}", &e)) + VmInternalError::Expect(format!("Failed to open ephemeral MARF tx: {:?}", &e)) })?; tx.begin(&StacksBlockId::sentinel(), ephemeral_next) .map_err(|e| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "Failed to begin first ephemeral MARF block: {:?}", &e )) })?; let ephemeral_marf_store = EphemeralMarfStore::new(read_only_marf, tx).map_err(|e| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "Failed to instantiate ephemeral MARF store: {:?}", &e )) @@ -406,7 +403,7 @@ impl ClarityMarfStoreTransaction for PersistentWritableMarfStore<'_> { /// metadata rows with `self.chain_tip` as their block identifier to have `target` instead. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn commit_metadata_for_trie(&mut self, target: &StacksBlockId) -> InterpreterResult<()> { SqliteConnection::commit_metadata_to(self.marf.sqlite_tx(), &self.chain_tip, target) } @@ -415,7 +412,7 @@ impl ClarityMarfStoreTransaction for PersistentWritableMarfStore<'_> { /// as their block identifier. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn drop_metadata_for_trie(&mut self, target: &StacksBlockId) -> InterpreterResult<()> { SqliteConnection::drop_metadata(self.marf.sqlite_tx(), target) } @@ -438,7 +435,7 @@ impl ClarityMarfStoreTransaction for PersistentWritableMarfStore<'_> { /// also any unconfirmed trie data from the sqlite DB as well as its associated metadata. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn drop_unconfirmed(mut self) -> InterpreterResult<()> { let chain_tip = self.chain_tip.clone(); debug!("Drop unconfirmed MARF trie {}", &chain_tip); @@ -452,13 +449,13 @@ impl ClarityMarfStoreTransaction for PersistentWritableMarfStore<'_> { /// drops this MARF store. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn commit_to_processed_block(mut self, target: &StacksBlockId) -> InterpreterResult<()> { debug!("commit_to({})", target); self.commit_metadata_for_trie(target)?; let _ = self.marf.commit_to(target).map_err(|e| { error!("Failed to commit to MARF block {target}: {e:?}"); - InterpreterError::Expect("Failed to commit to MARF block".into()) + VmInternalError::Expect("Failed to commit to MARF block".into()) })?; Ok(()) } @@ -468,7 +465,7 @@ impl ClarityMarfStoreTransaction for PersistentWritableMarfStore<'_> { /// the transaction and drops this MARF store. /// /// Returns Ok(()) on success - /// Returns Err(InterpreterError(..)) on sqlite failure + /// Returns Err(VmInternalError(..)) on sqlite failure fn commit_to_mined_block(mut self, target: &StacksBlockId) -> InterpreterResult<()> { debug!("commit_mined_block: ({}->{})", &self.chain_tip, target); // rollback the side_store @@ -480,7 +477,7 @@ impl ClarityMarfStoreTransaction for PersistentWritableMarfStore<'_> { self.drop_metadata_for_trie(&chain_tip)?; let _ = self.marf.commit_mined(target).map_err(|e| { error!("Failed to commit to mined MARF block {target}: {e:?}",); - InterpreterError::Expect("Failed to commit to MARF block".into()) + VmInternalError::Expect("Failed to commit to MARF block".into()) })?; Ok(()) } @@ -546,7 +543,7 @@ impl ClarityBackingStore for ReadOnlyMarfStore<'_> { .map_err(|e| match e { Error::NotFoundError => { test_debug!("No such block {:?} (NotFoundError)", &bhh); - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) } Error::NonMatchingForks(_bh1, _bh2) => { test_debug!( @@ -555,7 +552,7 @@ impl ClarityBackingStore for ReadOnlyMarfStore<'_> { BlockHeaderHash(_bh1), BlockHeaderHash(_bh2) ); - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) } _ => panic!("ERROR: Unexpected MARF failure: {}", e), })?; @@ -636,12 +633,12 @@ impl ClarityBackingStore for ReadOnlyMarfStore<'_> { Error::NotFoundError => Ok(None), _ => Err(e), }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|(marf_value, proof)| { let side_key = marf_value.to_hex(); let data = SqliteConnection::get(self.get_side_store(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -661,12 +658,12 @@ impl ClarityBackingStore for ReadOnlyMarfStore<'_> { Error::NotFoundError => Ok(None), _ => Err(e), }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|(marf_value, proof)| { let side_key = marf_value.to_hex(); let data = SqliteConnection::get(self.get_side_store(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -698,11 +695,11 @@ impl ClarityBackingStore for ReadOnlyMarfStore<'_> { Err(e) } }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|marf_value| { let side_key = marf_value.to_hex(); SqliteConnection::get(self.get_side_store(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -727,12 +724,12 @@ impl ClarityBackingStore for ReadOnlyMarfStore<'_> { } _ => Err(e), }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|marf_value| { let side_key = marf_value.to_hex(); trace!("MarfedKV get side-key for {:?}: {:?}", hash, &side_key); SqliteConnection::get(self.get_side_store(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -797,7 +794,7 @@ impl ClarityBackingStore for PersistentWritableMarfStore<'_> { .map_err(|e| match e { Error::NotFoundError => { test_debug!("No such block {:?} (NotFoundError)", &bhh); - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) } Error::NonMatchingForks(_bh1, _bh2) => { test_debug!( @@ -806,7 +803,7 @@ impl ClarityBackingStore for PersistentWritableMarfStore<'_> { BlockHeaderHash(_bh1), BlockHeaderHash(_bh2) ); - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)) } _ => panic!("ERROR: Unexpected MARF failure: {}", e), })?; @@ -836,12 +833,12 @@ impl ClarityBackingStore for PersistentWritableMarfStore<'_> { } _ => Err(e), }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|marf_value| { let side_key = marf_value.to_hex(); trace!("MarfedKV get side-key for {:?}: {:?}", key, &side_key); SqliteConnection::get(self.marf.sqlite_tx(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -866,12 +863,12 @@ impl ClarityBackingStore for PersistentWritableMarfStore<'_> { } _ => Err(e), }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|marf_value| { let side_key = marf_value.to_hex(); trace!("MarfedKV get side-key for {:?}: {:?}", hash, &side_key); SqliteConnection::get(self.marf.sqlite_tx(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -888,12 +885,12 @@ impl ClarityBackingStore for PersistentWritableMarfStore<'_> { Error::NotFoundError => Ok(None), _ => Err(e), }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|(marf_value, proof)| { let side_key = marf_value.to_hex(); let data = SqliteConnection::get(self.marf.sqlite_tx(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -913,12 +910,12 @@ impl ClarityBackingStore for PersistentWritableMarfStore<'_> { Error::NotFoundError => Ok(None), _ => Err(e), }) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure on GET".into()))? .map(|(marf_value, proof)| { let side_key = marf_value.to_hex(); let data = SqliteConnection::get(self.marf.sqlite_tx(), &side_key)?.ok_or_else(|| { - InterpreterError::Expect(format!( + VmInternalError::Expect(format!( "ERROR: MARF contained value_hash not found in side storage: {}", side_key )) @@ -1002,7 +999,7 @@ impl ClarityBackingStore for PersistentWritableMarfStore<'_> { } self.marf .insert_batch(&keys, values) - .map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure".into()).into()) + .map_err(|_| VmInternalError::Expect("ERROR: Unexpected MARF Failure".into()).into()) } fn get_contract_hash( diff --git a/stackslib/src/clarity_vm/database/mod.rs b/stackslib/src/clarity_vm/database/mod.rs index e76aae4dd2c..de9abc35514 100644 --- a/stackslib/src/clarity_vm/database/mod.rs +++ b/stackslib/src/clarity_vm/database/mod.rs @@ -11,7 +11,7 @@ use clarity::vm::database::{ BurnStateDB, ClarityBackingStore, ClarityDatabase, HeadersDB, SpecialCaseHandler, SqliteConnection, NULL_BURN_STATE_DB, NULL_HEADER_DB, }; -use clarity::vm::errors::{InterpreterResult, RuntimeErrorType}; +use clarity::vm::errors::{InterpreterResult, RuntimeError}; use clarity::vm::types::{QualifiedContractIdentifier, TupleData}; use rusqlite::{params, Connection, OptionalExtension, Row}; use stacks_common::types::chainstate::{ @@ -1213,7 +1213,7 @@ impl MemoryBackingStore { impl ClarityBackingStore for MemoryBackingStore { fn set_block_hash(&mut self, bhh: StacksBlockId) -> InterpreterResult { - Err(RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)).into()) + Err(RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)).into()) } fn get_data(&mut self, key: &str) -> InterpreterResult> { diff --git a/stackslib/src/clarity_vm/special.rs b/stackslib/src/clarity_vm/special.rs index 64e41881280..9f01c8526ee 100644 --- a/stackslib/src/clarity_vm/special.rs +++ b/stackslib/src/clarity_vm/special.rs @@ -15,7 +15,7 @@ // along with this program. If not, see . use clarity::vm::contexts::GlobalContext; -use clarity::vm::errors::Error as ClarityError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier, Value}; /// Handle special cases of contract-calls -- namely, those into PoX that should lock up STX @@ -27,7 +27,7 @@ pub fn handle_contract_call_special_cases( function_name: &str, args: &[Value], result: &Value, -) -> Result<(), ClarityError> { +) -> Result<(), VmExecutionError> { pox_locking::handle_contract_call_special_cases( global_context, sender, diff --git a/stackslib/src/clarity_vm/tests/analysis_costs.rs b/stackslib/src/clarity_vm/tests/analysis_costs.rs index 6f4244c74ea..5d60bd86c92 100644 --- a/stackslib/src/clarity_vm/tests/analysis_costs.rs +++ b/stackslib/src/clarity_vm/tests/analysis_costs.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use clarity::vm::clarity::{Error as ClarityError, TransactionConnection}; +use clarity::vm::clarity::{ClarityError, TransactionConnection}; use clarity::vm::costs::ExecutionCost; -use clarity::vm::errors::CheckErrors; +use clarity::vm::errors::CheckErrorKind; use clarity::vm::functions::NativeFunctions; use clarity::vm::test_util::TEST_HEADER_DB; use clarity::vm::tests::{test_only_mainnet_to_chain_id, UnitTestBurnStateDB}; @@ -314,10 +314,10 @@ fn undefined_top_variable_error(#[case] use_mainnet: bool, #[case] epoch: Stacks ClarityVersion::Clarity1, &contract_self, ); - let Err(ClarityError::Analysis(check_error)) = analysis_result else { + let Err(ClarityError::StaticCheck(check_error)) = analysis_result else { panic!("Bad analysis result: {analysis_result:?}"); }; - let CheckErrors::UndefinedVariable(var_name) = *check_error.err else { + let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err else { panic!("Bad analysis error: {check_error:?}"); }; assert_eq!(var_name, "foo".to_string()); diff --git a/stackslib/src/clarity_vm/tests/contracts.rs b/stackslib/src/clarity_vm/tests/contracts.rs index 9f01a0e8549..bc8a2c96dd5 100644 --- a/stackslib/src/clarity_vm/tests/contracts.rs +++ b/stackslib/src/clarity_vm/tests/contracts.rs @@ -15,8 +15,8 @@ // along with this program. If not, see . use clarity::types::StacksEpochId; -use clarity::vm::clarity::Error as ClarityError; -use clarity::vm::errors::{CheckErrors, Error}; +use clarity::vm::clarity::ClarityError; +use clarity::vm::errors::{CheckErrorKind, VmExecutionError}; use clarity::vm::types::SequenceData::Buffer; use clarity::vm::types::{ BuffData, OptionalData, PrincipalData, QualifiedContractIdentifier, TupleData, TypeSignature, @@ -48,8 +48,8 @@ fn test_get_burn_block_info_eval() { let clarity_version = ClarityVersion::default_for_epoch(epoch); let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); - if let Err(ClarityError::Analysis(check_error)) = res { - if let CheckErrors::UnknownFunction(func_name) = *check_error.err { + if let Err(ClarityError::StaticCheck(check_error)) = res { + if let CheckErrorKind::UnknownFunction(func_name) = *check_error.err { assert_eq!(func_name, "get-burn-block-info?"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -69,8 +69,8 @@ fn test_get_burn_block_info_eval() { let clarity_version = ClarityVersion::default_for_epoch(epoch); let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); - if let Err(ClarityError::Analysis(check_error)) = res { - if let CheckErrors::UnknownFunction(func_name) = *check_error.err { + if let Err(ClarityError::StaticCheck(check_error)) = res { + if let CheckErrorKind::UnknownFunction(func_name) = *check_error.err { assert_eq!(func_name, "get-burn-block-info?"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -161,8 +161,8 @@ fn test_get_block_info_eval_v210() { let clarity_version = ClarityVersion::default_for_epoch(epoch); let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); - if let Err(ClarityError::Analysis(check_error)) = res { - if let CheckErrors::NoSuchBlockInfoProperty(name) = *check_error.err { + if let Err(ClarityError::StaticCheck(check_error)) = res { + if let CheckErrorKind::NoSuchBlockInfoProperty(name) = *check_error.err { assert_eq!(name, "block-reward"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -182,8 +182,8 @@ fn test_get_block_info_eval_v210() { let clarity_version = ClarityVersion::default_for_epoch(epoch); let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); - if let Err(ClarityError::Analysis(check_error)) = res { - if let CheckErrors::NoSuchBlockInfoProperty(name) = *check_error.err { + if let Err(ClarityError::StaticCheck(check_error)) = res { + if let CheckErrorKind::NoSuchBlockInfoProperty(name) = *check_error.err { assert_eq!(name, "block-reward"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -282,7 +282,7 @@ fn publish_contract( contract_id: &QualifiedContractIdentifier, contract: &str, version: ClarityVersion, -) -> Result<(), clarity::vm::clarity::Error> { +) -> Result<(), ClarityError> { bc.as_transaction(|tx| { let (ast, analysis) = tx.analyze_smart_contract(contract_id, version, contract)?; tx.initialize_smart_contract( @@ -344,8 +344,8 @@ fn trait_invocation_205_with_stored_principal() { let error = publish_contract(conn, &invoke_contract_id, invoke_contract, clarity_version) .unwrap_err(); match error { - ClarityError::Analysis(ref e) => match *e.err { - CheckErrors::TypeError(..) => (), + ClarityError::StaticCheck(ref e) => match *e.err { + CheckErrorKind::TypeError(..) => (), _ => panic!("Unexpected error: {:?}", error), }, _ => panic!("Unexpected error: {:?}", error), @@ -438,7 +438,7 @@ fn trait_invocation_cross_epoch() { ) .unwrap_err(); - if let ClarityError::Interpreter(Error::Unchecked(CheckErrors::TypeValueError(trait_ref_type, value))) = error { + if let ClarityError::Interpreter(VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(trait_ref_type, value))) = error { assert!(matches!(*trait_ref_type, TypeSignature::TraitReferenceType(_))); } else { panic!("Expected an Interpreter(UncheckedError(TypeValue(TraitReferenceType, Principal))) during Epoch-2.2"); @@ -462,7 +462,7 @@ fn trait_invocation_cross_epoch() { ) .unwrap_err(); - if let ClarityError::Interpreter(Error::Unchecked(CheckErrors::TypeValueError(trait_ref_type, value))) = error { + if let ClarityError::Interpreter(VmExecutionError::Unchecked(CheckErrorKind::TypeValueError(trait_ref_type, value))) = error { assert!(matches!(*trait_ref_type, TypeSignature::TraitReferenceType(_))); } else { panic!("Expected an Interpreter(UncheckedError(TypeValue(TraitReferenceType, Principal))) during Epoch-2.2"); @@ -875,8 +875,8 @@ fn test_block_heights() { ClarityVersion::Clarity1, contract_clarity3, ); - if let Err(ClarityError::Analysis(check_error)) = res { - if let CheckErrors::UndefinedVariable(var_name) = *check_error.err { + if let Err(ClarityError::StaticCheck(check_error)) = res { + if let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err { assert_eq!(var_name, "stacks-block-height"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -909,8 +909,8 @@ fn test_block_heights() { ClarityVersion::Clarity2, contract_clarity3, ); - if let Err(ClarityError::Analysis(check_error)) = res { - if let CheckErrors::UndefinedVariable(var_name) = *check_error.err { + if let Err(ClarityError::StaticCheck(check_error)) = res { + if let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err { assert_eq!(var_name, "stacks-block-height"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -925,8 +925,8 @@ fn test_block_heights() { ClarityVersion::Clarity3, contract_clarity1, ); - if let Err(ClarityError::Analysis(check_error)) = res { - if let CheckErrors::UndefinedVariable(var_name) = *check_error.err { + if let Err(ClarityError::StaticCheck(check_error)) = res { + if let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err { assert_eq!(var_name, "block-height"); } else { panic!("Bad analysis error: {:?}", &check_error); diff --git a/stackslib/src/clarity_vm/tests/costs.rs b/stackslib/src/clarity_vm/tests/costs.rs index 75be448599e..898ee13f653 100644 --- a/stackslib/src/clarity_vm/tests/costs.rs +++ b/stackslib/src/clarity_vm/tests/costs.rs @@ -22,7 +22,7 @@ use clarity::vm::costs::{ DefaultVersion, ExecutionCost, LimitedCostTracker, COSTS_1_NAME, COSTS_2_NAME, COSTS_3_NAME, COSTS_4_NAME, }; -use clarity::vm::errors::Error; +use clarity::vm::errors::VmExecutionError; use clarity::vm::events::StacksTransactionEvent; use clarity::vm::functions::NativeFunctions; use clarity::vm::representations::SymbolicExpression; @@ -174,7 +174,7 @@ fn execute_transaction( contract_identifier: &QualifiedContractIdentifier, tx: &str, args: &[SymbolicExpression], -) -> Result<(Value, AssetMap, Vec), Error> { +) -> Result<(Value, AssetMap, Vec), VmExecutionError> { env.execute_transaction(issuer, None, contract_identifier.clone(), tx, args) } diff --git a/stackslib/src/clarity_vm/tests/forking.rs b/stackslib/src/clarity_vm/tests/forking.rs index ef0f4367db3..2d289b28562 100644 --- a/stackslib/src/clarity_vm/tests/forking.rs +++ b/stackslib/src/clarity_vm/tests/forking.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use clarity::vm::analysis::errors::CheckErrors; +use clarity::vm::analysis::errors::CheckErrorKind; use clarity::vm::contexts::OwnedEnvironment; -use clarity::vm::errors::{Error, InterpreterResult as Result, RuntimeErrorType}; +use clarity::vm::errors::{InterpreterResult as Result, RuntimeError, VmExecutionError}; use clarity::vm::test_util::{ execute, is_committed, is_err_code, symbols_from_values, TEST_BURN_STATE_DB, TEST_HEADER_DB, }; @@ -185,9 +185,9 @@ fn test_at_block_good(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc let resp = branch(x, version, 1, "reset").unwrap_err(); eprintln!("{}", resp); match resp { - Error::Runtime(x, _) => assert_eq!( + VmExecutionError::Runtime(x, _) => assert_eq!( x, - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash::from( + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash::from( vec![2; 32].as_slice() )) ), @@ -219,7 +219,7 @@ fn test_at_block_missing_defines(#[case] version: ClarityVersion, #[case] epoch: owned_env.initialize_contract(c_a, contract, None).unwrap(); } - fn initialize_2(owned_env: &mut OwnedEnvironment) -> Error { + fn initialize_2(owned_env: &mut OwnedEnvironment) -> VmExecutionError { let c_b = QualifiedContractIdentifier::local("contract-b").unwrap(); let contract = "(define-private (problematic-cc) @@ -245,7 +245,7 @@ fn test_at_block_missing_defines(#[case] version: ClarityVersion, #[case] epoch: let err = initialize_2(env); assert_eq!( err, - CheckErrors::NoSuchContract( + CheckErrorKind::NoSuchContract( "S1G2081040G2081040G2081040G208105NK8PE5.contract-a".into() ) .into() diff --git a/stackslib/src/clarity_vm/tests/large_contract.rs b/stackslib/src/clarity_vm/tests/large_contract.rs index 3e1ec77cd0f..06a154ffd1d 100644 --- a/stackslib/src/clarity_vm/tests/large_contract.rs +++ b/stackslib/src/clarity_vm/tests/large_contract.rs @@ -19,7 +19,7 @@ use clarity::vm::ast::stack_depth_checker::AST_CALL_STACK_DEPTH_BUFFER; use clarity::vm::clarity::{ClarityConnection, TransactionConnection}; use clarity::vm::contexts::OwnedEnvironment; use clarity::vm::database::HeadersDB; -use clarity::vm::errors::Error as InterpreterError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::test_util::*; use clarity::vm::tests::{test_clarity_versions, BurnStateDB}; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier, Value}; @@ -35,7 +35,7 @@ use stacks_common::types::StacksEpochId; use crate::chainstate::stacks::boot::{BOOT_CODE_COSTS_2, BOOT_CODE_COSTS_3, BOOT_CODE_COSTS_4}; use crate::chainstate::stacks::index::ClarityMarfTrieId; -use crate::clarity_vm::clarity::{ClarityBlockConnection, ClarityInstance, Error as ClarityError}; +use crate::clarity_vm::clarity::{ClarityBlockConnection, ClarityError, ClarityInstance}; use crate::clarity_vm::database::marf::MarfedKV; use crate::clarity_vm::database::MemoryBackingStore; use crate::util_lib::boot::boot_code_id; @@ -1210,7 +1210,7 @@ fn test_deep_tuples() { }); match error { - ClarityError::Interpreter(InterpreterError::Runtime(r_e, _)) => { + ClarityError::Interpreter(VmExecutionError::Runtime(r_e, _)) => { eprintln!("Runtime error: {:?}", r_e); } other => { @@ -1278,7 +1278,7 @@ fn test_deep_tuples_ast_precheck() { }); match error { - ClarityError::Interpreter(InterpreterError::Runtime(r_e, _)) => { + ClarityError::Interpreter(VmExecutionError::Runtime(r_e, _)) => { eprintln!("Runtime error: {:?}", r_e); } other => { @@ -1349,7 +1349,7 @@ fn test_deep_type_nesting() { }); match error { - ClarityError::Interpreter(InterpreterError::Runtime(r_e, _)) => { + ClarityError::Interpreter(VmExecutionError::Runtime(r_e, _)) => { eprintln!("Runtime error: {:?}", r_e); } other => { diff --git a/stackslib/src/clarity_vm/tests/simple_tests.rs b/stackslib/src/clarity_vm/tests/simple_tests.rs index 9257e0a4abd..dce0049bc63 100644 --- a/stackslib/src/clarity_vm/tests/simple_tests.rs +++ b/stackslib/src/clarity_vm/tests/simple_tests.rs @@ -1,5 +1,5 @@ use clarity::vm::contexts::OwnedEnvironment; -use clarity::vm::errors::{Error, RuntimeErrorType}; +use clarity::vm::errors::{RuntimeError, VmExecutionError}; use clarity::vm::test_util::{TEST_BURN_STATE_DB, TEST_HEADER_DB}; use clarity::vm::types::QualifiedContractIdentifier; use stacks_common::consts::{FIRST_BURNCHAIN_CONSENSUS_HASH, FIRST_STACKS_BLOCK_HASH}; @@ -62,11 +62,9 @@ fn test_at_unknown_block() { .unwrap_err(); eprintln!("{err}"); match err { - Error::Runtime(x, _) => assert_eq!( + VmExecutionError::Runtime(x, _) => assert_eq!( x, - RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash::from( - vec![2; 32].as_slice() - )) + RuntimeError::UnknownBlockHeaderHash(BlockHeaderHash::from(vec![2; 32].as_slice())) ), _ => panic!("Unexpected error"), } diff --git a/stackslib/src/net/api/callreadonly.rs b/stackslib/src/net/api/callreadonly.rs index cc9715b1727..3f62d0ac210 100644 --- a/stackslib/src/net/api/callreadonly.rs +++ b/stackslib/src/net/api/callreadonly.rs @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use clarity::vm::analysis::CheckErrors; +use clarity::vm::analysis::CheckErrorKind; use clarity::vm::ast::parser::v1::CLARITY_NAME_REGEX; use clarity::vm::clarity::ClarityConnection; use clarity::vm::costs::{ExecutionCost, LimitedCostTracker}; -use clarity::vm::errors::Error::Unchecked; +use clarity::vm::errors::VmExecutionError::Unchecked; use clarity::vm::representations::{CONTRACT_NAME_REGEX_STRING, STANDARD_PRINCIPAL_REGEX_STRING}; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::{ClarityName, ContractName, SymbolicExpression, Value}; @@ -265,7 +265,7 @@ impl RPCRequestHandler for RPCCallReadOnlyRequestHandler { } } Ok(Some(Err(e))) => match e { - Unchecked(CheckErrors::CostBalanceExceeded(actual_cost, _)) + Unchecked(CheckErrorKind::CostBalanceExceeded(actual_cost, _)) if actual_cost.write_count > 0 => { CallReadOnlyResponse { diff --git a/stackslib/src/net/api/fastcallreadonly.rs b/stackslib/src/net/api/fastcallreadonly.rs index cabd8c9db2d..67ca10529e2 100644 --- a/stackslib/src/net/api/fastcallreadonly.rs +++ b/stackslib/src/net/api/fastcallreadonly.rs @@ -15,11 +15,11 @@ use std::time::Duration; -use clarity::vm::analysis::CheckErrors; +use clarity::vm::analysis::CheckErrorKind; use clarity::vm::ast::parser::v1::CLARITY_NAME_REGEX; use clarity::vm::clarity::ClarityConnection; use clarity::vm::costs::{ExecutionCost, LimitedCostTracker}; -use clarity::vm::errors::Error::Unchecked; +use clarity::vm::errors::VmExecutionError::Unchecked; use clarity::vm::representations::{CONTRACT_NAME_REGEX_STRING, STANDARD_PRINCIPAL_REGEX_STRING}; use clarity::vm::types::PrincipalData; use clarity::vm::{ClarityName, ContractName, SymbolicExpression, Value}; @@ -266,7 +266,7 @@ impl RPCRequestHandler for RPCFastCallReadOnlyRequestHandler { } } Ok(Some(Err(e))) => match e { - Unchecked(CheckErrors::CostBalanceExceeded(actual_cost, _)) + Unchecked(CheckErrorKind::CostBalanceExceeded(actual_cost, _)) if actual_cost.write_count > 0 => { CallReadOnlyResponse { @@ -275,7 +275,7 @@ impl RPCRequestHandler for RPCFastCallReadOnlyRequestHandler { cause: Some("NotReadOnly".to_string()), } } - Unchecked(CheckErrors::ExecutionTimeExpired) => { + Unchecked(CheckErrorKind::ExecutionTimeExpired) => { return StacksHttpResponse::new_error( &preamble, &HttpRequestTimeout::new("ExecutionTime expired".to_string()), diff --git a/stackslib/src/net/api/postblock_proposal.rs b/stackslib/src/net/api/postblock_proposal.rs index a1170041b9f..3a60f374290 100644 --- a/stackslib/src/net/api/postblock_proposal.rs +++ b/stackslib/src/net/api/postblock_proposal.rs @@ -45,7 +45,7 @@ use crate::chainstate::stacks::miner::{ use crate::chainstate::stacks::{ Error as ChainError, StacksTransaction, TenureChangeCause, TransactionPayload, }; -use crate::clarity_vm::clarity::Error as ClarityError; +use crate::clarity_vm::clarity::ClarityError; use crate::core::mempool::ProposalCallbackReceiver; use crate::net::http::{ http_reason, parse_json, Error, HttpContentType, HttpRequest, HttpRequestContents, diff --git a/stackslib/src/net/mod.rs b/stackslib/src/net/mod.rs index 92d5a5e0f9a..99d0514f88a 100644 --- a/stackslib/src/net/mod.rs +++ b/stackslib/src/net/mod.rs @@ -19,7 +19,7 @@ use std::io::{Read, Write}; use std::net::{IpAddr, SocketAddr}; use std::{error, fmt, io}; -use clarity::vm::errors::Error as InterpreterError; +use clarity::vm::errors::VmExecutionError; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use libstackerdb::{Error as libstackerdb_error, StackerDBChunkData}; use p2p::{DropReason, DropSource}; @@ -48,7 +48,7 @@ use crate::chainstate::stacks::{ Error as chainstate_error, Error as chain_error, StacksBlock, StacksMicroblock, StacksPublicKey, StacksTransaction, }; -use crate::clarity_vm::clarity::Error as clarity_error; +use crate::clarity_vm::clarity::ClarityError; use crate::core::mempool::*; use crate::cost_estimates::metrics::CostMetric; use crate::cost_estimates::{CostEstimator, FeeEstimator}; @@ -203,7 +203,7 @@ pub enum Error { /// MARF error, percolated up from chainstate MARFError(marf_error), /// Clarity VM error, percolated up from chainstate - ClarityError(clarity_error), + ClarityError(ClarityError), /// Catch-all for chainstate errors that don't map cleanly into network errors ChainstateError(String), /// Coordinator hung up @@ -527,14 +527,14 @@ impl From for Error { } } -impl From for Error { - fn from(e: clarity_error) -> Self { +impl From for Error { + fn from(e: ClarityError) -> Self { Error::ClarityError(e) } } -impl From for Error { - fn from(e: InterpreterError) -> Self { +impl From for Error { + fn from(e: VmExecutionError) -> Self { Error::ClarityError(e.into()) } } diff --git a/stackslib/src/net/relay.rs b/stackslib/src/net/relay.rs index 882dd000f87..f19d7263ec1 100644 --- a/stackslib/src/net/relay.rs +++ b/stackslib/src/net/relay.rs @@ -18,7 +18,7 @@ use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; use std::mem; use clarity::vm::ast::ast_check_size; -use clarity::vm::ast::errors::ParseErrors; +use clarity::vm::ast::errors::ParseErrorKind; use clarity::vm::types::{QualifiedContractIdentifier, StacksAddressExtensions}; use clarity::vm::ClarityVersion; use rand::prelude::*; @@ -1806,8 +1806,8 @@ impl Relayer { match ast_res { Ok(_) => {} Err(parse_error) => match *parse_error.err { - ParseErrors::ExpressionStackDepthTooDeep - | ParseErrors::VaryExpressionStackDepthTooDeep => { + ParseErrorKind::ExpressionStackDepthTooDeep + | ParseErrorKind::VaryExpressionStackDepthTooDeep => { // don't include this block info!("Transaction {} is problematic and will not be included, relayed, or built upon", &tx.txid()); return Err(Error::ClarityError(parse_error.into())); diff --git a/stackslib/src/net/tests/mod.rs b/stackslib/src/net/tests/mod.rs index 7762c4b68b6..418dd0e6523 100644 --- a/stackslib/src/net/tests/mod.rs +++ b/stackslib/src/net/tests/mod.rs @@ -965,10 +965,10 @@ impl NakamotoBootPlan { for (receipt, tx) in stacks_receipts.iter().zip(block.txs.iter()) { // transactions processed in the same order assert_eq!(receipt.transaction.txid(), tx.txid()); - // no CheckErrors + // no CheckErrorKind assert!( receipt.vm_error.is_none(), - "Receipt had a CheckErrors: {:?}", + "Receipt had a CheckErrorKind: {:?}", &receipt ); // transaction was not aborted post-hoc diff --git a/stackslib/src/util_lib/strings.rs b/stackslib/src/util_lib/strings.rs index c76dbb6c610..86592ab5e35 100644 --- a/stackslib/src/util_lib/strings.rs +++ b/stackslib/src/util_lib/strings.rs @@ -19,7 +19,7 @@ use std::fmt; use std::io::{Read, Write}; use std::ops::{Deref, DerefMut}; -use clarity::vm::errors::RuntimeErrorType; +use clarity::vm::errors::RuntimeError; use clarity::vm::representations::{ ClarityName, ContractName, MAX_STRING_LEN as CLARITY_MAX_STRING_LENGTH, }; @@ -41,8 +41,8 @@ guarded_string!( "UrlString", URL_STRING_REGEX, CLARITY_MAX_STRING_LENGTH, - RuntimeErrorType, - RuntimeErrorType::BadNameValue + RuntimeError, + RuntimeError::BadNameValue ); /// printable-ASCII-only string, but encodable.