From 9035d7ce92e08094f3c8eee095b9dbb4a2c23349 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 24 Oct 2025 17:41:19 +0100 Subject: [PATCH 01/13] WIP: extract StaticCheckErrorKind from CheckErrorKind --- clarity-types/src/errors/analysis.rs | 1147 ++++++++++++++--- clarity-types/src/errors/mod.rs | 17 +- clarity-types/src/tests/types/mod.rs | 3 +- clarity-types/src/tests/types/signatures.rs | 22 +- clarity-types/src/types/mod.rs | 31 +- clarity-types/src/types/serialization.rs | 37 +- clarity-types/src/types/signatures.rs | 170 +-- clarity/src/vm/analysis/analysis_db.rs | 38 +- .../contract_interface_builder/mod.rs | 10 +- clarity/src/vm/analysis/errors.rs | 2 +- clarity/src/vm/analysis/mod.rs | 30 +- .../src/vm/analysis/read_only_checker/mod.rs | 35 +- .../vm/analysis/read_only_checker/tests.rs | 15 +- clarity/src/vm/analysis/trait_checker/mod.rs | 6 +- .../src/vm/analysis/trait_checker/tests.rs | 49 +- .../src/vm/analysis/type_checker/contexts.rs | 8 +- clarity/src/vm/analysis/type_checker/mod.rs | 6 +- .../analysis/type_checker/v2_05/contexts.rs | 8 +- .../src/vm/analysis/type_checker/v2_05/mod.rs | 117 +- .../type_checker/v2_05/natives/assets.rs | 58 +- .../type_checker/v2_05/natives/maps.rs | 28 +- .../type_checker/v2_05/natives/mod.rs | 127 +- .../type_checker/v2_05/natives/options.rs | 75 +- .../type_checker/v2_05/natives/sequences.rs | 65 +- .../type_checker/v2_05/tests/assets.rs | 80 +- .../type_checker/v2_05/tests/contracts.rs | 16 +- .../analysis/type_checker/v2_05/tests/mod.rs | 340 ++--- .../vm/analysis/type_checker/v2_1/contexts.rs | 10 +- .../src/vm/analysis/type_checker/v2_1/mod.rs | 213 +-- .../type_checker/v2_1/natives/assets.rs | 60 +- .../type_checker/v2_1/natives/maps.rs | 29 +- .../analysis/type_checker/v2_1/natives/mod.rs | 232 ++-- .../type_checker/v2_1/natives/options.rs | 75 +- .../type_checker/v2_1/natives/sequences.rs | 73 +- .../type_checker/v2_1/tests/assets.rs | 80 +- .../type_checker/v2_1/tests/contracts.rs | 123 +- .../analysis/type_checker/v2_1/tests/mod.rs | 631 ++++----- clarity/src/vm/analysis/types.rs | 8 +- clarity/src/vm/clarity.rs | 19 +- clarity/src/vm/errors.rs | 2 +- clarity/src/vm/functions/define.rs | 49 +- clarity/src/vm/functions/mod.rs | 3 +- clarity/src/vm/tests/variables.rs | 299 +++-- clarity/src/vm/types/signatures.rs | 131 +- .../chainstate/stacks/boot/contract_tests.rs | 4 +- ..._block_with_contract_call_success.snap.new | 160 --- stackslib/src/clarity_cli.rs | 5 +- .../src/clarity_vm/tests/analysis_costs.rs | 4 +- stackslib/src/clarity_vm/tests/contracts.rs | 18 +- 49 files changed, 2832 insertions(+), 1936 deletions(-) delete mode 100644 stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__consensus__append_block_with_contract_call_success.snap.new diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index 5efb0843f45..43269e5c6e7 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -136,16 +136,418 @@ impl SyntaxBindingError { } } -impl From for CheckErrorKind { +/// Converts a [`SyntaxBindingError`] into a [`StaticCheckErrorKind`]. +/// Used for propagating binding errors from +/// [`crate::vm::analysis::read_only_checker::ReadOnlyChecker::check_each_expression_is_read_only`] +impl From for StaticCheckErrorKind { 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. +/// Converts a [`SyntaxBindingError`] into a [`CommonCheckErrorKind`]. +/// Used for propagating binding errors from [`crate::vm::functions::handle_binding_list`], +/// which is utilized in both static and runtime analysis to ensure consistent error handling. +impl From for CommonCheckErrorKind { + fn from(e: SyntaxBindingError) -> Self { + CommonCheckErrorKind::BadSyntaxBinding(e) + } +} + +/// Internal set of error variants that are shared exclusively between static analysis (deployment) +// and runtime checking (execution), specifically for validation logic that is implemented in common +// code paths used by both. +/// +/// **This enum is strictly for internal use and is not a part of the public API.** +/// +/// All these variants represent errors that can arise *only* from code executed in both analysis and execution +/// contexts—such as argument count checks, type size limits, or shared cost tracking logic. If an error +/// may be triggered by either context via common logic, it lives here. +/// +/// Importantly, this enum does *not* cover all errors common to both analysis and execution. +/// There are other error shared error variants, but those are generated specifically by logic +/// that is unique to static analysis or unique to execution. These errors are defined separately +/// and do not pass through this enum. Only error cases that can possibly arise from a shared validation +/// flow will appear here. +/// +/// When a `CommonCheckErrorKind` is produced, it is always converted immediately into either a +/// [`StaticCheckErrorKind`] (when encountered during deployment analysis) *or* a +/// [`CheckErrorKind`] (when encountered at runtime). +#[derive(Debug, PartialEq)] +pub enum CommonCheckErrorKind { + // 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 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), + + // 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), + + /// 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), + + /// Could not determine the serialization type for a value during analysis. + CouldNotDetermineSerializationType, + + /// Could not determine the type of an expression during analysis. + CouldNotDetermineType, + + /// Empty tuple is not allowed in Clarity. + EmptyTuplesNotAllowed, + + /// Invalid or malformed signature in a function definition. + DefineFunctionBadSignature, + + /// Name (e.g., variable, function) is already in use within the same scope. + /// The `String` wraps the conflicting name. + NameAlreadyUsed(String), + + /// Invalid binding syntax in a generic construct (e.g., `let`, `match`). + /// The `SyntaxBindingError` wraps the specific binding error. + BadSyntaxBinding(SyntaxBindingError), + + // 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), + + /// Expected a trait identifier (e.g., `.trait-name`) but found an invalid token. + ExpectedTraitIdentifier, + /// 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), +} + +/// An error detected during the static analysis of a smart contract at deployment time. +/// +/// These checks are performed once, before any contract execution occurs, to find issues +/// like type mismatches, invalid function signatures, or incorrect control flow. +#[derive(Debug, PartialEq)] +pub enum StaticCheckErrorKind { + // 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 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 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), + + /// Constructed list exceeds the maximum allowed length during type-checking. + ConstructedListTooLarge, + + // 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), + + /// 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 + /// 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), + /// 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), + /// 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, + + // 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), + + // 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 + /// Referenced data variable does not exist in scope. + /// The `String` wraps the non-existent variable name. + NoSuchDataVariable(String), + + // 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 + /// 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), + + // 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), + /// 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 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 + /// 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 + /// Invalid syntax in a `let` expression, violating binding or structure rules. + BadLetSyntax, + + // 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 variable is not defined in the current scope. + /// The `String` wraps the non-existent variable name. + UndefinedVariable(String), + + // 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 + /// 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, + /// 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, + /// `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), + + /// Attempt to write to contract state in a read-only function. + WriteAttemptedInReadOnly, + /// `at-block` closure must be read-only but contains write operations. + AtBlockClosureMustBeReadOnly, +} + +/// An error that occurs during the runtime analysis of a smart contract at runtime. Could be returnd by: +/// - a contract initialization execution +/// - a contract call execution +/// +/// These errors are found when a contract is executed. They represent dynamic conditions +/// that cannot be determined by static analysis, such as: +/// - Failures based on runtime arguments or state changes. +/// - Value-level type mismatches. #[derive(Debug, PartialEq)] pub enum CheckErrorKind { // Cost checker errors @@ -195,8 +597,6 @@ pub enum CheckErrorKind { // List typing errors /// List elements have mismatched types, violating type consistency. ListTypesMustMatch, - /// Constructed list exceeds the maximum allowed length during type-checking. - ConstructedListTooLarge, // Type mismatch errors /// Expected type does not match the actual type during analysis. @@ -220,15 +620,6 @@ pub enum CheckErrorKind { /// 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), @@ -238,35 +629,19 @@ pub enum CheckErrorKind { /// 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), @@ -287,8 +662,6 @@ pub enum CheckErrorKind { BadBurnFTArguments, // 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), @@ -297,9 +670,6 @@ pub enum CheckErrorKind { 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 /// Referenced data variable does not exist in scope. @@ -307,8 +677,6 @@ pub enum CheckErrorKind { NoSuchDataVariable(String), // 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), @@ -318,13 +686,9 @@ pub enum CheckErrorKind { 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), @@ -348,27 +712,16 @@ pub enum CheckErrorKind { 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. @@ -377,9 +730,6 @@ pub enum CheckErrorKind { /// 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 /// Attempt to apply a non-function value as a function. @@ -389,8 +739,6 @@ pub enum CheckErrorKind { /// 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 /// Invalid syntax in a `let` expression, violating binding or structure rules. @@ -401,8 +749,6 @@ pub enum CheckErrorKind { /// 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), @@ -420,26 +766,8 @@ pub enum CheckErrorKind { /// 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 - /// 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), @@ -448,8 +776,6 @@ pub enum CheckErrorKind { 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), @@ -458,15 +784,11 @@ pub enum CheckErrorKind { /// 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 /// String contains invalid or disallowed characters (e.g., non-ASCII in ASCII strings). @@ -480,17 +802,18 @@ pub enum CheckErrorKind { /// Attempt to write to contract state in a read-only function. WriteAttemptedInReadOnly, - /// `at-block` closure must be read-only but contains write operations. - AtBlockClosureMustBeReadOnly, } #[derive(Debug, PartialEq)] -/// 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. +/// A complete static analysis error, combining the error with diagnostic information. +/// +/// This struct wraps a [`StaticCheckErrorKind`] variant with its source location +/// (like line and column numbers) and the code expression that caused the error. +/// It provides the full context needed to report a clear, actionable error to a +/// developer during contract deployment. pub struct StaticCheckError { /// The specific type-checking or semantic error that occurred. - pub err: Box, + 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. @@ -508,8 +831,17 @@ impl CheckErrorKind { } } +impl StaticCheckErrorKind { + pub fn rejectable(&self) -> bool { + matches!( + self, + StaticCheckErrorKind::SupertypeTooLarge | StaticCheckErrorKind::Expects(_) + ) + } +} + impl StaticCheckError { - pub fn new(err: CheckErrorKind) -> StaticCheckError { + pub fn new(err: StaticCheckErrorKind) -> StaticCheckError { let diagnostic = Diagnostic::err(&err); StaticCheckError { err: Box::new(err), @@ -532,7 +864,7 @@ impl StaticCheckError { self.expressions.replace(exprs.to_vec()); } - pub fn with_expression(err: CheckErrorKind, expr: &SymbolicExpression) -> Self { + pub fn with_expression(err: StaticCheckErrorKind, expr: &SymbolicExpression) -> Self { let mut r = Self::new(err); r.set_expression(expr); r @@ -541,30 +873,42 @@ impl StaticCheckError { impl From<(SyntaxBindingError, &SymbolicExpression)> for StaticCheckError { fn from(e: (SyntaxBindingError, &SymbolicExpression)) -> Self { - Self::with_expression(CheckErrorKind::BadSyntaxBinding(e.0), e.1) + Self::with_expression(StaticCheckErrorKind::BadSyntaxBinding(e.0), e.1) } } -impl From<(CheckErrorKind, &SymbolicExpression)> for StaticCheckError { - fn from(e: (CheckErrorKind, &SymbolicExpression)) -> Self { - let mut ce = Self::new(e.0); +impl From<(CommonCheckErrorKind, &SymbolicExpression)> for StaticCheckError { + fn from(e: (CommonCheckErrorKind, &SymbolicExpression)) -> Self { + let mut ce = Self::new(e.0.into()); ce.set_expression(e.1); ce } } -impl From<(CheckErrorKind, &SymbolicExpression)> for CheckErrorKind { - fn from(e: (CheckErrorKind, &SymbolicExpression)) -> Self { +impl From<(CommonCheckErrorKind, &SymbolicExpression)> for CommonCheckErrorKind { + fn from(e: (CommonCheckErrorKind, &SymbolicExpression)) -> Self { e.0 } } +impl From<(CommonCheckErrorKind, &SymbolicExpression)> for CheckErrorKind { + fn from(e: (CommonCheckErrorKind, &SymbolicExpression)) -> Self { + e.0.into() + } +} + impl fmt::Display for CheckErrorKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self:?}") } } +impl fmt::Display for StaticCheckErrorKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{self:?}") + } +} + impl fmt::Display for StaticCheckError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.err)?; @@ -579,7 +923,30 @@ impl fmt::Display for StaticCheckError { impl From for StaticCheckError { fn from(err: CostErrors) -> Self { - StaticCheckError::from(CheckErrorKind::from(err)) + StaticCheckError::from(StaticCheckErrorKind::from(err)) + } +} + +impl From for StaticCheckErrorKind { + fn from(err: CostErrors) -> Self { + match err { + CostErrors::CostOverflow => StaticCheckErrorKind::CostOverflow, + CostErrors::CostBalanceExceeded(a, b) => { + StaticCheckErrorKind::CostBalanceExceeded(a, b) + } + CostErrors::MemoryBalanceExceeded(a, b) => { + StaticCheckErrorKind::MemoryBalanceExceeded(a, b) + } + CostErrors::CostComputationFailed(s) => StaticCheckErrorKind::CostComputationFailed(s), + CostErrors::CostContractLoadFailure => { + StaticCheckErrorKind::CostComputationFailed("Failed to load cost contract".into()) + } + CostErrors::InterpreterFailure => StaticCheckErrorKind::Expects( + "Unexpected interpreter failure in cost computation".into(), + ), + CostErrors::Expect(s) => StaticCheckErrorKind::Expects(s), + CostErrors::ExecutionTimeExpired => StaticCheckErrorKind::ExecutionTimeExpired, + } } } @@ -602,6 +969,29 @@ impl From for CheckErrorKind { } } +impl From for CommonCheckErrorKind { + fn from(err: CostErrors) -> Self { + match err { + CostErrors::CostOverflow => CommonCheckErrorKind::CostOverflow, + CostErrors::CostBalanceExceeded(a, b) => { + CommonCheckErrorKind::CostBalanceExceeded(a, b) + } + CostErrors::MemoryBalanceExceeded(a, b) => { + CommonCheckErrorKind::MemoryBalanceExceeded(a, b) + } + CostErrors::CostComputationFailed(s) => CommonCheckErrorKind::CostComputationFailed(s), + CostErrors::CostContractLoadFailure => { + CommonCheckErrorKind::CostComputationFailed("Failed to load cost contract".into()) + } + CostErrors::InterpreterFailure => CommonCheckErrorKind::Expects( + "Unexpected interpreter failure in cost computation".into(), + ), + CostErrors::Expect(s) => CommonCheckErrorKind::Expects(s), + CostErrors::ExecutionTimeExpired => CommonCheckErrorKind::ExecutionTimeExpired, + } + } +} + impl error::Error for StaticCheckError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { None @@ -614,30 +1004,166 @@ impl error::Error for CheckErrorKind { } } -impl From for StaticCheckError { - fn from(err: CheckErrorKind) -> Self { +impl From for StaticCheckError { + fn from(err: StaticCheckErrorKind) -> Self { StaticCheckError::new(err) } } +impl From for StaticCheckError { + fn from(err: CommonCheckErrorKind) -> Self { + StaticCheckError::new(StaticCheckErrorKind::from(err)) + } +} + +impl From for CheckErrorKind { + fn from(err: CommonCheckErrorKind) -> Self { + match err { + CommonCheckErrorKind::CostOverflow => CheckErrorKind::CostOverflow, + CommonCheckErrorKind::CostBalanceExceeded(a, b) => { + CheckErrorKind::CostBalanceExceeded(a, b) + } + CommonCheckErrorKind::MemoryBalanceExceeded(a, b) => { + CheckErrorKind::MemoryBalanceExceeded(a, b) + } + CommonCheckErrorKind::CostComputationFailed(s) => { + CheckErrorKind::CostComputationFailed(s) + } + CommonCheckErrorKind::ExecutionTimeExpired => CheckErrorKind::ExecutionTimeExpired, + CommonCheckErrorKind::IncorrectArgumentCount(expected, args) => { + CheckErrorKind::IncorrectArgumentCount(expected, args) + } + CommonCheckErrorKind::RequiresAtLeastArguments(expected, args) => { + CheckErrorKind::RequiresAtLeastArguments(expected, args) + } + CommonCheckErrorKind::RequiresAtMostArguments(expected, args) => { + CheckErrorKind::RequiresAtMostArguments(expected, args) + } + CommonCheckErrorKind::ExpectedName => CheckErrorKind::ExpectedName, + CommonCheckErrorKind::DefineFunctionBadSignature => { + CheckErrorKind::DefineFunctionBadSignature + } + CommonCheckErrorKind::ExpectedTraitIdentifier => { + CheckErrorKind::ExpectedTraitIdentifier + } + CommonCheckErrorKind::Expects(s) => CheckErrorKind::Expects(s), + CommonCheckErrorKind::CouldNotDetermineType => CheckErrorKind::CouldNotDetermineType, + CommonCheckErrorKind::ValueTooLarge => CheckErrorKind::ValueTooLarge, + CommonCheckErrorKind::TypeSignatureTooDeep => CheckErrorKind::TypeSignatureTooDeep, + CommonCheckErrorKind::DefineTraitDuplicateMethod(s) => { + CheckErrorKind::DefineTraitDuplicateMethod(s) + } + CommonCheckErrorKind::DefineTraitBadSignature => { + CheckErrorKind::DefineTraitBadSignature + } + CommonCheckErrorKind::InvalidTypeDescription => CheckErrorKind::InvalidTypeDescription, + CommonCheckErrorKind::SupertypeTooLarge => CheckErrorKind::SupertypeTooLarge, + CommonCheckErrorKind::TypeError(a, b) => CheckErrorKind::TypeError(a, b), + CommonCheckErrorKind::BadSyntaxBinding(e) => CheckErrorKind::BadSyntaxBinding(e), + CommonCheckErrorKind::ValueOutOfBounds => CheckErrorKind::ValueOutOfBounds, + CommonCheckErrorKind::CouldNotDetermineSerializationType => { + CheckErrorKind::CouldNotDetermineSerializationType + } + CommonCheckErrorKind::EmptyTuplesNotAllowed => CheckErrorKind::EmptyTuplesNotAllowed, + CommonCheckErrorKind::NameAlreadyUsed(name) => CheckErrorKind::NameAlreadyUsed(name), + CommonCheckErrorKind::UnknownTypeName(name) => CheckErrorKind::UnknownTypeName(name), + } + } +} + +impl From for StaticCheckErrorKind { + fn from(err: CommonCheckErrorKind) -> Self { + match err { + CommonCheckErrorKind::CostOverflow => StaticCheckErrorKind::CostOverflow, + CommonCheckErrorKind::CostBalanceExceeded(a, b) => { + StaticCheckErrorKind::CostBalanceExceeded(a, b) + } + CommonCheckErrorKind::MemoryBalanceExceeded(a, b) => { + StaticCheckErrorKind::MemoryBalanceExceeded(a, b) + } + CommonCheckErrorKind::CostComputationFailed(s) => { + StaticCheckErrorKind::CostComputationFailed(s) + } + CommonCheckErrorKind::ExecutionTimeExpired => { + StaticCheckErrorKind::ExecutionTimeExpired + } + CommonCheckErrorKind::IncorrectArgumentCount(expected, args) => { + StaticCheckErrorKind::IncorrectArgumentCount(expected, args) + } + CommonCheckErrorKind::RequiresAtLeastArguments(expected, args) => { + StaticCheckErrorKind::RequiresAtLeastArguments(expected, args) + } + CommonCheckErrorKind::RequiresAtMostArguments(expected, args) => { + StaticCheckErrorKind::RequiresAtMostArguments(expected, args) + } + CommonCheckErrorKind::ExpectedName => StaticCheckErrorKind::ExpectedName, + CommonCheckErrorKind::DefineFunctionBadSignature => { + StaticCheckErrorKind::DefineFunctionBadSignature + } + CommonCheckErrorKind::ExpectedTraitIdentifier => { + StaticCheckErrorKind::ExpectedTraitIdentifier + } + CommonCheckErrorKind::Expects(s) => StaticCheckErrorKind::Expects(s), + CommonCheckErrorKind::CouldNotDetermineType => { + StaticCheckErrorKind::CouldNotDetermineType + } + CommonCheckErrorKind::ValueTooLarge => StaticCheckErrorKind::ValueTooLarge, + CommonCheckErrorKind::TypeSignatureTooDeep => { + StaticCheckErrorKind::TypeSignatureTooDeep + } + CommonCheckErrorKind::DefineTraitDuplicateMethod(s) => { + StaticCheckErrorKind::DefineTraitDuplicateMethod(s) + } + CommonCheckErrorKind::DefineTraitBadSignature => { + StaticCheckErrorKind::DefineTraitBadSignature + } + CommonCheckErrorKind::InvalidTypeDescription => { + StaticCheckErrorKind::InvalidTypeDescription + } + CommonCheckErrorKind::SupertypeTooLarge => StaticCheckErrorKind::SupertypeTooLarge, + CommonCheckErrorKind::TypeError(a, b) => StaticCheckErrorKind::TypeError(a, b), + CommonCheckErrorKind::BadSyntaxBinding(e) => StaticCheckErrorKind::BadSyntaxBinding(e), + CommonCheckErrorKind::ValueOutOfBounds => StaticCheckErrorKind::ValueOutOfBounds, + CommonCheckErrorKind::CouldNotDetermineSerializationType => { + StaticCheckErrorKind::CouldNotDetermineSerializationType + } + CommonCheckErrorKind::EmptyTuplesNotAllowed => { + StaticCheckErrorKind::EmptyTuplesNotAllowed + } + CommonCheckErrorKind::NameAlreadyUsed(name) => { + StaticCheckErrorKind::NameAlreadyUsed(name) + } + CommonCheckErrorKind::UnknownTypeName(name) => { + StaticCheckErrorKind::UnknownTypeName(name) + } + } + } +} + #[cfg(any(test, feature = "testing"))] -impl From for String { - fn from(o: CheckErrorKind) -> Self { +impl From for String { + fn from(o: StaticCheckErrorKind) -> Self { o.to_string() } } -pub fn check_argument_count(expected: usize, args: &[T]) -> Result<(), CheckErrorKind> { +pub fn check_argument_count(expected: usize, args: &[T]) -> Result<(), CommonCheckErrorKind> { if args.len() != expected { - Err(CheckErrorKind::IncorrectArgumentCount(expected, args.len())) + Err(CommonCheckErrorKind::IncorrectArgumentCount( + expected, + args.len(), + )) } else { Ok(()) } } -pub fn check_arguments_at_least(expected: usize, args: &[T]) -> Result<(), CheckErrorKind> { +pub fn check_arguments_at_least( + expected: usize, + args: &[T], +) -> Result<(), CommonCheckErrorKind> { if args.len() < expected { - Err(CheckErrorKind::RequiresAtLeastArguments( + Err(CommonCheckErrorKind::RequiresAtLeastArguments( expected, args.len(), )) @@ -646,9 +1172,9 @@ pub fn check_arguments_at_least(expected: usize, args: &[T]) -> Result<(), Ch } } -pub fn check_arguments_at_most(expected: usize, args: &[T]) -> Result<(), CheckErrorKind> { +pub fn check_arguments_at_most(expected: usize, args: &[T]) -> Result<(), CommonCheckErrorKind> { if args.len() > expected { - Err(CheckErrorKind::RequiresAtMostArguments( + Err(CommonCheckErrorKind::RequiresAtMostArguments( expected, args.len(), )) @@ -672,125 +1198,329 @@ fn formatted_expected_types(expected_types: &[TypeSignature]) -> String { expected_types_joined } -impl DiagnosableError for CheckErrorKind { +impl DiagnosableError for StaticCheckErrorKind { fn message(&self) -> String { match &self { - CheckErrorKind::SupertypeTooLarge => "supertype of two types is too large".into(), - CheckErrorKind::Expects(s) => format!("unexpected interpreter behavior: {s}"), - CheckErrorKind::BadMatchOptionSyntax(source) => + StaticCheckErrorKind::SupertypeTooLarge => "supertype of two types is too large".into(), + StaticCheckErrorKind::Expects(s) => format!("unexpected interpreter behavior: {s}"), + StaticCheckErrorKind::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()), - CheckErrorKind::BadMatchResponseSyntax(source) => + StaticCheckErrorKind::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()), - CheckErrorKind::BadMatchInput(t) => + StaticCheckErrorKind::BadMatchInput(t) => format!("match requires an input of either a response or optional, found input: '{t}'"), - 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:?}"), + StaticCheckErrorKind::CostOverflow => "contract execution cost overflowed cost counter".into(), + StaticCheckErrorKind::CostBalanceExceeded(a, b) => format!("contract execution cost exceeded budget: {a:?} > {b:?}"), + StaticCheckErrorKind::MemoryBalanceExceeded(a, b) => format!("contract execution cost exceeded memory budget: {a:?} > {b:?}"), + StaticCheckErrorKind::InvalidTypeDescription => "supplied type description is invalid".into(), + StaticCheckErrorKind::EmptyTuplesNotAllowed => "tuple types may not be empty".into(), + StaticCheckErrorKind::UnknownTypeName(name) => format!("failed to parse type: '{name}'"), + StaticCheckErrorKind::ValueTooLarge => "created a type which was greater than maximum allowed value size".into(), + StaticCheckErrorKind::ValueOutOfBounds => "created a type which value size was out of defined bounds".into(), + StaticCheckErrorKind::TypeSignatureTooDeep => "created a type which was deeper than maximum allowed type depth".into(), + StaticCheckErrorKind::ExpectedName => "expected a name argument to this function".into(), + StaticCheckErrorKind::ConstructedListTooLarge => "reached limit of elements in a sequence".into(), + StaticCheckErrorKind::TypeError(expected_type, found_type) => format!("expecting expression of type '{expected_type}', found '{found_type}'"), + StaticCheckErrorKind::UnionTypeError(expected_types, found_type) => format!("expecting expression of type {}, found '{}'", formatted_expected_types(expected_types), found_type), + StaticCheckErrorKind::ExpectedOptionalType(found_type) => format!("expecting expression of type 'optional', found '{found_type}'"), + StaticCheckErrorKind::ExpectedOptionalOrResponseType(found_type) => format!("expecting expression of type 'optional' or 'response', found '{found_type}'"), + StaticCheckErrorKind::ExpectedResponseType(found_type) => format!("expecting expression of type 'response', found '{found_type}'"), + StaticCheckErrorKind::CouldNotDetermineResponseOkType => "attempted to obtain 'ok' value from response, but 'ok' type is indeterminate".into(), + StaticCheckErrorKind::CouldNotDetermineResponseErrType => "attempted to obtain 'err' value from response, but 'err' type is indeterminate".into(), + StaticCheckErrorKind::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(), + StaticCheckErrorKind::CouldNotDetermineType => "type of expression cannot be determined".into(), + StaticCheckErrorKind::BadTupleFieldName => "invalid tuple field name".into(), + StaticCheckErrorKind::ExpectedTuple(type_signature) => format!("expecting tuple, found '{type_signature}'"), + StaticCheckErrorKind::NoSuchTupleField(field_name, tuple_signature) => format!("cannot find field '{field_name}' in tuple '{tuple_signature}'"), + StaticCheckErrorKind::BadTupleConstruction(message) => format!("invalid tuple syntax: {message}"), + StaticCheckErrorKind::NoSuchDataVariable(var_name) => format!("use of unresolved persisted variable '{var_name}'"), + StaticCheckErrorKind::BadMapName => "invalid map name".into(), + StaticCheckErrorKind::NoSuchMap(map_name) => format!("use of unresolved map '{map_name}'"), + StaticCheckErrorKind::DefineFunctionBadSignature => "invalid function definition".into(), + StaticCheckErrorKind::BadFunctionName => "invalid function name".into(), + StaticCheckErrorKind::BadMapTypeDefinition => "invalid map definition".into(), + StaticCheckErrorKind::PublicFunctionMustReturnResponse(found_type) => format!("public functions must return an expression of type 'response', found '{found_type}'"), + StaticCheckErrorKind::DefineVariableBadSignature => "invalid variable definition".into(), + StaticCheckErrorKind::ReturnTypesMustMatch(type_1, type_2) => format!("detected two execution paths, returning two different expression types (got '{type_1}' and '{type_2}')"), + StaticCheckErrorKind::NoSuchContract(contract_identifier) => format!("use of unresolved contract '{contract_identifier}'"), + StaticCheckErrorKind::NoSuchPublicFunction(contract_identifier, function_name) => format!("contract '{contract_identifier}' has no public function '{function_name}'"), + StaticCheckErrorKind::ContractAlreadyExists(contract_identifier) => format!("contract name '{contract_identifier}' conflicts with existing contract"), + StaticCheckErrorKind::ContractCallExpectName => "missing contract name for call".into(), + StaticCheckErrorKind::ExpectedCallableType(found_type) => format!("expected a callable contract, found {found_type}"), + StaticCheckErrorKind::NoSuchBlockInfoProperty(property_name) => format!("use of block unknown property '{property_name}'"), + StaticCheckErrorKind::NoSuchStacksBlockInfoProperty(property_name) => format!("use of unknown stacks block property '{property_name}'"), + StaticCheckErrorKind::NoSuchTenureInfoProperty(property_name) => format!("use of unknown tenure property '{property_name}'"), + StaticCheckErrorKind::GetBlockInfoExpectPropertyName => "missing property name for block info introspection".into(), + StaticCheckErrorKind::GetBurnBlockInfoExpectPropertyName => "missing property name for burn block info introspection".into(), + StaticCheckErrorKind::GetStacksBlockInfoExpectPropertyName => "missing property name for stacks block info introspection".into(), + StaticCheckErrorKind::GetTenureInfoExpectPropertyName => "missing property name for tenure info introspection".into(), + StaticCheckErrorKind::NameAlreadyUsed(name) => format!("defining '{name}' conflicts with previous value"), + StaticCheckErrorKind::ReservedWord(name) => format!("{name} is a reserved word"), + StaticCheckErrorKind::NonFunctionApplication => "expecting expression of type function".into(), + StaticCheckErrorKind::ExpectedListApplication => "expecting expression of type list".into(), + StaticCheckErrorKind::ExpectedSequence(found_type) => format!("expecting expression of type 'list', 'buff', 'string-ascii' or 'string-utf8' - found '{found_type}'"), + StaticCheckErrorKind::MaxLengthOverflow => format!("expecting a value <= {}", u32::MAX), + StaticCheckErrorKind::BadLetSyntax => "invalid syntax of 'let'".into(), + StaticCheckErrorKind::BadSyntaxBinding(binding_error) => format!("invalid syntax binding: {}", &binding_error.message()), + StaticCheckErrorKind::MaxContextDepthReached => "reached depth limit".into(), + StaticCheckErrorKind::UndefinedVariable(var_name) => format!("use of unresolved variable '{var_name}'"), + StaticCheckErrorKind::RequiresAtLeastArguments(expected, found) => format!("expecting >= {expected} arguments, got {found}"), + StaticCheckErrorKind::RequiresAtMostArguments(expected, found) => format!("expecting < {expected} arguments, got {found}"), + StaticCheckErrorKind::IncorrectArgumentCount(expected_count, found_count) => format!("expecting {expected_count} arguments, got {found_count}"), + StaticCheckErrorKind::IfArmsMustMatch(type_1, type_2) => format!("expression types returned by the arms of 'if' must match (got '{type_1}' and '{type_2}')"), + StaticCheckErrorKind::MatchArmsMustMatch(type_1, type_2) => format!("expression types returned by the arms of 'match' must match (got '{type_1}' and '{type_2}')"), + StaticCheckErrorKind::DefaultTypesMustMatch(type_1, type_2) => format!("expression types passed in 'default-to' must match (got '{type_1}' and '{type_2}')"), + StaticCheckErrorKind::IllegalOrUnknownFunctionApplication(function_name) => format!("use of illegal / unresolved function '{function_name}"), + StaticCheckErrorKind::UnknownFunction(function_name) => format!("use of unresolved function '{function_name}'"), + StaticCheckErrorKind::WriteAttemptedInReadOnly => "expecting read-only statements, detected a writing operation".into(), + StaticCheckErrorKind::AtBlockClosureMustBeReadOnly => "(at-block ...) closures expect read-only statements, but detected a writing operation".into(), + StaticCheckErrorKind::BadTokenName => "expecting an token name as an argument".into(), + StaticCheckErrorKind::DefineNFTBadSignature => "(define-asset ...) expects an asset name and an asset identifier type signature as arguments".into(), + StaticCheckErrorKind::NoSuchNFT(asset_name) => format!("tried to use asset function with a undefined asset ('{asset_name}')"), + StaticCheckErrorKind::NoSuchFT(asset_name) => format!("tried to use token function with a undefined token ('{asset_name}')"), + StaticCheckErrorKind::NoSuchTrait(contract_name, trait_name) => format!("use of unresolved trait {contract_name}.{trait_name}"), + StaticCheckErrorKind::TraitReferenceUnknown(trait_name) => format!("use of undeclared trait <{trait_name}>"), + StaticCheckErrorKind::TraitMethodUnknown(trait_name, func_name) => format!("method '{func_name}' unspecified in trait <{trait_name}>"), + StaticCheckErrorKind::BadTraitImplementation(trait_name, func_name) => format!("invalid signature for method '{func_name}' regarding trait's specification <{trait_name}>"), + StaticCheckErrorKind::ExpectedTraitIdentifier => "expecting expression of type trait identifier".into(), + StaticCheckErrorKind::UnexpectedTraitOrFieldReference => "unexpected use of trait reference or field".into(), + StaticCheckErrorKind::DefineTraitBadSignature => "invalid trait definition".into(), + StaticCheckErrorKind::DefineTraitDuplicateMethod(method_name) => format!("duplicate method name '{method_name}' in trait definition"), + StaticCheckErrorKind::ContractOfExpectsTrait => "trait reference expected".into(), + StaticCheckErrorKind::IncompatibleTrait(expected_trait, actual_trait) => format!("trait '{actual_trait}' is not a compatible with expected trait, '{expected_trait}'"), + StaticCheckErrorKind::TypeAlreadyAnnotatedFailure | StaticCheckErrorKind::CheckerImplementationFailure => { + "internal error - please file an issue on https://github.com/stacks-network/stacks-blockchain".into() + }, + StaticCheckErrorKind::UncheckedIntermediaryResponses => "intermediary responses in consecutive statements must be checked".into(), + StaticCheckErrorKind::CostComputationFailed(s) => format!("contract cost computation failed: {s}"), + StaticCheckErrorKind::CouldNotDetermineSerializationType => "could not determine the input type for the serialization function".into(), + StaticCheckErrorKind::ExecutionTimeExpired => "execution time expired".into(), + } + } + + fn suggestion(&self) -> Option { + match &self { + StaticCheckErrorKind::BadLetSyntax => Some( + "'let' syntax example: (let ((supply 1000) (ttl 60)) )".into(), + ), + StaticCheckErrorKind::TraitReferenceUnknown(_) => Some( + "traits should be either defined, with define-trait, or imported, with use-trait." + .into(), + ), + StaticCheckErrorKind::NoSuchBlockInfoProperty(_) => Some( + "properties available: time, header-hash, burnchain-header-hash, vrf-seed".into(), + ), + _ => None, + } + } +} + +impl DiagnosableError for CheckErrorKind { + fn message(&self) -> String { + match &self { + 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() + ), + 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() + ), + CheckErrorKind::BadMatchInput(t) => format!( + "match requires an input of either a response or optional, found input: '{t}'" + ), + 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::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::ListTypesMustMatch => { + "expecting elements of same type in a list".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::ExpectedOptionalOrResponseValue(found_value) => format!( + "expecting expression of type 'optional' or 'response', found '{found_value}'" + ), + 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::CouldNotDetermineType => { + "type of expression cannot be determined".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::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::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::PublicFunctionMustReturnResponse(found_type) => format!( + "public functions must return an expression of type 'response', found '{found_type}'" + ), + 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::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::GetBlockInfoExpectPropertyName => { + "missing property name for 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::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::ExpectedSequence(found_type) => format!( + "expecting expression of type 'list', 'buff', 'string-ascii' or 'string-utf8' - found '{found_type}'" + ), 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::CircularReference(references) => { + format!("detected circular reference: ({})", references.join(", ")) + } + CheckErrorKind::BadSyntaxBinding(binding_error) => { + format!("invalid syntax binding: {}", &binding_error.message()) + } + 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::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::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::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::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::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::DefineTraitDuplicateMethod(method_name) => { + format!("duplicate method name '{method_name}' in trait definition") + } 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() - }, - 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::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(), } } @@ -804,9 +1534,6 @@ impl DiagnosableError for CheckErrorKind { "traits should be either defined, with define-trait, or imported, with use-trait." .into(), ), - CheckErrorKind::NoSuchBlockInfoProperty(_) => Some( - "properties available: time, header-hash, burnchain-header-hash, vrf-seed".into(), - ), _ => None, } } diff --git a/clarity-types/src/errors/mod.rs b/clarity-types/src/errors/mod.rs index 370a93f88db..4e9948dccf3 100644 --- a/clarity-types/src/errors/mod.rs +++ b/clarity-types/src/errors/mod.rs @@ -20,6 +20,7 @@ pub mod lexer; use std::{error, fmt}; +use analysis::CommonCheckErrorKind; pub use analysis::{CheckErrorKind, StaticCheckError}; pub use ast::{ParseError, ParseErrorKind, ParseResult}; pub use cost::CostErrors; @@ -274,6 +275,14 @@ impl From for VmExecutionError { } } +// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. +// So there shouldn't be any need to convert it to a VmExecutionError. +impl From for VmExecutionError { + fn from(err: CommonCheckErrorKind) -> Self { + VmExecutionError::Unchecked(err.into()) + } +} + impl From for VmExecutionError { fn from(err: CostErrors) -> Self { match err { @@ -300,9 +309,11 @@ impl From for VmExecutionError { } } -impl From<(CheckErrorKind, &SymbolicExpression)> for VmExecutionError { - fn from(err: (CheckErrorKind, &SymbolicExpression)) -> Self { - VmExecutionError::Unchecked(err.0) +// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. +// So there shouldn't be any need to convert it to a VmExecutionError. +impl From<(CommonCheckErrorKind, &SymbolicExpression)> for VmExecutionError { + fn from(err: (CommonCheckErrorKind, &SymbolicExpression)) -> Self { + VmExecutionError::Unchecked(err.0.into()) } } diff --git a/clarity-types/src/tests/types/mod.rs b/clarity-types/src/tests/types/mod.rs index ef0a023a60b..0b9329d93ed 100644 --- a/clarity-types/src/tests/types/mod.rs +++ b/clarity-types/src/tests/types/mod.rs @@ -19,6 +19,7 @@ use rstest::rstest; use stacks_common::types::StacksEpochId; use crate::VmExecutionError; +use crate::errors::analysis::CommonCheckErrorKind; use crate::errors::{CheckErrorKind, RuntimeError, VmInternalError}; use crate::types::{ ASCIIData, BuffData, CharType, ListTypeData, MAX_VALUE_SIZE, PrincipalData, @@ -38,7 +39,7 @@ fn test_constructors() { ); assert_eq!( ListTypeData::new_list(TypeSignature::IntType, MAX_VALUE_SIZE), - Err(CheckErrorKind::ValueTooLarge) + Err(CommonCheckErrorKind::ValueTooLarge) ); assert_eq!( diff --git a/clarity-types/src/tests/types/signatures.rs b/clarity-types/src/tests/types/signatures.rs index 6fecdd77767..a41dbf6ed38 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::CheckErrorKind; +use crate::errors::analysis::CommonCheckErrorKind; use crate::representations::CONTRACT_MAX_NAME_LENGTH; use crate::types::TypeSignature::{BoolType, IntType, ListUnionType, UIntType}; use crate::types::signatures::{CallableSubtype, TypeSignature}; @@ -43,7 +43,7 @@ fn test_buffer_length_try_from_u32_trait() { assert_eq!(MAX_VALUE_SIZE, buffer.get_value()); let err = BufferLength::try_from(MAX_VALUE_SIZE + 1).unwrap_err(); - assert_eq!(CheckErrorKind::ValueTooLarge, err); + assert_eq!(CommonCheckErrorKind::ValueTooLarge, err); } #[test] @@ -55,7 +55,7 @@ fn test_buffer_length_try_from_usize_trait() { assert_eq!(MAX_VALUE_SIZE, buffer.get_value()); let err = BufferLength::try_from(MAX_VALUE_SIZE as usize + 1).unwrap_err(); - assert_eq!(CheckErrorKind::ValueTooLarge, err); + assert_eq!(CommonCheckErrorKind::ValueTooLarge, err); } #[test] @@ -67,10 +67,10 @@ fn test_buffer_length_try_from_i128_trait() { assert_eq!(MAX_VALUE_SIZE, buffer.get_value()); let err = BufferLength::try_from(MAX_VALUE_SIZE as i128 + 1).unwrap_err(); - assert_eq!(CheckErrorKind::ValueTooLarge, err); + assert_eq!(CommonCheckErrorKind::ValueTooLarge, err); let err = BufferLength::try_from(-1_i128).unwrap_err(); - assert_eq!(CheckErrorKind::ValueOutOfBounds, err); + assert_eq!(CommonCheckErrorKind::ValueOutOfBounds, err); } #[test] @@ -229,7 +229,7 @@ fn test_string_utf8_length_try_from_u32_trait() { assert_eq!(MAX_UTF8_VALUE_SIZE, string.get_value()); let err = StringUTF8Length::try_from(MAX_UTF8_VALUE_SIZE + 1).unwrap_err(); - assert_eq!(CheckErrorKind::ValueTooLarge, err); + assert_eq!(CommonCheckErrorKind::ValueTooLarge, err); } #[test] @@ -244,7 +244,7 @@ fn test_string_utf8_length_try_from_usize_trait() { assert_eq!(MAX_UTF8_VALUE_SIZE, string.get_value()); let err = StringUTF8Length::try_from(MAX_UTF8_VALUE_SIZE as usize + 1).unwrap_err(); - assert_eq!(CheckErrorKind::ValueTooLarge, err); + assert_eq!(CommonCheckErrorKind::ValueTooLarge, err); } #[test] @@ -259,10 +259,10 @@ fn test_string_utf8_length_try_from_i128_trait() { assert_eq!(MAX_UTF8_VALUE_SIZE, string.get_value()); let err = StringUTF8Length::try_from(MAX_UTF8_VALUE_SIZE as i128 + 1).unwrap_err(); - assert_eq!(CheckErrorKind::ValueTooLarge, err); + assert_eq!(CommonCheckErrorKind::ValueTooLarge, err); let err = StringUTF8Length::try_from(-1_i128).unwrap_err(); - assert_eq!(CheckErrorKind::ValueOutOfBounds, err); + assert_eq!(CommonCheckErrorKind::ValueOutOfBounds, err); } #[test] @@ -826,11 +826,11 @@ fn test_least_supertype() { for pair in bad_pairs { matches!( TypeSignature::least_supertype_v2_1(&pair.0, &pair.1).unwrap_err(), - CheckErrorKind::TypeError(..) + CommonCheckErrorKind::TypeError(..) ); matches!( TypeSignature::least_supertype_v2_1(&pair.1, &pair.0).unwrap_err(), - CheckErrorKind::TypeError(..) + CommonCheckErrorKind::TypeError(..) ); } } diff --git a/clarity-types/src/types/mod.rs b/clarity-types/src/types/mod.rs index 42ff94e4a9c..9e193391723 100644 --- a/clarity-types/src/types/mod.rs +++ b/clarity-types/src/types/mod.rs @@ -36,6 +36,7 @@ pub use self::signatures::{ AssetIdentifier, BufferLength, ListTypeData, SequenceSubtype, StringSubtype, StringUTF8Length, TupleTypeSignature, TypeSignature, }; +use crate::errors::analysis::CommonCheckErrorKind; use crate::errors::{CheckErrorKind, InterpreterResult as Result, RuntimeError, VmInternalError}; use crate::representations::{ClarityName, ContractName, SymbolicExpression}; @@ -700,7 +701,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; @@ -725,7 +726,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(), ))) @@ -745,9 +746,11 @@ 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(|_| { - CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into()) + CommonCheckErrorKind::Expects( + "ERROR: Too large of a buffer successfully constructed.".into(), + ) })?; Ok(TypeSignature::SequenceType(SequenceSubtype::BufferType( buff_length, @@ -768,9 +771,11 @@ 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(|_| { - CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into()) + CommonCheckErrorKind::Expects( + "ERROR: Too large of a buffer successfully constructed.".into(), + ) })?; Ok(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(buff_length), @@ -794,9 +799,11 @@ 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(|_| { - CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into()) + CommonCheckErrorKind::Expects( + "ERROR: Too large of a buffer successfully constructed.".into(), + ) })?; Ok(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::UTF8(str_len), @@ -812,19 +819,19 @@ impl SequencedValue> for UTF8Data { } 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(|_| { - CheckErrorKind::Expects("Should not have constructed too large of a type.".into()) + CommonCheckErrorKind::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)?, @@ -836,7 +843,7 @@ impl ResponseData { ), }; type_result.map_err(|_| { - CheckErrorKind::Expects("Should not have constructed too large of a type.".into()) + CommonCheckErrorKind::Expects("Should not have constructed too large of a type.".into()) }) } } diff --git a/clarity-types/src/types/serialization.rs b/clarity-types/src/types/serialization.rs index 929b2e43136..019beb38f49 100644 --- a/clarity-types/src/types/serialization.rs +++ b/clarity-types/src/types/serialization.rs @@ -23,6 +23,7 @@ use stacks_common::util::hash::{hex_bytes, to_hex}; use stacks_common::util::retry::BoundReader; use super::{ListTypeData, TupleTypeSignature}; +use crate::errors::analysis::{CommonCheckErrorKind, StaticCheckErrorKind}; use crate::errors::{CheckErrorKind, IncomparableError, VmInternalError}; use crate::representations::{ClarityName, ContractName, MAX_STRING_LEN}; use crate::types::{ @@ -128,6 +129,14 @@ impl From for SerializationError { } } +// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. +// So there shouldn't be any need to convert it to a SerializationError. +impl From for SerializationError { + fn from(e: CommonCheckErrorKind) -> Self { + SerializationError::BadTypeError(CheckErrorKind::from(e)) + } +} + define_u8_enum!(TypePrefix { Int = 0, UInt = 1, @@ -394,7 +403,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 +414,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(CheckErrorKind::CouldNotDetermineSerializationType); + return Err(StaticCheckErrorKind::CouldNotDetermineSerializationType); } TypeSignature::IntType => 16, TypeSignature::UIntType => 16, @@ -417,14 +426,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(|| CheckErrorKind::ValueTooLarge)? + .ok_or_else(|| StaticCheckErrorKind::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(|| CheckErrorKind::ValueTooLarge)? + .ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)? } TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::ASCII( length, @@ -434,7 +443,7 @@ impl TypeSignature { // ascii is 1-byte per character u32::from(length) .checked_add(str_length_encode) - .ok_or_else(|| CheckErrorKind::ValueTooLarge)? + .ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)? } TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::UTF8( length, @@ -445,7 +454,7 @@ impl TypeSignature { u32::from(length) .checked_mul(4) .and_then(|x| x.checked_add(str_length_encode)) - .ok_or_else(|| CheckErrorKind::ValueTooLarge)? + .ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)? } TypeSignature::PrincipalType | TypeSignature::CallableType(_) @@ -468,7 +477,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(|| CheckErrorKind::ValueTooLarge)?; + .ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)?; } total_size } @@ -477,7 +486,7 @@ impl TypeSignature { Ok(size) => size, // if NoType, then this is just serializing a none // value, which is only the type prefix - Err(CheckErrorKind::CouldNotDetermineSerializationType) => 0, + Err(StaticCheckErrorKind::CouldNotDetermineSerializationType) => 0, Err(e) => return Err(e), } } @@ -485,17 +494,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(CheckErrorKind::CouldNotDetermineSerializationType) => (0, true), + Err(StaticCheckErrorKind::CouldNotDetermineSerializationType) => (0, true), Err(e) => return Err(e), }; let err_type_max_size = match err_type.max_serialized_size() { Ok(size) => size, - Err(CheckErrorKind::CouldNotDetermineSerializationType) => { + Err(StaticCheckErrorKind::CouldNotDetermineSerializationType) => { if no_ok_type { // if both the ok type and the error type are NoType, - // throw a CheckErrorKind. This should not be possible, but the check + // throw a StaticCheckErrorKind. This should not be possible, but the check // is done out of caution. - return Err(CheckErrorKind::CouldNotDetermineSerializationType); + return Err(StaticCheckErrorKind::CouldNotDetermineSerializationType); } else { 0 } @@ -505,13 +514,13 @@ impl TypeSignature { cmp::max(ok_type_max_size, err_type_max_size) } TypeSignature::ListUnionType(_) => { - return Err(CheckErrorKind::CouldNotDetermineSerializationType); + return Err(StaticCheckErrorKind::CouldNotDetermineSerializationType); } }; max_output_size .checked_add(type_prefix_size) - .ok_or_else(|| CheckErrorKind::ValueTooLarge) + .ok_or_else(|| StaticCheckErrorKind::ValueTooLarge) } } diff --git a/clarity-types/src/types/signatures.rs b/clarity-types/src/types/signatures.rs index 5f7cee23fb1..7a716fae88e 100644 --- a/clarity-types/src/types/signatures.rs +++ b/clarity-types/src/types/signatures.rs @@ -23,6 +23,7 @@ use serde::{Deserialize, Serialize}; use stacks_common::types::StacksEpochId; use crate::errors::CheckErrorKind; +use crate::errors::analysis::{CommonCheckErrorKind, StaticCheckErrorKind}; use crate::representations::{CONTRACT_MAX_NAME_LENGTH, ClarityName, ContractName}; use crate::types::{ CharType, MAX_TO_ASCII_BUFFER_LEN, MAX_TO_ASCII_RESULT_LEN, MAX_TYPE_DEPTH, @@ -121,11 +122,11 @@ impl BufferLength { /// /// This function is primarily intended for internal runtime use, /// and serves as the central place for all integer validation logic. - fn try_from_i128(data: i128) -> Result { + fn try_from_i128(data: i128) -> Result { if data > (MAX_VALUE_SIZE as i128) { - Err(CheckErrorKind::ValueTooLarge) + Err(CommonCheckErrorKind::ValueTooLarge) } else if data < 0 { - Err(CheckErrorKind::ValueOutOfBounds) + Err(CommonCheckErrorKind::ValueOutOfBounds) } else { Ok(BufferLength(data as u32)) } @@ -161,22 +162,22 @@ impl From for u32 { } impl TryFrom for BufferLength { - type Error = CheckErrorKind; - fn try_from(data: u32) -> Result { + type Error = CommonCheckErrorKind; + fn try_from(data: u32) -> Result { Self::try_from(data as i128) } } impl TryFrom for BufferLength { - type Error = CheckErrorKind; - fn try_from(data: usize) -> Result { + type Error = CommonCheckErrorKind; + fn try_from(data: usize) -> Result { Self::try_from(data as i128) } } impl TryFrom for BufferLength { - type Error = CheckErrorKind; - fn try_from(data: i128) -> Result { + type Error = CommonCheckErrorKind; + fn try_from(data: i128) -> Result { Self::try_from_i128(data) } } @@ -202,11 +203,11 @@ impl StringUTF8Length { /// /// This function is primarily intended for internal runtime use, /// and serves as the central place for all integer validation logic. - fn try_from_i128(value: i128) -> Result { + fn try_from_i128(value: i128) -> Result { if value > MAX_UTF8_VALUE_SIZE as i128 { - Err(CheckErrorKind::ValueTooLarge) + Err(CommonCheckErrorKind::ValueTooLarge) } else if value < 0 { - Err(CheckErrorKind::ValueOutOfBounds) + Err(CommonCheckErrorKind::ValueOutOfBounds) } else { Ok(StringUTF8Length(value as u32)) } @@ -242,22 +243,22 @@ impl From for u32 { } impl TryFrom for StringUTF8Length { - type Error = CheckErrorKind; - fn try_from(data: u32) -> Result { + type Error = CommonCheckErrorKind; + fn try_from(data: u32) -> Result { Self::try_from(data as i128) } } impl TryFrom for StringUTF8Length { - type Error = CheckErrorKind; - fn try_from(data: usize) -> Result { + type Error = CommonCheckErrorKind; + fn try_from(data: usize) -> Result { Self::try_from(data as i128) } } impl TryFrom for StringUTF8Length { - type Error = CheckErrorKind; - fn try_from(data: i128) -> Result { + type Error = CommonCheckErrorKind; + fn try_from(data: i128) -> Result { Self::try_from_i128(data) } } @@ -358,10 +359,10 @@ impl ListTypeData { pub fn new_list( entry_type: TypeSignature, max_len: u32, - ) -> Result { + ) -> Result { let would_be_depth = 1 + entry_type.depth(); if would_be_depth > MAX_TYPE_DEPTH { - return Err(CheckErrorKind::TypeSignatureTooDeep); + return Err(CommonCheckErrorKind::TypeSignatureTooDeep); } let list_data = ListTypeData { @@ -370,9 +371,9 @@ impl ListTypeData { }; let would_be_size = list_data .inner_size()? - .ok_or_else(|| CheckErrorKind::ValueTooLarge)?; + .ok_or_else(|| CommonCheckErrorKind::ValueTooLarge)?; if would_be_size > MAX_VALUE_SIZE { - Err(CheckErrorKind::ValueTooLarge) + Err(CommonCheckErrorKind::ValueTooLarge) } else { Ok(list_data) } @@ -400,13 +401,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(CheckErrorKind::ValueTooLarge) + Err(CommonCheckErrorKind::ValueTooLarge) } else if new_depth > MAX_TYPE_DEPTH { - Err(CheckErrorKind::TypeSignatureTooDeep) + Err(CommonCheckErrorKind::TypeSignatureTooDeep) } else { Ok(OptionalType(Box::new(inner_type))) } @@ -415,14 +416,14 @@ 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(CheckErrorKind::ValueTooLarge) + Err(CommonCheckErrorKind::ValueTooLarge) } else if new_depth > MAX_TYPE_DEPTH { - Err(CheckErrorKind::TypeSignatureTooDeep) + Err(CommonCheckErrorKind::TypeSignatureTooDeep) } else { Ok(ResponseType(Box::new((ok_type, err_type)))) } @@ -436,7 +437,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) } @@ -445,7 +446,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 @@ -457,13 +458,13 @@ impl TypeSignature { | StacksEpochId::Epoch31 | StacksEpochId::Epoch32 | StacksEpochId::Epoch33 => self.admits_type_v2_1(other), - StacksEpochId::Epoch10 => { - Err(CheckErrorKind::Expects("epoch 1.0 not supported".into())) - } + StacksEpochId::Epoch10 => Err(CommonCheckErrorKind::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 { @@ -545,18 +546,18 @@ impl TypeSignature { Ok(false) } } - NoType => Err(CheckErrorKind::CouldNotDetermineType), - CallableType(_) => Err(CheckErrorKind::Expects( + NoType => Err(CommonCheckErrorKind::CouldNotDetermineType), + CallableType(_) => Err(CommonCheckErrorKind::Expects( "CallableType should not be used in epoch v2.0".into(), )), - ListUnionType(_) => Err(CheckErrorKind::Expects( + ListUnionType(_) => Err(CommonCheckErrorKind::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(_) => { @@ -645,7 +646,7 @@ impl TypeSignature { Ok(false) } } - NoType => Err(CheckErrorKind::CouldNotDetermineType), + NoType => Err(CommonCheckErrorKind::CouldNotDetermineType), _ => Ok(&other == self), } } @@ -702,7 +703,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; @@ -711,7 +712,7 @@ impl TypeSignature { match partial { CallableSubtype::Principal(_) => { if is_trait.is_some() { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::CallableType(partial.clone())), Box::new(TypeSignature::PrincipalType), )); @@ -721,7 +722,7 @@ impl TypeSignature { } CallableSubtype::Trait(t) => { if is_principal { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::CallableType(partial.clone())), )); @@ -744,12 +745,12 @@ impl TypeSignature { } impl TryFrom> for TupleTypeSignature { - type Error = CheckErrorKind; + type Error = CommonCheckErrorKind; fn try_from( type_data: Vec<(ClarityName, TypeSignature)>, - ) -> Result { + ) -> Result { if type_data.is_empty() { - return Err(CheckErrorKind::EmptyTuplesNotAllowed); + return Err(CommonCheckErrorKind::EmptyTuplesNotAllowed); } let mut type_map = BTreeMap::new(); @@ -757,7 +758,7 @@ impl TryFrom> for TupleTypeSignature { if let Entry::Vacant(e) = type_map.entry(name.clone()) { e.insert(type_info); } else { - return Err(CheckErrorKind::NameAlreadyUsed(name.into())); + return Err(CommonCheckErrorKind::NameAlreadyUsed(name.into())); } } TupleTypeSignature::try_from(type_map) @@ -765,25 +766,25 @@ impl TryFrom> for TupleTypeSignature { } impl TryFrom> for TupleTypeSignature { - type Error = CheckErrorKind; + type Error = CommonCheckErrorKind; fn try_from( type_map: BTreeMap, - ) -> Result { + ) -> Result { if type_map.is_empty() { - return Err(CheckErrorKind::EmptyTuplesNotAllowed); + return Err(CommonCheckErrorKind::EmptyTuplesNotAllowed); } for child_sig in type_map.values() { if (1 + child_sig.depth()) > MAX_TYPE_DEPTH { - return Err(CheckErrorKind::TypeSignatureTooDeep); + return Err(CommonCheckErrorKind::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(|| CheckErrorKind::ValueTooLarge)?; + .ok_or_else(|| CommonCheckErrorKind::ValueTooLarge)?; if would_be_size > MAX_VALUE_SIZE { - Err(CheckErrorKind::ValueTooLarge) + Err(CommonCheckErrorKind::ValueTooLarge) } else { Ok(result) } @@ -813,7 +814,7 @@ impl TupleTypeSignature { &self, epoch: &StacksEpochId, other: &TupleTypeSignature, - ) -> Result { + ) -> Result { if self.type_map.len() != other.type_map.len() { return Ok(false); } @@ -923,7 +924,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() { @@ -974,7 +975,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 @@ -986,16 +987,16 @@ impl TypeSignature { | StacksEpochId::Epoch31 | StacksEpochId::Epoch32 | StacksEpochId::Epoch33 => Self::least_supertype_v2_1(a, b), - StacksEpochId::Epoch10 => { - Err(CheckErrorKind::Expects("epoch 1.0 not supported".into())) - } + StacksEpochId::Epoch10 => Err(CommonCheckErrorKind::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 }), @@ -1003,7 +1004,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(CheckErrorKind::TypeError( + let entry_b = types_b.get(name).ok_or(CommonCheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), ))?; @@ -1012,7 +1013,7 @@ impl TypeSignature { } Ok(TupleTypeSignature::try_from(type_map_out) .map(|x| x.into()) - .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) + .map_err(|_| CommonCheckErrorKind::SupertypeTooLarge)?) } ( SequenceType(SequenceSubtype::ListType(ListTypeData { @@ -1033,7 +1034,7 @@ impl TypeSignature { }; let max_len = cmp::max(len_a, len_b); Ok(Self::list_of(entry_type, *max_len) - .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) + .map_err(|_| CommonCheckErrorKind::SupertypeTooLarge)?) } (ResponseType(resp_a), ResponseType(resp_b)) => { let ok_type = @@ -1092,7 +1093,7 @@ impl TypeSignature { if x == y { Ok(x.clone()) } else { - Err(CheckErrorKind::TypeError( + Err(CommonCheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), )) @@ -1104,7 +1105,7 @@ impl TypeSignature { pub fn least_supertype_v2_1( a: &TypeSignature, b: &TypeSignature, - ) -> Result { + ) -> Result { match (a, b) { ( TupleType(TupleTypeSignature { type_map: types_a }), @@ -1112,7 +1113,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(CheckErrorKind::TypeError( + let entry_b = types_b.get(name).ok_or(CommonCheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), ))?; @@ -1121,7 +1122,7 @@ impl TypeSignature { } Ok(TupleTypeSignature::try_from(type_map_out) .map(|x| x.into()) - .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) + .map_err(|_| CommonCheckErrorKind::SupertypeTooLarge)?) } ( SequenceType(SequenceSubtype::ListType(ListTypeData { @@ -1142,7 +1143,7 @@ impl TypeSignature { }; let max_len = cmp::max(len_a, len_b); Ok(Self::list_of(entry_type, *max_len) - .map_err(|_| CheckErrorKind::SupertypeTooLarge)?) + .map_err(|_| CommonCheckErrorKind::SupertypeTooLarge)?) } (ResponseType(resp_a), ResponseType(resp_b)) => { let ok_type = @@ -1223,7 +1224,7 @@ impl TypeSignature { if all_principals { Ok(PrincipalType) } else { - Err(CheckErrorKind::TypeError( + Err(CommonCheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), )) @@ -1236,7 +1237,7 @@ impl TypeSignature { if x == y { Ok(x.clone()) } else { - Err(CheckErrorKind::TypeError( + Err(CommonCheckErrorKind::TypeError( Box::new(a.clone()), Box::new(b.clone()), )) @@ -1248,7 +1249,7 @@ impl TypeSignature { pub fn list_of( item_type: TypeSignature, max_len: u32, - ) -> Result { + ) -> Result { ListTypeData::new_list(item_type, max_len).map(|x| x.into()) } @@ -1259,7 +1260,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, @@ -1288,7 +1289,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()), @@ -1299,18 +1300,21 @@ impl TypeSignature { // Checks if resulting type signature is of valid size. pub fn construct_parent_list_type(args: &[Value]) -> Result { - let children_types: Result, CheckErrorKind> = + let children_types: Result, CommonCheckErrorKind> = args.iter().map(TypeSignature::type_of).collect(); - TypeSignature::parent_list_type(&children_types?) + Ok(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(|_| CheckErrorKind::ValueTooLarge)?; + let len = + u32::try_from(children.len()).map_err(|_| CommonCheckErrorKind::ValueTooLarge)?; ListTypeData::new_list(current_entry_type, len) } else { Ok(TypeSignature::empty_list()) @@ -1350,16 +1354,16 @@ impl TypeSignature { } } - pub fn size(&self) -> Result { + pub fn size(&self) -> Result { self.inner_size()?.ok_or_else(|| { - CheckErrorKind::Expects( + CommonCheckErrorKind::Expects( "FAIL: .size() overflowed on too large of a type. construction should have failed!" .into(), ) }) } - fn inner_size(&self) -> Result, CheckErrorKind> { + fn inner_size(&self) -> Result, CommonCheckErrorKind> { 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). @@ -1392,9 +1396,9 @@ impl TypeSignature { Ok(out) } - pub fn type_size(&self) -> Result { + pub fn type_size(&self) -> Result { self.inner_type_size() - .ok_or_else(|| CheckErrorKind::ValueTooLarge) + .ok_or_else(|| CommonCheckErrorKind::ValueTooLarge) } /// Returns the size of the _type signature_ @@ -1424,7 +1428,7 @@ impl TypeSignature { impl ListTypeData { /// List Size: type_signature_size + max_len * entry_type.size() - fn inner_size(&self) -> Result, CheckErrorKind> { + fn inner_size(&self) -> Result, CommonCheckErrorKind> { let total_size = self .entry_type .size()? @@ -1490,7 +1494,7 @@ impl TupleTypeSignature { /// Tuple Size: /// size( btreemap ) + type_size /// size( btreemap ) = 2*map.len() + sum(names) + sum(values) - fn inner_size(&self) -> Result, CheckErrorKind> { + fn inner_size(&self) -> Result, CommonCheckErrorKind> { let Some(mut total_size) = u32::try_from(self.type_map.len()) .ok() .and_then(|x| x.checked_mul(2)) diff --git a/clarity/src/vm/analysis/analysis_db.rs b/clarity/src/vm/analysis/analysis_db.rs index 62c28813ca0..ff7197249f6 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::{CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind}; 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| CheckErrorKind::Expects(format!("{e:?}")))?; + .map_err(|e| StaticCheckErrorKind::Expects(format!("{e:?}")))?; Err(e) })?; self.commit() - .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")))?; + .map_err(|e| StaticCheckErrorKind::Expects(format!("{e:?}")))?; Ok(result) } @@ -66,13 +66,13 @@ impl<'a> AnalysisDatabase<'a> { pub fn commit(&mut self) -> Result<(), StaticCheckError> { self.store .commit() - .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()) + .map_err(|e| StaticCheckErrorKind::Expects(format!("{e:?}")).into()) } pub fn roll_back(&mut self) -> Result<(), StaticCheckError> { self.store .rollback() - .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()) + .map_err(|e| StaticCheckErrorKind::Expects(format!("{e:?}")).into()) } pub fn storage_key() -> &'static str { @@ -108,7 +108,7 @@ impl<'a> AnalysisDatabase<'a> { .flatten() .map(|x| { ContractAnalysis::deserialize(&x).map_err(|_| { - CheckErrorKind::Expects("Bad data deserialized from DB".into()).into() + StaticCheckErrorKind::Expects("Bad data deserialized from DB".into()).into() }) }) .transpose() @@ -127,8 +127,9 @@ impl<'a> AnalysisDatabase<'a> { .ok() .flatten() .map(|x| { - ContractAnalysis::deserialize(&x) - .map_err(|_| CheckErrorKind::Expects("Bad data deserialized from DB".into())) + ContractAnalysis::deserialize(&x).map_err(|_| { + StaticCheckErrorKind::Expects("Bad data deserialized from DB".into()) + }) }) .transpose()? .map(|mut x| { @@ -144,14 +145,15 @@ impl<'a> AnalysisDatabase<'a> { ) -> Result<(), StaticCheckError> { let key = AnalysisDatabase::storage_key(); if self.store.has_metadata_entry(contract_identifier, key) { - return Err( - CheckErrorKind::ContractAlreadyExists(contract_identifier.to_string()).into(), - ); + return Err(StaticCheckErrorKind::ContractAlreadyExists( + contract_identifier.to_string(), + ) + .into()); } self.store .insert_metadata(contract_identifier, key, &contract.serialize()) - .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")))?; + .map_err(|e| StaticCheckErrorKind::Expects(format!("{e:?}")))?; Ok(()) } @@ -165,7 +167,7 @@ impl<'a> AnalysisDatabase<'a> { // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( contract_identifier.to_string(), ))?; Ok(contract.clarity_version) @@ -183,7 +185,7 @@ impl<'a> AnalysisDatabase<'a> { // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( contract_identifier.to_string(), ))?; Ok(contract @@ -203,7 +205,7 @@ impl<'a> AnalysisDatabase<'a> { // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( contract_identifier.to_string(), ))?; Ok(contract @@ -223,7 +225,7 @@ impl<'a> AnalysisDatabase<'a> { // charges based on the function type size. let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( contract_identifier.to_string(), ))?; Ok(contract.get_defined_trait(trait_name).map(|trait_map| { @@ -240,7 +242,7 @@ impl<'a> AnalysisDatabase<'a> { ) -> Result, StaticCheckError> { let contract = self .load_contract_non_canonical(contract_identifier)? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( contract_identifier.to_string(), ))?; Ok(contract.implemented_traits) diff --git a/clarity/src/vm/analysis/contract_interface_builder/mod.rs b/clarity/src/vm/analysis/contract_interface_builder/mod.rs index 5fc0169c5cb..54f1a161cf7 100644 --- a/clarity/src/vm/analysis/contract_interface_builder/mod.rs +++ b/clarity/src/vm/analysis/contract_interface_builder/mod.rs @@ -19,12 +19,12 @@ use std::collections::{BTreeMap, BTreeSet}; use stacks_common::types::StacksEpochId; use crate::vm::analysis::types::ContractAnalysis; -use crate::vm::analysis::StaticCheckError; +use crate::vm::analysis::{StaticCheckError, StaticCheckErrorKind}; use crate::vm::types::signatures::CallableSubtype; use crate::vm::types::{ FixedFunction, FunctionArg, FunctionType, TupleTypeSignature, TypeSignature, }; -use crate::vm::{CheckErrorKind, ClarityName, ClarityVersion}; +use crate::vm::{ClarityName, ClarityVersion}; pub fn build_contract_interface( contract_analysis: &ContractAnalysis, @@ -278,7 +278,7 @@ impl ContractInterfaceFunction { FunctionType::Fixed(FixedFunction { returns, .. }) => { ContractInterfaceAtomType::from_type_signature(returns) } - _ => return Err(CheckErrorKind::Expects( + _ => return Err(StaticCheckErrorKind::Expects( "Contract functions should only have fixed function return types!" .into(), ) @@ -290,7 +290,7 @@ impl ContractInterfaceFunction { ContractInterfaceFunctionArg::from_function_args(args) } _ => { - return Err(CheckErrorKind::Expects( + return Err(StaticCheckErrorKind::Expects( "Contract functions should only have fixed function arguments!" .into(), ) @@ -402,7 +402,7 @@ impl ContractInterface { pub fn serialize(&self) -> Result { serde_json::to_string(self).map_err(|_| { - CheckErrorKind::Expects("Failed to serialize contract interface".into()).into() + StaticCheckErrorKind::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 7bf7faabc13..c7e326e6a6e 100644 --- a/clarity/src/vm/analysis/errors.rs +++ b/clarity/src/vm/analysis/errors.rs @@ -16,5 +16,5 @@ pub use clarity_types::errors::analysis::{ check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, - StaticCheckError, SyntaxBindingError, SyntaxBindingErrorType, + StaticCheckError, StaticCheckErrorKind, SyntaxBindingError, SyntaxBindingErrorType, }; diff --git a/clarity/src/vm/analysis/mod.rs b/clarity/src/vm/analysis/mod.rs index f25c0d4e732..9da98099d2e 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::{CheckErrorKind, StaticCheckError}; +pub use self::errors::{CheckErrorKind, StaticCheckError, StaticCheckErrorKind}; use self::read_only_checker::ReadOnlyChecker; use self::trait_checker::TraitChecker; use self::type_checker::v2_05::TypeChecker as TypeChecker2_05; @@ -54,9 +54,10 @@ pub fn mem_type_check( epoch: StacksEpochId, ) -> Result<(Option, ContractAnalysis), StaticCheckError> { let contract_identifier = QualifiedContractIdentifier::transient(); - let contract = build_ast(&contract_identifier, snippet, &mut (), version, epoch) - .map_err(|_| CheckErrorKind::Expects("Failed to build AST".into()))? - .expressions; + let contract: Vec = + build_ast(&contract_identifier, snippet, &mut (), version, epoch) + .map_err(|_| StaticCheckErrorKind::Expects("Failed to build AST".into()))? + .expressions; let mut marf = MemoryBackingStore::new(); let mut analysis_db = marf.as_analysis_db(); @@ -73,16 +74,15 @@ pub fn mem_type_check( ) { Ok(x) => { // return the first type result of the type checker - let first_type = x - .type_map - .as_ref() - .ok_or_else(|| CheckErrorKind::Expects("Should be non-empty".into()))? - .get_type_expected( - x.expressions - .last() - .ok_or_else(|| CheckErrorKind::Expects("Should be non-empty".into()))?, - ) - .cloned(); + + let first_type = + x.type_map + .as_ref() + .ok_or_else(|| StaticCheckErrorKind::Expects("Should be non-empty".into()))? + .get_type_expected(x.expressions.last().ok_or_else(|| { + StaticCheckErrorKind::Expects("Should be non-empty".into()) + })?) + .cloned(); Ok((first_type, x)) } Err(e) => Err(e.0), @@ -151,7 +151,7 @@ pub fn run_analysis( TypeChecker2_1::run_pass(&epoch, &mut contract_analysis, db, build_type_map) } StacksEpochId::Epoch10 => { - return Err(CheckErrorKind::Expects( + return Err(StaticCheckErrorKind::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 9faea79fa0e..c41a452cab4 100644 --- a/clarity/src/vm/analysis/read_only_checker/mod.rs +++ b/clarity/src/vm/analysis/read_only_checker/mod.rs @@ -22,7 +22,7 @@ use stacks_common::types::StacksEpochId; pub use super::errors::{ check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, - SyntaxBindingError, + StaticCheckErrorKind, SyntaxBindingError, }; use super::AnalysisDatabase; use crate::vm::analysis::types::{AnalysisPass, ContractAnalysis}; @@ -82,7 +82,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { /// Returns successfully iff this function is read-only correct. /// /// # Errors - /// - `CheckErrorKind::WriteAttemptedInReadOnly` + /// - `StaticCheckErrorKind::WriteAttemptedInReadOnly` /// - Contract parsing errors pub fn run(&mut self, contract_analysis: &ContractAnalysis) -> Result<(), StaticCheckError> { // Iterate over all the top-level statements in a contract. @@ -106,7 +106,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { /// Returns successfully iff this function is read-only correct. /// /// # Errors - /// - CheckErrorKind::WriteAttemptedInReadOnly + /// - StaticCheckErrorKind::WriteAttemptedInReadOnly /// - Contract parsing errors fn check_top_level_expression( &mut self, @@ -136,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(CheckErrorKind::WriteAttemptedInReadOnly.into()); + return Err(StaticCheckErrorKind::WriteAttemptedInReadOnly.into()); } else { self.defined_functions.insert(function_name, is_read_only); } @@ -172,9 +172,9 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { ) -> Result<(ClarityName, bool), StaticCheckError> { let function_name = signature .first() - .ok_or(CheckErrorKind::DefineFunctionBadSignature)? + .ok_or(StaticCheckErrorKind::DefineFunctionBadSignature)? .match_atom() - .ok_or(CheckErrorKind::BadFunctionName)?; + .ok_or(StaticCheckErrorKind::BadFunctionName)?; let is_read_only = self.check_read_only(body)?; @@ -207,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(CheckErrorKind::WriteAttemptedInReadOnly.into()); + return Err(StaticCheckErrorKind::WriteAttemptedInReadOnly.into()); } else { self.defined_functions.insert(f_name, is_read_only); } @@ -314,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(CheckErrorKind::AtBlockClosureMustBeReadOnly.into()); + return Err(StaticCheckErrorKind::AtBlockClosureMustBeReadOnly.into()); } Ok(is_block_arg_read_only) } @@ -331,7 +331,9 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { Let => { check_arguments_at_least(2, args)?; - let binding_list = args[0].match_list().ok_or(CheckErrorKind::BadLetSyntax)?; + let binding_list = args[0] + .match_list() + .ok_or(StaticCheckErrorKind::BadLetSyntax)?; for (i, pair) in binding_list.iter().enumerate() { let pair_expression = pair.match_list().ok_or_else(|| { @@ -406,7 +408,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { let function_name = args[1] .match_atom() - .ok_or(CheckErrorKind::ContractCallExpectName)?; + .ok_or(StaticCheckErrorKind::ContractCallExpectName)?; let is_function_read_only = match &args[0].expr { SymbolicExpressionType::LiteralValue(Value::Principal( @@ -427,7 +429,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { } _ => { return Err(StaticCheckError::new( - CheckErrorKind::ContractCallExpectName, + StaticCheckErrorKind::ContractCallExpectName, )) } }; @@ -454,11 +456,11 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { ) -> Result { let (function_name, args) = expressions .split_first() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::NonFunctionApplication)?; let function_name = function_name .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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 { @@ -466,10 +468,9 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> { } result } else { - let is_function_read_only = *self - .defined_functions - .get(function_name) - .ok_or(CheckErrorKind::UnknownFunction(function_name.to_string()))?; + let is_function_read_only = *self.defined_functions.get(function_name).ok_or( + StaticCheckErrorKind::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 5b985b7b2f2..9e0f8b46aaa 100644 --- a/clarity/src/vm/analysis/read_only_checker/tests.rs +++ b/clarity/src/vm/analysis/read_only_checker/tests.rs @@ -20,10 +20,11 @@ use rstest::rstest; use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; +use crate::vm::analysis::type_check; use crate::vm::analysis::type_checker::v2_1::tests::mem_type_check; -use crate::vm::analysis::{type_check, CheckErrorKind}; use crate::vm::ast::parse; use crate::vm::database::MemoryBackingStore; +use crate::vm::errors::StaticCheckErrorKind; use crate::vm::tests::test_clarity_versions; use crate::vm::types::QualifiedContractIdentifier; use crate::vm::ClarityVersion; @@ -34,11 +35,11 @@ fn test_argument_count_violations() { ( "(define-private (foo-bar) (at-block))", - CheckErrorKind::IncorrectArgumentCount(2, 0), + StaticCheckErrorKind::IncorrectArgumentCount(2, 0), ), ( "(define-private (foo-bar) (map-get?))", - CheckErrorKind::IncorrectArgumentCount(2, 0), + StaticCheckErrorKind::IncorrectArgumentCount(2, 0), ), ]; @@ -72,7 +73,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, CheckErrorKind::AtBlockClosureMustBeReadOnly) + assert_eq!(*err.err, StaticCheckErrorKind::AtBlockClosureMustBeReadOnly) } } @@ -163,7 +164,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, CheckErrorKind::WriteAttemptedInReadOnly) + assert_eq!(*err.err, StaticCheckErrorKind::WriteAttemptedInReadOnly) } } @@ -180,7 +181,7 @@ fn test_nested_writing_closure() { for contract in bad_contracts.iter() { let err = mem_type_check(contract).unwrap_err(); - assert_eq!(*err.err, CheckErrorKind::AtBlockClosureMustBeReadOnly) + assert_eq!(*err.err, StaticCheckErrorKind::AtBlockClosureMustBeReadOnly) } } @@ -231,7 +232,7 @@ fn test_contract_call_read_only_violations( ) }) .unwrap_err(); - assert_eq!(*err.err, CheckErrorKind::WriteAttemptedInReadOnly); + assert_eq!(*err.err, StaticCheckErrorKind::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 a2563de2d47..01396a64e25 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::{CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind}; use crate::vm::analysis::types::{AnalysisPass, ContractAnalysis}; use crate::vm::analysis::AnalysisDatabase; @@ -49,13 +49,13 @@ impl TraitChecker { let trait_name = trait_identifier.name.to_string(); let contract_defining_trait = analysis_db .load_contract(&trait_identifier.contract_identifier, &self.epoch)? - .ok_or(CheckErrorKind::TraitReferenceUnknown( + .ok_or(StaticCheckErrorKind::TraitReferenceUnknown( trait_identifier.name.to_string(), ))?; let trait_definition = contract_defining_trait .get_defined_trait(&trait_name) - .ok_or(CheckErrorKind::TraitReferenceUnknown( + .ok_or(StaticCheckErrorKind::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 c103f7a6eaa..a04ad00d8c9 100644 --- a/clarity/src/vm/analysis/trait_checker/tests.rs +++ b/clarity/src/vm/analysis/trait_checker/tests.rs @@ -20,8 +20,7 @@ use rstest::rstest; use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::CheckErrorKind; -use crate::vm::analysis::{type_check, StaticCheckError}; +use crate::vm::analysis::{type_check, StaticCheckError, StaticCheckErrorKind}; use crate::vm::ast::errors::ParseErrorKind; use crate::vm::ast::{build_ast, parse}; use crate::vm::database::MemoryBackingStore; @@ -98,7 +97,7 @@ fn test_incomplete_impl_trait_1(#[case] version: ClarityVersion, #[case] epoch: }) .unwrap_err(); match *err.err { - CheckErrorKind::BadTraitImplementation(_, _) => {} + StaticCheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -125,7 +124,7 @@ fn test_incomplete_impl_trait_2(#[case] version: ClarityVersion, #[case] epoch: }) .unwrap_err(); match *err.err { - CheckErrorKind::BadTraitImplementation(_, _) => {} + StaticCheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -149,7 +148,7 @@ fn test_impl_trait_arg_admission_1(#[case] version: ClarityVersion, #[case] epoc }) .unwrap_err(); match *err.err { - CheckErrorKind::BadTraitImplementation(_, _) => {} + StaticCheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -289,7 +288,7 @@ fn test_get_trait_reference_from_tuple( }) .unwrap_err(); match *err.err { - CheckErrorKind::ContractCallExpectName => {} + StaticCheckErrorKind::ContractCallExpectName => {} _ => panic!("{err:?}"), } } @@ -332,7 +331,7 @@ fn test_dynamic_dispatch_by_defining_and_impl_trait( }) .unwrap_err(); match *err.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err:?}"), } } @@ -434,7 +433,7 @@ fn test_cycle_in_traits_2_contracts(#[case] version: ClarityVersion, #[case] epo }) .unwrap_err(); match *err.err { - CheckErrorKind::NoSuchContract(_) => {} + StaticCheckErrorKind::NoSuchContract(_) => {} _ => panic!("{err:?}"), } } @@ -487,7 +486,7 @@ fn test_dynamic_dispatch_unknown_method( }) .unwrap_err(); match *err.err { - CheckErrorKind::TraitMethodUnknown(_, _) => {} + StaticCheckErrorKind::TraitMethodUnknown(_, _) => {} _ => panic!("{err:?}"), } } @@ -812,7 +811,7 @@ fn test_dynamic_dispatch_importing_non_existant_trait( }) .unwrap_err(); match *err.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err:?}"), } } @@ -1099,13 +1098,13 @@ fn test_dynamic_dispatch_including_wrong_nested_trait( .unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, actual) if epoch < StacksEpochId::Epoch21 => { + StaticCheckErrorKind::TypeError(expected, actual) if epoch < StacksEpochId::Epoch21 => { match (&*expected, &*actual) { (TypeSignature::TraitReferenceType(_), TypeSignature::TraitReferenceType(_)) => {} _ => panic!("unexpected TypeSignature: {expected:?} {actual:?}"), } } - CheckErrorKind::TypeError(expected, actual) + StaticCheckErrorKind::TypeError(expected, actual) if epoch >= StacksEpochId::Epoch21 && version < ClarityVersion::Clarity2 => { match (&*expected, &*actual) { @@ -1113,7 +1112,7 @@ fn test_dynamic_dispatch_including_wrong_nested_trait( _ => panic!("unexpected TypeSignature: {expected:?} {actual:?}"), } } - CheckErrorKind::TraitReferenceUnknown(name) => assert_eq!(name.as_str(), "trait-a"), + StaticCheckErrorKind::TraitReferenceUnknown(name) => assert_eq!(name.as_str(), "trait-a"), _ => panic!("{err:?}"), } } @@ -1167,7 +1166,7 @@ fn test_dynamic_dispatch_mismatched_args( }) .unwrap_err(); match *err.err { - CheckErrorKind::TypeError(_, _) => {} + StaticCheckErrorKind::TypeError(_, _) => {} _ => panic!("{err:?}"), } } @@ -1221,7 +1220,7 @@ fn test_dynamic_dispatch_mismatched_returns( }) .unwrap_err(); match *err.err { - CheckErrorKind::BadTraitImplementation(_, _) => {} + StaticCheckErrorKind::BadTraitImplementation(_, _) => {} _ => panic!("{err:?}"), } } @@ -1257,7 +1256,7 @@ fn test_bad_call_with_trait(#[case] version: ClarityVersion, #[case] epoch: Stac }) .unwrap_err(); match *err.err { - CheckErrorKind::TypeError(_, _) => {} + StaticCheckErrorKind::TypeError(_, _) => {} _ => panic!("{err:?}"), } } @@ -1466,7 +1465,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 { - CheckErrorKind::TypeError(_, _) => {} + StaticCheckErrorKind::TypeError(_, _) => {} _ => panic!("{err:?}"), }; } @@ -1560,7 +1559,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_principal.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_principal:?}"), } let err_int = db @@ -1570,7 +1569,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_int.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_int:?}"), } let err_uint = db @@ -1580,7 +1579,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_uint.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_uint:?}"), } let err_bool = db @@ -1590,7 +1589,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_bool.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_bool:?}"), } let err_list = db @@ -1600,7 +1599,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_list.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_list:?}"), } let err_buff = db @@ -1610,7 +1609,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_buff.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_buff:?}"), } let err_tuple = db @@ -1620,7 +1619,7 @@ fn test_contract_of_wrong_type(#[case] version: ClarityVersion, #[case] epoch: S }) .unwrap_err(); match *err_tuple.err { - CheckErrorKind::TraitReferenceUnknown(_) => {} + StaticCheckErrorKind::TraitReferenceUnknown(_) => {} _ => panic!("{err_tuple:?}"), } } @@ -1819,7 +1818,7 @@ fn test_trait_contract_not_found(#[case] version: ClarityVersion, #[case] epoch: ) }) { Err(StaticCheckError { err, .. }) if version < ClarityVersion::Clarity2 => match *err { - CheckErrorKind::NoSuchContract(contract) => { + StaticCheckErrorKind::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 50f8cd16104..8a350431b35 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::{CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind}; use crate::vm::types::signatures::CallableSubtype; use crate::vm::types::{TraitIdentifier, TypeSignature}; use crate::vm::{ClarityName, ClarityVersion, SymbolicExpression, MAX_CONTEXT_DEPTH}; @@ -69,7 +69,7 @@ impl TypeMap { TypeMapDataType::Map(ref mut map) => { if map.insert(expr.id, type_sig).is_some() { Err(StaticCheckError::new( - CheckErrorKind::TypeAlreadyAnnotatedFailure, + StaticCheckErrorKind::TypeAlreadyAnnotatedFailure, )) } else { Ok(()) @@ -78,7 +78,7 @@ impl TypeMap { TypeMapDataType::Set(ref mut map) => { if !map.insert(expr.id) { Err(StaticCheckError::new( - CheckErrorKind::TypeAlreadyAnnotatedFailure, + StaticCheckErrorKind::TypeAlreadyAnnotatedFailure, )) } else { Ok(()) @@ -110,7 +110,7 @@ impl TypingContext<'_> { pub fn extend(&self) -> Result, StaticCheckError> { if self.depth >= MAX_CONTEXT_DEPTH { Err(StaticCheckError::new( - CheckErrorKind::MaxContextDepthReached, + StaticCheckErrorKind::MaxContextDepthReached, )) } else { Ok(TypingContext { diff --git a/clarity/src/vm/analysis/type_checker/mod.rs b/clarity/src/vm/analysis/type_checker/mod.rs index 7305d63d08e..30db2e931ff 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::{CheckErrorKind, StaticCheckError}; +use super::errors::{StaticCheckError, StaticCheckErrorKind}; pub use super::types::{AnalysisPass, ContractAnalysis}; use super::AnalysisDatabase; use crate::vm::costs::CostTracker; @@ -49,7 +49,7 @@ impl FunctionType { | StacksEpochId::Epoch32 | StacksEpochId::Epoch33 => self.check_args_2_1(accounting, args, clarity_version), StacksEpochId::Epoch10 => { - Err(CheckErrorKind::Expects("Epoch10 is not supported".into()).into()) + Err(StaticCheckErrorKind::Expects("Epoch10 is not supported".into()).into()) } } } @@ -77,7 +77,7 @@ impl FunctionType { self.check_args_by_allowing_trait_cast_2_1(db, clarity_version, func_args) } StacksEpochId::Epoch10 => { - Err(CheckErrorKind::Expects("Epoch10 is not supported".into()).into()) + Err(StaticCheckErrorKind::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 684c7ff872b..ac08536c82b 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::{CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind}; use crate::vm::analysis::types::ContractAnalysis; use crate::vm::representations::ClarityName; use crate::vm::types::signatures::FunctionSignature; @@ -67,9 +67,9 @@ impl ContractContext { || self.traits.contains_key(name) || self.map_types.contains_key(name) { - Err(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( - name.to_string(), - ))) + Err(StaticCheckError::new( + StaticCheckErrorKind::NameAlreadyUsed(name.to_string()), + )) } else { 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 da3872048d9..8ccd89410bf 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,7 @@ 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, CheckErrorKind, StaticCheckError, + check_argument_count, check_arguments_at_least, StaticCheckError, StaticCheckErrorKind, SyntaxBindingErrorType, }; use crate::vm::analysis::AnalysisDatabase; @@ -147,7 +147,7 @@ impl FunctionType { 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(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -165,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(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -183,10 +183,11 @@ impl FunctionType { return Ok(return_type.clone()); } } - Err( - CheckErrorKind::UnionTypeError(arg_types.clone(), Box::new(found_type.clone())) - .into(), + Err(StaticCheckErrorKind::UnionTypeError( + arg_types.clone(), + Box::new(found_type.clone()), ) + .into()) } FunctionType::ArithmeticVariadic | FunctionType::ArithmeticBinary @@ -197,14 +198,17 @@ impl FunctionType { if self == &FunctionType::ArithmeticBinary { check_argument_count(2, args)?; } - let (first, rest) = args - .split_first() - .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, args.len()))?; + let (first, rest) = + args.split_first() + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::UnionTypeError( + _ => Err(StaticCheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(first.clone()), )), @@ -212,7 +216,7 @@ impl FunctionType { for found_type in rest.iter() { analysis_typecheck_cost(accounting, &TypeSignature::IntType, found_type)?; if found_type != &return_type { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(return_type), Box::new(found_type.clone()), ) @@ -228,7 +232,7 @@ impl FunctionType { analysis_typecheck_cost(accounting, &TypeSignature::IntType, second)?; if first != &TypeSignature::IntType && first != &TypeSignature::UIntType { - return Err(CheckErrorKind::UnionTypeError( + return Err(StaticCheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(first.clone()), ) @@ -236,7 +240,7 @@ impl FunctionType { } if first != second { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(first.clone()), Box::new(second.clone()), ) @@ -245,7 +249,7 @@ impl FunctionType { Ok(TypeSignature::BoolType) } - FunctionType::Binary(_, _, _) => Err(CheckErrorKind::Expects( + FunctionType::Binary(_, _, _) => Err(StaticCheckErrorKind::Expects( "Binary type should not be reached in 2.05".into(), ) .into()), @@ -259,7 +263,9 @@ impl FunctionType { ) -> Result { let (expected_args, returns) = match self { FunctionType::Fixed(FixedFunction { args, returns }) => (args, returns), - _ => return Err(CheckErrorKind::Expects("Unexpected function type".into()).into()), + _ => { + return Err(StaticCheckErrorKind::Expects("Unexpected function type".into()).into()) + } }; check_argument_count(expected_args.len(), func_args)?; @@ -271,7 +277,9 @@ impl FunctionType { ) => { let contract_to_check = db .load_contract(contract, &StacksEpochId::Epoch2_05)? - .ok_or_else(|| CheckErrorKind::NoSuchContract(contract.name.to_string()))?; + .ok_or_else(|| { + StaticCheckErrorKind::NoSuchContract(contract.name.to_string()) + })?; let trait_definition = db .get_defined_trait( &trait_id.contract_identifier, @@ -279,9 +287,11 @@ impl FunctionType { &StacksEpochId::Epoch2_05, ) .map_err(|_| { - CheckErrorKind::NoSuchContract(trait_id.contract_identifier.to_string()) + StaticCheckErrorKind::NoSuchContract( + trait_id.contract_identifier.to_string(), + ) })? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( trait_id.contract_identifier.to_string(), ))?; contract_to_check.check_trait_compliance( @@ -293,7 +303,7 @@ impl FunctionType { (expected_type, value) => { if !expected_type.admits(&StacksEpochId::Epoch2_05, value)? { let actual_type = TypeSignature::type_of(value)?; - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type), ) @@ -327,13 +337,13 @@ fn type_reserved_variable(variable_name: &str) -> Result, BlockHeight => TypeSignature::UIntType, BurnBlockHeight => TypeSignature::UIntType, NativeNone => TypeSignature::new_option(no_type()) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, NativeTrue => TypeSignature::BoolType, NativeFalse => TypeSignature::BoolType, TotalLiquidMicroSTX => TypeSignature::UIntType, Regtest => TypeSignature::BoolType, TxSponsor | Mainnet | ChainId | StacksBlockHeight | TenureHeight | StacksBlockTime | CurrentContract => { - return Err(CheckErrorKind::Expects( + return Err(StaticCheckErrorKind::Expects( "tx-sponsor, mainnet, chain-id, stacks-block-height, tenure-height, stacks-block-time, and current-contract should not reach here in 2.05".into(), ) .into()) @@ -393,7 +403,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new(expected_type), Box::new(return_type), ) @@ -424,7 +434,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } Err(e) => Err(e), })? - .ok_or_else(|| CheckErrorKind::Expects("Expected a depth result".into()))?; + .ok_or_else(|| StaticCheckErrorKind::Expects("Expected a depth result".into()))?; } runtime_cost(ClarityCostFunction::AnalysisStorage, self, size)?; @@ -463,7 +473,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { let contract_to_check = self .db .load_contract(contract_identifier, &StacksEpochId::Epoch2_05)? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( contract_identifier.to_string(), ))?; @@ -473,13 +483,13 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &trait_identifier.contract_identifier, &StacksEpochId::Epoch2_05, )? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( trait_identifier.contract_identifier.to_string(), ))?; let trait_definition = contract_defining_trait .get_defined_trait(&trait_identifier.name) - .ok_or(CheckErrorKind::NoSuchTrait( + .ok_or(StaticCheckErrorKind::NoSuchTrait( trait_identifier.contract_identifier.to_string(), trait_identifier.name.to_string(), ))?; @@ -496,9 +506,11 @@ 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: StaticCheckError = - CheckErrorKind::TypeError(Box::new(expected_type.clone()), Box::new(actual_type)) - .into(); + let mut err: StaticCheckError = StaticCheckErrorKind::TypeError( + Box::new(expected_type.clone()), + Box::new(actual_type), + ) + .into(); err.set_expression(expr); Err(err) } else { @@ -533,12 +545,12 @@ impl<'a, 'b> TypeChecker<'a, 'b> { let mut types_returned = self.type_check_all(args, context)?; let last_return = types_returned.pop().ok_or(StaticCheckError::new( - CheckErrorKind::CheckerImplementationFailure, + StaticCheckErrorKind::CheckerImplementationFailure, ))?; for type_return in types_returned.iter() { if type_return.is_response_type() { - return Err(CheckErrorKind::UncheckedIntermediaryResponses.into()); + return Err(StaticCheckErrorKind::UncheckedIntermediaryResponses.into()); } } Ok(last_return) @@ -581,10 +593,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result<(ClarityName, FixedFunction), StaticCheckError> { let (function_name, args) = signature .split_first() - .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, 0))?; + .ok_or(StaticCheckErrorKind::RequiresAtLeastArguments(1, 0))?; let function_name = function_name .match_atom() - .ok_or(CheckErrorKind::BadFunctionName)?; + .ok_or(StaticCheckErrorKind::BadFunctionName)?; let args = parse_name_type_pairs::<(), StaticCheckError>( StacksEpochId::Epoch2_05, args, @@ -593,7 +605,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { )?; if self.function_return_tracker.is_some() { - return Err(CheckErrorKind::Expects( + return Err(StaticCheckErrorKind::Expects( "Interpreter error: Previous function define left dirty typecheck state.".into(), ) .into()); @@ -635,7 +647,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new(expected.clone()), Box::new(return_type), ) @@ -674,10 +686,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { // 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(|_| CheckErrorKind::BadMapTypeDefinition)?; + .map_err(|_| StaticCheckErrorKind::BadMapTypeDefinition)?; let value_type = TypeSignature::parse_type_repr(StacksEpochId::Epoch2_05, value_type, &mut ()) - .map_err(|_| CheckErrorKind::BadMapTypeDefinition)?; + .map_err(|_| StaticCheckErrorKind::BadMapTypeDefinition)?; Ok((map_name.clone(), (key_type, value_type))) } @@ -709,19 +721,21 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result { let (function_name, args) = expression .split_first() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::NonFunctionApplication)?; self.type_map.set_type(function_name, no_type())?; let function_name = function_name .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::UnknownFunction(function_name.to_string())), + _ => Err(StaticCheckErrorKind::UnknownFunction( + function_name.to_string(), + )), }?; for (expected_type, found_type) in function.args.iter().map(|x| &x.signature).zip(args) @@ -751,7 +765,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(CheckErrorKind::UndefinedVariable(name.to_string()).into()); + return Err(StaticCheckErrorKind::UndefinedVariable(name.to_string()).into()); } runtime_cost( @@ -763,7 +777,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { if let Some(type_result) = context.lookup_variable_type(name) { Ok(type_result.clone()) } else { - Err(CheckErrorKind::UndefinedVariable(name.to_string()).into()) + Err(StaticCheckErrorKind::UndefinedVariable(name.to_string()).into()) } } } @@ -778,7 +792,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { Atom(ref name) => self.lookup_variable(name, context)?, List(ref expression) => self.type_check_function_application(expression, context)?, TraitReference(_, _) | Field(_) => { - return Err(CheckErrorKind::UnexpectedTraitOrFieldReference.into()); + return Err(StaticCheckErrorKind::UnexpectedTraitOrFieldReference.into()); } }; @@ -810,7 +824,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let expected_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch2_05, var_type, &mut ()) - .map_err(|_e| CheckErrorKind::DefineVariableBadSignature)?; + .map_err(|_e| StaticCheckErrorKind::DefineVariableBadSignature)?; self.type_check_expects(initial, context, &expected_type)?; @@ -838,7 +852,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let asset_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch2_05, nft_type, &mut ()) - .map_err(|_| CheckErrorKind::DefineNFTBadSignature)?; + .map_err(|_| StaticCheckErrorKind::DefineNFTBadSignature)?; Ok((asset_name.clone(), asset_type)) } @@ -902,9 +916,9 @@ impl<'a, 'b> TypeChecker<'a, 'b> { .add_public_function_type(f_name, FunctionType::Fixed(f_type))?; return Ok(Some(())); } else { - return Err(CheckErrorKind::PublicFunctionMustReturnResponse(Box::new( - f_type.returns, - )) + return Err(StaticCheckErrorKind::PublicFunctionMustReturnResponse( + Box::new(f_type.returns), + ) .into()); } } @@ -1009,9 +1023,10 @@ 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( - CheckErrorKind::TraitReferenceUnknown(name.to_string()).into() - ); + return Err(StaticCheckErrorKind::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 74680694340..3bc0a6af6d1 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,9 @@ // along with this program. If not, see . use super::{TypeChecker, TypingContext}; -use crate::vm::analysis::errors::{check_argument_count, CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{ + check_argument_count, StaticCheckError, StaticCheckErrorKind, +}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::representations::SymbolicExpression; @@ -28,13 +30,15 @@ pub fn check_special_get_owner( ) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) .cloned() - .ok_or_else(|| CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; + .ok_or_else(|| StaticCheckErrorKind::NoSuchNFT(asset_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -56,10 +60,12 @@ pub fn check_special_get_balance( ) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -77,13 +83,15 @@ pub fn check_special_mint_asset( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? + .ok_or(StaticCheckErrorKind::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( @@ -108,7 +116,9 @@ pub fn check_special_mint_token( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -119,7 +129,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(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -135,13 +145,15 @@ pub fn check_special_transfer_asset( ) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let token_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(token_name) - .ok_or(CheckErrorKind::NoSuchNFT(token_name.to_string()))? + .ok_or(StaticCheckErrorKind::NoSuchNFT(token_name.to_string()))? .clone(); runtime_cost( @@ -167,7 +179,9 @@ pub fn check_special_transfer_token( ) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let token_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -179,7 +193,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(CheckErrorKind::NoSuchFT(token_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(token_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -195,10 +209,12 @@ pub fn check_special_get_token_supply( ) -> Result { check_argument_count(1, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -213,13 +229,15 @@ pub fn check_special_burn_asset( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? + .ok_or(StaticCheckErrorKind::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( @@ -244,7 +262,9 @@ pub fn check_special_burn_token( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -255,7 +275,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(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::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 e454e424f10..b9cb0122af1 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, CheckErrorKind, StaticCheckError, TypeChecker, TypingContext, + check_arguments_at_least, StaticCheckError, StaticCheckErrorKind, TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; @@ -31,14 +31,16 @@ pub fn check_special_fetch_entry( ) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let map_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::NoSuchMap(map_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -55,7 +57,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -71,14 +73,16 @@ pub fn check_special_delete_entry( ) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let map_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let (expected_key_type, _) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -88,7 +92,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -104,7 +108,9 @@ fn check_set_or_insert_entry( ) -> Result { check_arguments_at_least(3, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let map_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let value_type = checker.type_check(&args[2], context)?; @@ -112,7 +118,7 @@ fn check_set_or_insert_entry( let (expected_key_type, expected_value_type) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -129,12 +135,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) } else if !expected_value_type.admits_type(&StacksEpochId::Epoch2_05, &value_type)? { - Err(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) 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 4a0b5a65338..6b530c7d098 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::{CheckErrorKind, StaticCheckError, SyntaxBindingErrorType}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind, SyntaxBindingErrorType}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; use crate::vm::diagnostic::DiagnosableError; @@ -117,10 +117,12 @@ fn inner_handle_tuple_get( let return_type = tuple_type_sig .field_type(field_to_get) - .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchTupleField( - field_to_get.to_string(), - tuple_type_sig.clone(), - )))? + .ok_or(StaticCheckError::new( + StaticCheckErrorKind::NoSuchTupleField( + field_to_get.to_string(), + tuple_type_sig.clone(), + ), + ))? .clone(); Ok(return_type) } @@ -134,7 +136,7 @@ fn check_special_get( let field_to_get = args[0] .match_atom() - .ok_or(CheckErrorKind::BadTupleFieldName)?; + .ok_or(StaticCheckErrorKind::BadTupleFieldName)?; let argument_type = checker.type_check(&args[1], context)?; @@ -146,10 +148,10 @@ fn check_special_get( let option_type = TypeSignature::new_option(inner_type)?; Ok(option_type) } else { - Err(CheckErrorKind::ExpectedTuple(value_type_sig).into()) + Err(StaticCheckErrorKind::ExpectedTuple(value_type_sig).into()) } } else { - Err(CheckErrorKind::ExpectedTuple(Box::new(argument_type)).into()) + Err(StaticCheckErrorKind::ExpectedTuple(Box::new(argument_type)).into()) } } @@ -163,13 +165,13 @@ fn check_special_merge( let res = checker.type_check(&args[0], context)?; let mut base = match res { TypeSignature::TupleType(tuple_sig) => Ok(tuple_sig), - _ => Err(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), + _ => Err(StaticCheckErrorKind::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(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), + _ => Err(StaticCheckErrorKind::ExpectedTuple(Box::new(res.clone()))), }?; runtime_cost( ClarityCostFunction::AnalysisCheckTupleMerge, @@ -209,8 +211,9 @@ pub fn check_special_tuple_cons( }, )?; - let tuple_signature = TupleTypeSignature::try_from(tuple_type_data) - .map_err(|e| CheckErrorKind::BadTupleConstruction(e.message()))?; + let tuple_signature = TupleTypeSignature::try_from(tuple_type_data).map_err(|e| { + StaticCheckErrorKind::BadTupleConstruction(StaticCheckErrorKind::from(e).message()) + })?; Ok(TypeSignature::TupleType(tuple_signature)) } @@ -224,7 +227,7 @@ fn check_special_let( let binding_list = args[0] .match_list() - .ok_or(StaticCheckError::new(CheckErrorKind::BadLetSyntax))?; + .ok_or(StaticCheckError::new(StaticCheckErrorKind::BadLetSyntax))?; let mut out_context = context.extend()?; @@ -236,9 +239,9 @@ 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(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( - var_name.to_string(), - ))); + return Err(StaticCheckError::new( + StaticCheckErrorKind::NameAlreadyUsed(var_name.to_string()), + )); } let typed_result = checker.type_check(var_sexp, &out_context)?; @@ -267,14 +270,14 @@ fn check_special_fetch_var( let var_name = args[0] .match_atom() - .ok_or(StaticCheckError::new(CheckErrorKind::BadMapName))?; + .ok_or(StaticCheckError::new(StaticCheckErrorKind::BadMapName))?; let value_type = checker .contract_context .get_persisted_variable_type(var_name) - .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchDataVariable( - var_name.to_string(), - )))?; + .ok_or(StaticCheckError::new( + StaticCheckErrorKind::NoSuchDataVariable(var_name.to_string()), + ))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -292,14 +295,18 @@ fn check_special_set_var( ) -> Result { check_arguments_at_least(2, args)?; - let var_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let var_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchDataVariable( + var_name.to_string(), + ))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -309,7 +316,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) @@ -331,7 +338,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(|_| CheckErrorKind::TypeError(Box::new(x_type), Box::new(arg_type)))?; + .map_err(|_| StaticCheckErrorKind::TypeError(Box::new(x_type), Box::new(arg_type)))?; } Ok(TypeSignature::BoolType) @@ -354,7 +361,8 @@ fn check_special_if( analysis_typecheck_cost(checker, expr1, expr2)?; TypeSignature::least_supertype(&StacksEpochId::Epoch2_05, expr1, expr2).map_err(|_| { - CheckErrorKind::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())).into() + StaticCheckErrorKind::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())) + .into() }) } @@ -366,7 +374,7 @@ fn check_contract_call( check_arguments_at_least(2, args)?; let func_name = args[1].match_atom().ok_or(StaticCheckError::new( - CheckErrorKind::ContractCallExpectName, + StaticCheckErrorKind::ContractCallExpectName, ))?; checker.type_map.set_type(&args[1], no_type())?; @@ -391,10 +399,12 @@ fn check_contract_call( { Ok(function) } else { - Err(StaticCheckError::new(CheckErrorKind::NoSuchPublicFunction( - contract_identifier.to_string(), - func_name.to_string(), - ))) + Err(StaticCheckError::new( + StaticCheckErrorKind::NoSuchPublicFunction( + contract_identifier.to_string(), + func_name.to_string(), + ), + )) } }?; @@ -413,21 +423,22 @@ fn check_contract_call( let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, _ => { - return Err( - CheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into(), - ); + return Err(StaticCheckErrorKind::TraitReferenceUnknown( + trait_instance.to_string(), + ) + .into()); } }; runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; let trait_signature = checker.contract_context.get_trait(&trait_id.name).ok_or( - CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), + StaticCheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), )?; let func_signature = trait_signature .get(func_name) - .ok_or(CheckErrorKind::TraitMethodUnknown( + .ok_or(StaticCheckErrorKind::TraitMethodUnknown( trait_id.name.to_string(), func_name.to_string(), ))?; @@ -442,7 +453,7 @@ fn check_contract_call( } _ => { return Err(StaticCheckError::new( - CheckErrorKind::ContractCallExpectName, + StaticCheckErrorKind::ContractCallExpectName, )) } }; @@ -466,14 +477,18 @@ fn check_contract_of( SymbolicExpressionType::Atom(trait_instance) => trait_instance, _ => { return Err(StaticCheckError::new( - CheckErrorKind::ContractOfExpectsTrait, + StaticCheckErrorKind::ContractOfExpectsTrait, )) } }; let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, - _ => return Err(CheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into()), + _ => { + return Err( + StaticCheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into(), + ) + } }; runtime_cost(ClarityCostFunction::ContractOf, checker, 1)?; @@ -481,7 +496,7 @@ fn check_contract_of( checker .contract_context .get_trait(&trait_id.name) - .ok_or_else(|| CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()))?; + .ok_or_else(|| StaticCheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()))?; Ok(TypeSignature::PrincipalType) } @@ -495,7 +510,7 @@ fn check_principal_of( checker.type_check_expects(&args[0], context, &TypeSignature::BUFFER_33)?; Ok( TypeSignature::new_response(TypeSignature::PrincipalType, TypeSignature::UIntType) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -509,7 +524,7 @@ fn check_secp256k1_recover( checker.type_check_expects(&args[1], context, &TypeSignature::BUFFER_65)?; Ok( TypeSignature::new_response(TypeSignature::BUFFER_33, TypeSignature::UIntType) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -533,7 +548,7 @@ fn check_get_block_info( check_arguments_at_least(2, args)?; let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( - CheckErrorKind::GetBlockInfoExpectPropertyName, + StaticCheckErrorKind::GetBlockInfoExpectPropertyName, ))?; let block_info_prop = BlockInfoProperty::lookup_by_name_at_version( @@ -541,7 +556,7 @@ fn check_get_block_info( &ClarityVersion::Clarity1, ) .ok_or(StaticCheckError::new( - CheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), + StaticCheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), ))?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -567,7 +582,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 { @@ -589,7 +604,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::IntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -600,7 +615,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -611,7 +626,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::BoolType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -664,7 +679,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("owner".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -676,7 +691,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("amount".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -684,7 +699,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("sender".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -692,7 +707,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("recipient".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -702,14 +717,14 @@ impl TypedNativeFunction { TypeSignature::BoolType, TypeSignature::UIntType, ) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, }))), StxBurn => Simple(SimpleNativeFunction(FunctionType::Fixed(FixedFunction { args: vec![ FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("amount".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -717,7 +732,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("sender".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -727,7 +742,7 @@ impl TypedNativeFunction { TypeSignature::BoolType, TypeSignature::UIntType, ) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, }))), GetTokenBalance => Special(SpecialNativeFunction(&assets::check_special_get_balance)), GetAssetOwner => Special(SpecialNativeFunction(&assets::check_special_get_owner)), @@ -793,7 +808,7 @@ impl TypedNativeFunction { | StxGetAccount | BitwiseAnd | BitwiseOr | BitwiseNot | BitwiseLShift | BitwiseRShift | BitwiseXor2 | Slice | ToConsensusBuff | FromConsensusBuff | ReplaceAt | GetStacksBlockInfo | GetTenureInfo | ContractHash | ToAscii => { - return Err(CheckErrorKind::Expects( + return Err(StaticCheckErrorKind::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 73a4d87f649..75c931428c3 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, CheckErrorKind, StaticCheckError, - TypeChecker, TypingContext, + check_argument_count, check_arguments_at_least, no_type, StaticCheckError, + StaticCheckErrorKind, TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; @@ -82,7 +82,7 @@ pub fn check_special_is_response( if let TypeSignature::ResponseType(_types) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrorKind::ExpectedResponseType(Box::new(input)).into()) + Err(StaticCheckErrorKind::ExpectedResponseType(Box::new(input)).into()) } } @@ -100,7 +100,7 @@ pub fn check_special_is_optional( if let TypeSignature::OptionalType(_type) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) + Err(StaticCheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) } } @@ -120,11 +120,14 @@ pub fn check_special_default_to( let contained_type = *input_type; TypeSignature::least_supertype(&StacksEpochId::Epoch2_05, &default, &contained_type) .map_err(|_| { - CheckErrorKind::DefaultTypesMustMatch(Box::new(default), Box::new(contained_type)) - .into() + StaticCheckErrorKind::DefaultTypesMustMatch( + Box::new(default), + Box::new(contained_type), + ) + .into() }) } else { - Err(CheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) + Err(StaticCheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) } } @@ -152,7 +155,7 @@ fn inner_unwrap( match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(*input_type) } @@ -160,12 +163,12 @@ fn inner_unwrap( TypeSignature::ResponseType(response_type) => { let ok_type = response_type.0; if ok_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(ok_type) } } - _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(StaticCheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } @@ -178,12 +181,12 @@ fn inner_unwrap_err( if let TypeSignature::ResponseType(response_type) = input { let err_type = response_type.1; if err_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { Ok(err_type) } } else { - Err(CheckErrorKind::ExpectedResponseType(Box::new(input)).into()) + Err(StaticCheckErrorKind::ExpectedResponseType(Box::new(input)).into()) } } @@ -231,7 +234,7 @@ pub fn check_special_try_ret( match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { checker.track_return_type(TypeSignature::new_option(TypeSignature::NoType)?)?; Ok(*input_type) @@ -240,9 +243,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(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else if err_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { checker.track_return_type(TypeSignature::new_response( TypeSignature::NoType, @@ -251,7 +254,7 @@ pub fn check_special_try_ret( Ok(ok_type) } } - _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(StaticCheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } @@ -297,7 +300,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(CheckErrorKind::NameAlreadyUsed(bind_name.into()).into()); + return Err(StaticCheckErrorKind::NameAlreadyUsed(bind_name.into()).into()); } inner_context.variable_types.insert(bind_name, bind_type); @@ -312,22 +315,22 @@ fn check_special_match_opt( context: &TypingContext, ) -> Result { if args.len() != 3 { - Err(CheckErrorKind::BadMatchOptionSyntax(Box::new( - CheckErrorKind::IncorrectArgumentCount(4, args.len() + 1), + Err(StaticCheckErrorKind::BadMatchOptionSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(4, args.len() + 1), )))?; } let bind_name = args[0] .match_atom() .ok_or_else(|| { - CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)) + StaticCheckErrorKind::BadMatchOptionSyntax(Box::new(StaticCheckErrorKind::ExpectedName)) })? .clone(); let some_branch = &args[1]; let none_branch = &args[2]; if option_type.is_no_type() { - return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); + return Err(StaticCheckErrorKind::CouldNotDetermineMatchTypes.into()); } let some_branch_type = @@ -342,8 +345,11 @@ fn check_special_match_opt( &none_branch_type, ) .map_err(|_| { - CheckErrorKind::MatchArmsMustMatch(Box::new(some_branch_type), Box::new(none_branch_type)) - .into() + StaticCheckErrorKind::MatchArmsMustMatch( + Box::new(some_branch_type), + Box::new(none_branch_type), + ) + .into() }) } @@ -354,22 +360,26 @@ fn check_special_match_resp( context: &TypingContext, ) -> Result { if args.len() != 4 { - Err(CheckErrorKind::BadMatchResponseSyntax(Box::new( - CheckErrorKind::IncorrectArgumentCount(5, args.len() + 1), + Err(StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(5, args.len() + 1), )))?; } let ok_bind_name = args[0] .match_atom() .ok_or_else(|| { - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )) })? .clone(); let ok_branch = &args[1]; let err_bind_name = args[2] .match_atom() .ok_or_else(|| { - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )) })? .clone(); let err_branch = &args[3]; @@ -377,7 +387,7 @@ fn check_special_match_resp( let (ok_type, err_type) = resp_type; if ok_type.is_no_type() || err_type.is_no_type() { - return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); + return Err(StaticCheckErrorKind::CouldNotDetermineMatchTypes.into()); } let ok_branch_type = eval_with_new_binding(ok_branch, ok_bind_name, ok_type, checker, context)?; @@ -388,8 +398,11 @@ fn check_special_match_resp( TypeSignature::least_supertype(&StacksEpochId::Epoch2_05, &ok_branch_type, &err_branch_type) .map_err(|_| { - CheckErrorKind::MatchArmsMustMatch(Box::new(ok_branch_type), Box::new(err_branch_type)) - .into() + StaticCheckErrorKind::MatchArmsMustMatch( + Box::new(ok_branch_type), + Box::new(err_branch_type), + ) + .into() }) } @@ -409,6 +422,6 @@ pub fn check_special_match( TypeSignature::ResponseType(resp_type) => { check_special_match_resp(*resp_type, checker, &args[1..], context) } - _ => Err(CheckErrorKind::BadMatchInput(Box::new(input)).into()), + _ => Err(StaticCheckErrorKind::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 8b03807c7a9..37f3d83b837 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,8 +18,8 @@ use stacks_common::types::StacksEpochId; use super::{SimpleNativeFunction, TypedNativeFunction}; use crate::vm::analysis::type_checker::v2_05::{ - check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, TypeChecker, - TypingContext, + check_argument_count, check_arguments_at_least, StaticCheckError, StaticCheckErrorKind, + TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; @@ -44,14 +44,15 @@ fn get_simple_native_or_user_define( { Ok(function_type) } else { - Err( - CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()) - .into(), + Err(StaticCheckErrorKind::IllegalOrUnknownFunctionApplication( + function_name.to_string(), ) + .into()) } } else { checker.get_function_type(function_name).ok_or( - CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()).into(), + StaticCheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()) + .into(), ) } } @@ -65,7 +66,7 @@ pub fn check_special_map( let function_name = args[0] .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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)?; @@ -101,7 +102,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(CheckErrorKind::ExpectedSequence(Box::new(argument_type)).into()); + return Err(StaticCheckErrorKind::ExpectedSequence(Box::new(argument_type)).into()); } }; func_args.push(entry_type); @@ -110,7 +111,7 @@ 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(|_| CheckErrorKind::ConstructedListTooLarge.into()) + .map_err(|_| StaticCheckErrorKind::ConstructedListTooLarge.into()) } pub fn check_special_filter( @@ -122,7 +123,7 @@ pub fn check_special_filter( let function_name = args[0] .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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)?; @@ -133,7 +134,7 @@ pub fn check_special_filter( { let input_type = match argument_type { TypeSignature::SequenceType(ref sequence_type) => Ok(sequence_type.unit_type()), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new( + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new( argument_type.clone(), ))), }?; @@ -146,7 +147,7 @@ pub fn check_special_filter( )?; if TypeSignature::BoolType != filter_type { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BoolType), Box::new(filter_type), ) @@ -166,7 +167,7 @@ pub fn check_special_fold( let function_name = args[0] .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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)?; @@ -176,7 +177,9 @@ pub fn check_special_fold( let input_type = match argument_type { TypeSignature::SequenceType(sequence_type) => Ok(sequence_type.unit_type()), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(argument_type))), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new( + argument_type, + ))), }?; let initial_value_type = checker.type_check(&args[2], context)?; @@ -234,29 +237,29 @@ pub fn check_special_concat( )?; let new_len = lhs_max_len .checked_add(rhs_max_len) - .ok_or(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(StringType(UTF8(size.try_into()?))) } (_, _) => { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(lhs_type.clone()), Box::new(rhs_type.clone()), ) @@ -264,7 +267,7 @@ pub fn check_special_concat( } } } - _ => return Err(CheckErrorKind::ExpectedSequence(Box::new(lhs_type.clone())).into()), + _ => return Err(StaticCheckErrorKind::ExpectedSequence(Box::new(lhs_type.clone())).into()), }; Ok(res) } @@ -293,11 +296,11 @@ pub fn check_special_append( )?; let new_len = lhs_max_len .checked_add(1) - .ok_or(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::MaxLengthOverflow)?; let return_type = TypeSignature::list_of(list_entry_type, new_len)?; Ok(return_type) } - _ => Err(CheckErrorKind::ExpectedListApplication.into()), + _ => Err(StaticCheckErrorKind::ExpectedListApplication.into()), } } @@ -312,7 +315,7 @@ pub fn check_special_as_max_len( SymbolicExpressionType::LiteralValue(Value::UInt(expected_len)) => expected_len, _ => { let expected_len_type = checker.type_check(&args[1], context)?; - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(expected_len_type), ) @@ -329,7 +332,7 @@ pub fn check_special_as_max_len( .set_type(&args[1], TypeSignature::UIntType)?; let expected_len = - u32::try_from(expected_len).map_err(|_e| CheckErrorKind::MaxLengthOverflow)?; + u32::try_from(expected_len).map_err(|_e| StaticCheckErrorKind::MaxLengthOverflow)?; let sequence = checker.type_check(&args[0], context)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -355,7 +358,7 @@ pub fn check_special_as_max_len( StringUTF8Length::try_from(expected_len)?, )))), )), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(sequence)).into()), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new(sequence)).into()), } } @@ -371,7 +374,9 @@ pub fn check_special_len( match collection_type { TypeSignature::SequenceType(_) => Ok(()), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type))), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new( + collection_type, + ))), }?; Ok(TypeSignature::UIntType) @@ -400,16 +405,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(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, )))), )), TypeSignature::SequenceType(StringType(UTF8(_))) => Ok(TypeSignature::OptionalType( Box::new(TypeSignature::SequenceType(StringType(UTF8( StringUTF8Length::try_from(1u32) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, )))), )), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type)).into()), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new(collection_type)).into()), } } @@ -425,7 +430,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(CheckErrorKind::ExpectedSequence(Box::new(list_type))), + _ => Err(StaticCheckErrorKind::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 39e52b274d2..22272d7e435 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::CheckErrorKind; +use crate::vm::analysis::errors::StaticCheckErrorKind; 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 = [ - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::BadTokenName, - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::NoSuchNFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::NoSuchNFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::NoSuchNFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::NoSuchNFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::NoSuchNFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::NoSuchNFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrorKind::DefineNFTBadSignature, - CheckErrorKind::TypeError( + StaticCheckErrorKind::DefineNFTBadSignature, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::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 6b6c5137276..3ff400d42ee 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,10 +19,10 @@ 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::CheckErrorKind; use crate::vm::analysis::{mem_type_check, type_check}; use crate::vm::ast::parse; use crate::vm::database::MemoryBackingStore; +use crate::vm::errors::StaticCheckErrorKind; use crate::vm::types::QualifiedContractIdentifier; use crate::vm::ClarityVersion; @@ -492,7 +492,7 @@ fn test_names_tokens_contracts_bad() { ) }) .unwrap_err(); - assert!(matches!(*err.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*err.err, StaticCheckErrorKind::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, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*err.err, StaticCheckErrorKind::TypeError(_, _))); } assert!(matches!( @@ -545,7 +545,7 @@ fn test_bad_map_usage() { ) .unwrap_err() .err, - CheckErrorKind::UnionTypeError(_, _) + StaticCheckErrorKind::UnionTypeError(_, _) )); } @@ -665,7 +665,7 @@ fn test_expects() { eprintln!("unmatched_return_types returned check error: {err}"); assert!(matches!( *err.err, - CheckErrorKind::ReturnTypesMustMatch(_, _) + StaticCheckErrorKind::ReturnTypesMustMatch(_, _) )); } @@ -678,7 +678,7 @@ fn test_expects() { eprintln!("bad_default_types returned check error: {err}"); assert!(matches!( *err.err, - CheckErrorKind::DefaultTypesMustMatch(_, _) + StaticCheckErrorKind::DefaultTypesMustMatch(_, _) )); let err = mem_type_check( @@ -690,7 +690,7 @@ fn test_expects() { eprintln!("notype_response_type returned check error: {err}"); assert!(matches!( *err.err, - CheckErrorKind::CouldNotDetermineResponseErrType + StaticCheckErrorKind::CouldNotDetermineResponseErrType )); let err = mem_type_check( @@ -702,6 +702,6 @@ fn test_expects() { eprintln!("notype_response_type_2 returned check error: {err}"); assert!(matches!( *err.err, - CheckErrorKind::CouldNotDetermineResponseOkType + StaticCheckErrorKind::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 db7cdf7810f..6a130dd6537 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,7 +16,7 @@ use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError, SyntaxBindingError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind, SyntaxBindingError}; use crate::vm::analysis::mem_type_check; use crate::vm::ast::build_ast; use crate::vm::ast::errors::ParseErrorKind; @@ -69,10 +69,10 @@ fn test_get_block_info() { "(get-block-info? time)", ]; let bad_expected = [ - 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), + StaticCheckErrorKind::NoSuchBlockInfoProperty("none".to_string()), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::RequiresAtLeastArguments(2, 1), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -113,10 +113,10 @@ fn test_define_trait() { "(define-trait)", ]; let bad_expected = [ - CheckErrorKind::InvalidTypeDescription, - CheckErrorKind::DefineTraitBadSignature, - CheckErrorKind::DefineTraitBadSignature, - CheckErrorKind::InvalidTypeDescription, + StaticCheckErrorKind::InvalidTypeDescription, + StaticCheckErrorKind::DefineTraitBadSignature, + StaticCheckErrorKind::DefineTraitBadSignature, + StaticCheckErrorKind::InvalidTypeDescription, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -216,16 +216,16 @@ fn test_stx_ops() { "(stx-get-balance 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)" ]; let bad_expected = [ - 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), + StaticCheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -291,7 +291,7 @@ fn test_destructuring_opts() { let bad = [ ( "(unwrap-err! (some 2) 2)", - CheckErrorKind::ExpectedResponseType(Box::new(TypeSignature::from_string( + StaticCheckErrorKind::ExpectedResponseType(Box::new(TypeSignature::from_string( "(optional int)", ClarityVersion::Clarity1, StacksEpochId::Epoch2_05, @@ -299,90 +299,99 @@ fn test_destructuring_opts() { ), ( "(unwrap! (err 3) 2)", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-err-panic (ok 3))", - CheckErrorKind::CouldNotDetermineResponseErrType, + StaticCheckErrorKind::CouldNotDetermineResponseErrType, ), ( "(unwrap-panic none)", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(define-private (foo) (if (> 1 0) none none)) (unwrap-panic (foo))", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-panic (err 3))", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(match none inner-value (/ 1 0) (+ 1 8))", - CheckErrorKind::CouldNotDetermineMatchTypes, + StaticCheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (ok 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrorKind::CouldNotDetermineMatchTypes, + StaticCheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (err 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrorKind::CouldNotDetermineMatchTypes, + StaticCheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(define-private (foo) (if (> 1 0) (ok 1) (err u8))) (match (foo) ok-val (+ 1 ok-val) err-val (/ err-val u0))", - CheckErrorKind::MatchArmsMustMatch( + StaticCheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value) (> 1 28))", - CheckErrorKind::MatchArmsMustMatch( + StaticCheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::BoolType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value))", - CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::IncorrectArgumentCount( - 4, 3, - ))), + StaticCheckErrorKind::BadMatchOptionSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(4, 3), + )), ), ( "(match (ok 1) inner-value (+ 1 inner-value))", - CheckErrorKind::BadMatchResponseSyntax(Box::new( - CheckErrorKind::IncorrectArgumentCount(5, 3), + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(5, 3), )), ), ( "(match (ok 1) 1 (+ 1 1) err-val (+ 2 err-val))", - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )), ), ( "(match (ok 1) ok-val (+ 1 1) (+ 3 4) (+ 2 err-val))", - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )), ), ( "(match (some 1) 2 (+ 1 1) (+ 3 4))", - CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)), + StaticCheckErrorKind::BadMatchOptionSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )), + ), + ( + "(match)", + StaticCheckErrorKind::RequiresAtLeastArguments(1, 0), ), - ("(match)", CheckErrorKind::RequiresAtLeastArguments(1, 0)), ( "(match 1 ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrorKind::BadMatchInput(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::BadMatchInput(Box::new(TypeSignature::IntType)), ), ( "(default-to 3 5)", - CheckErrorKind::ExpectedOptionalType(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::ExpectedOptionalType(Box::new(TypeSignature::IntType)), ), ( "(define-private (foo (x int)) (match (some 3) x (+ x 2) 5))", - CheckErrorKind::NameAlreadyUsed("x".to_string()), + StaticCheckErrorKind::NameAlreadyUsed("x".to_string()), ), ( "(define-private (t1 (x uint)) (if (> x u1) (ok x) (err false))) @@ -390,7 +399,7 @@ fn test_destructuring_opts() { (if (> x u4) (err u3) (ok (+ u2 (try! (t1 x))))))", - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -405,7 +414,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))))", - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -415,23 +424,23 @@ fn test_destructuring_opts() { ), ( "(try! (ok 3))", - CheckErrorKind::CouldNotDetermineResponseErrType, + StaticCheckErrorKind::CouldNotDetermineResponseErrType, ), ( "(try! none)", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(try! (err 3))", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(try! 3)", - CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), ), ( "(try! (ok 3) 4)", - CheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), ), ]; @@ -459,14 +468,14 @@ fn test_at_block() { let bad = [ ( "(at-block (sha512 u0) u1)", - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_32), Box::new(TypeSignature::BUFFER_64), ), ), ( "(at-block (sha256 u0) u1 u2)", - CheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), ), ]; @@ -507,7 +516,7 @@ fn test_trait_reference_unknown() { fn test_unexpected_use_of_field_or_trait_reference() { let bad = [( "(+ 1 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.contract.field)", - CheckErrorKind::UnexpectedTraitOrFieldReference, + StaticCheckErrorKind::UnexpectedTraitOrFieldReference, )]; for (bad_test, expected) in bad.iter() { @@ -532,12 +541,12 @@ fn test_simple_arithmetic_checks() { "(and (or true false) (+ 1 2 3))", ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::RequiresAtLeastArguments(1, 0), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::UndefinedVariable("x".to_string()), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -598,14 +607,14 @@ fn test_simple_hash_checks() { for bad_test in bad_types.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrorKind::UnionTypeError(_, _) + StaticCheckErrorKind::UnionTypeError(_, _) )); } for bad_test in invalid_args.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrorKind::IncorrectArgumentCount(_, _) + StaticCheckErrorKind::IncorrectArgumentCount(_, _) )); } } @@ -628,10 +637,10 @@ fn test_simple_ifs() { ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::IfArmsMustMatch(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IfArmsMustMatch(Box::new(ascii_type(1)), Box::new(BoolType)), + StaticCheckErrorKind::IncorrectArgumentCount(3, 0), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -664,9 +673,9 @@ fn test_simple_lets() { ]; let bad_expected = [ - CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), - CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), @@ -721,26 +730,26 @@ fn test_index_of() { ]; let bad_expected = [ - CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_MIN), Box::new(TypeSignature::STRING_ASCII_MIN), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::STRING_UTF8_MIN), Box::new(TypeSignature::STRING_ASCII_MIN), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::STRING_ASCII_MIN), Box::new(TypeSignature::STRING_UTF8_MIN), ), - CheckErrorKind::CouldNotDetermineType, - CheckErrorKind::CouldNotDetermineType, - CheckErrorKind::CouldNotDetermineType, + StaticCheckErrorKind::CouldNotDetermineType, + StaticCheckErrorKind::CouldNotDetermineType, + StaticCheckErrorKind::CouldNotDetermineType, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -769,11 +778,11 @@ fn test_element_at() { let bad = ["(element-at (list 1 2 3 4 5) 100)", "(element-at 3 u100)"]; let bad_expected = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -805,12 +814,12 @@ fn test_eqs() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::list_of(IntType, 1).unwrap()), Box::new(IntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(optional bool)", ClarityVersion::Clarity1, @@ -852,9 +861,9 @@ fn test_asserts() { ]; let bad_expected = [ - CheckErrorKind::IncorrectArgumentCount(2, 1), - CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -918,23 +927,23 @@ fn test_lists() { "(map + (list 1 2 3 4 5) (list true true true true true))", ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::UnknownFunction("ynot".to_string()), + StaticCheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(UIntType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -975,20 +984,20 @@ fn test_buff() { "(len 1)", ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::UnknownFunction("ynot".to_string()), + StaticCheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(UIntType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1063,9 +1072,9 @@ fn test_native_as_max_len() { "(as-max-len? 0x01 u1048577)", ]; let bad_expected = [ - CheckErrorKind::ValueTooLarge, - CheckErrorKind::ValueTooLarge, - CheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1109,9 +1118,9 @@ fn test_native_append() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1137,9 +1146,9 @@ fn test_native_concat() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1235,8 +1244,8 @@ fn test_tuples() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1266,7 +1275,7 @@ fn test_empty_tuple_should_fail() { ) .unwrap_err() .err, - CheckErrorKind::EmptyTuplesNotAllowed + StaticCheckErrorKind::EmptyTuplesNotAllowed ); } @@ -1362,9 +1371,9 @@ fn test_simple_uints() { let bad = ["(> u1 1)", "(to-uint true)", "(to-int false)"]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1425,7 +1434,7 @@ fn test_response_inference() { ]; let bad_expected = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(response bool int)", ClarityVersion::Clarity1, @@ -1433,8 +1442,8 @@ fn test_response_inference() { )), Box::new(BoolType), ), - CheckErrorKind::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1572,7 +1581,7 @@ fn test_options() { .unwrap_err() .err { - CheckErrorKind::TypeError(t1, t2) => { + StaticCheckErrorKind::TypeError(t1, t2) => { *t1 == TypeSignature::from_string( "(optional bool)", ClarityVersion::Clarity1, @@ -1724,7 +1733,7 @@ fn test_missing_value_on_declaration_should_fail() { .unwrap_err(); assert!(matches!( *res.err, - CheckErrorKind::IncorrectArgumentCount(_, _) + StaticCheckErrorKind::IncorrectArgumentCount(_, _) )); } @@ -1740,7 +1749,7 @@ fn test_mismatching_type_on_declaration_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } #[test] @@ -1761,7 +1770,7 @@ fn test_mismatching_type_on_update_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } #[test] @@ -1778,7 +1787,10 @@ fn test_direct_access_to_persisted_var_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } #[test] @@ -1798,7 +1810,7 @@ fn test_data_var_shadowed_by_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1816,7 +1828,10 @@ fn test_mutating_unknown_data_var_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::NoSuchDataVariable(_) + )); } #[test] @@ -1832,7 +1847,10 @@ fn test_accessing_unknown_data_var_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::NoSuchDataVariable(_) + )); } #[test] @@ -1848,7 +1866,7 @@ fn test_let_shadowed_by_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1865,7 +1883,7 @@ fn test_let_shadowed_by_nested_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1883,7 +1901,7 @@ fn test_define_constant_shadowed_by_let_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -1900,7 +1918,7 @@ fn test_define_constant_shadowed_by_argument_should_fail() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2122,7 +2140,7 @@ fn test_fetch_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -2142,7 +2160,10 @@ fn test_fetch_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -2194,7 +2215,7 @@ fn test_insert_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -2217,7 +2238,10 @@ fn test_insert_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -2267,7 +2291,7 @@ fn test_delete_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -2287,7 +2311,10 @@ fn test_delete_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -2341,7 +2368,7 @@ fn test_set_entry_mismatching_type_signatures() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -2364,7 +2391,10 @@ fn test_set_entry_unbound_variables() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -2499,7 +2529,7 @@ fn test_buff_negative_len() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); + assert_eq!(*res.err, StaticCheckErrorKind::ValueOutOfBounds); } #[test] @@ -2513,7 +2543,7 @@ fn test_string_ascii_negative_len() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); + assert_eq!(*res.err, StaticCheckErrorKind::ValueOutOfBounds); } #[test] @@ -2527,5 +2557,5 @@ fn test_string_utf8_negative_len() { StacksEpochId::Epoch2_05, ) .unwrap_err(); - assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); + assert_eq!(*res.err, StaticCheckErrorKind::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 7632ea305bb..c8998b90190 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::{CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind}; use crate::vm::analysis::type_checker::is_reserved_word; use crate::vm::analysis::types::ContractAnalysis; use crate::vm::representations::ClarityName; @@ -169,7 +169,7 @@ impl ContractContext { pub fn check_name_used(&self, name: &str) -> Result<(), StaticCheckError> { if is_reserved_word(name, self.clarity_version) { - return Err(StaticCheckError::new(CheckErrorKind::ReservedWord( + return Err(StaticCheckError::new(StaticCheckErrorKind::ReservedWord( name.to_string(), ))); } @@ -183,9 +183,9 @@ impl ContractContext { || self.traits.is_name_used(name) || self.map_types.contains_key(name) { - Err(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( - name.to_string(), - ))) + Err(StaticCheckError::new( + StaticCheckErrorKind::NameAlreadyUsed(name.to_string()), + )) } else { Ok(()) } 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 d2b17abc3b6..b150ed72e6c 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, CheckErrorKind, - StaticCheckError, SyntaxBindingErrorType, + check_argument_count, check_arguments_at_least, check_arguments_at_most, + StaticCheckError, StaticCheckErrorKind, SyntaxBindingErrorType, }; use crate::vm::analysis::AnalysisDatabase; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -161,14 +161,6 @@ pub fn compute_typecheck_cost( ) } -pub fn check_argument_len(expected: usize, args_len: usize) -> Result<(), CheckErrorKind> { - if args_len != expected { - Err(CheckErrorKind::IncorrectArgumentCount(expected, args_len)) - } else { - Ok(()) - } -} - impl FunctionType { #[allow(clippy::type_complexity)] pub fn check_args_visitor_2_1( @@ -192,7 +184,7 @@ impl FunctionType { if !admitted { return ( cost, - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(arg_type.clone()), ) @@ -211,7 +203,7 @@ impl FunctionType { let return_type = match arg_type { TypeSignature::IntType => Ok(Some(TypeSignature::IntType)), TypeSignature::UIntType => Ok(Some(TypeSignature::UIntType)), - _ => Err(CheckErrorKind::UnionTypeError( + _ => Err(StaticCheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(arg_type.clone()), ) @@ -220,10 +212,10 @@ impl FunctionType { (cost, return_type) } else { let return_type = accumulated_type - .ok_or_else(|| CheckErrorKind::Expects("Failed to set accumulated type for arg indices >= 1 in variadic arithmetic".into()).into()); + .ok_or_else(|| StaticCheckErrorKind::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(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(return_type.clone()), Box::new(arg_type.clone()), ) @@ -246,10 +238,11 @@ impl FunctionType { // note: argument count will be wrong? return ( None, - Err( - CheckErrorKind::IncorrectArgumentCount(arg_types.len(), arg_index) - .into(), - ), + Err(StaticCheckErrorKind::IncorrectArgumentCount( + arg_types.len(), + arg_index, + ) + .into()), ); } (None, Ok(None)) @@ -262,7 +255,7 @@ impl FunctionType { if arg_index >= 1 { return ( None, - Err(CheckErrorKind::IncorrectArgumentCount(1, arg_index).into()), + Err(StaticCheckErrorKind::IncorrectArgumentCount(1, arg_index).into()), ); } (None, Ok(None)) @@ -273,7 +266,7 @@ impl FunctionType { if arg_index >= 2 { return ( None, - Err(CheckErrorKind::IncorrectArgumentCount(2, arg_index).into()), + Err(StaticCheckErrorKind::IncorrectArgumentCount(2, arg_index).into()), ); } (None, Ok(None)) @@ -293,7 +286,7 @@ impl FunctionType { 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(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -311,7 +304,7 @@ impl FunctionType { { analysis_typecheck_cost(accounting, expected_type, found_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch21, found_type)? { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(found_type.clone()), ) @@ -329,10 +322,11 @@ impl FunctionType { return Ok(return_type.clone()); } } - Err( - CheckErrorKind::UnionTypeError(arg_types.clone(), Box::new(found_type.clone())) - .into(), + Err(StaticCheckErrorKind::UnionTypeError( + arg_types.clone(), + Box::new(found_type.clone()), ) + .into()) } FunctionType::Binary(left_arg_sig, right_arg_sig, return_sig) => { check_argument_count(2, args)?; @@ -357,14 +351,17 @@ impl FunctionType { if self == &FunctionType::ArithmeticBinary { check_argument_count(2, args)?; } - let (first, rest) = args - .split_first() - .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, args.len()))?; + let (first, rest) = + args.split_first() + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::UnionTypeError( + _ => Err(StaticCheckErrorKind::UnionTypeError( vec![TypeSignature::IntType, TypeSignature::UIntType], Box::new(first.clone()), )), @@ -372,7 +369,7 @@ impl FunctionType { for found_type in rest.iter() { analysis_typecheck_cost(accounting, &TypeSignature::IntType, found_type)?; if found_type != &return_type { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(return_type.clone()), Box::new(found_type.clone()), ) @@ -406,7 +403,7 @@ impl FunctionType { }; if !first_type_supported { - return Err(CheckErrorKind::UnionTypeError( + return Err(StaticCheckErrorKind::UnionTypeError( vec![ TypeSignature::IntType, TypeSignature::UIntType, @@ -448,7 +445,7 @@ impl FunctionType { }; if !pair_of_types_matches { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(first.clone()), Box::new(second.clone()), ) @@ -493,7 +490,7 @@ impl FunctionType { depth: u8, ) -> Result { if depth > MAX_TYPE_DEPTH { - return Err(CheckErrorKind::TypeSignatureTooDeep.into()); + return Err(StaticCheckErrorKind::TypeSignatureTooDeep.into()); } Ok(match value { @@ -563,7 +560,9 @@ impl FunctionType { ) -> Result { let (expected_args, returns) = match self { FunctionType::Fixed(FixedFunction { args, returns }) => (args, returns), - _ => return Err(CheckErrorKind::Expects("Unexpected function type".into()).into()), + _ => { + return Err(StaticCheckErrorKind::Expects("Unexpected function type".into()).into()) + } }; check_argument_count(expected_args.len(), func_args)?; @@ -577,7 +576,7 @@ impl FunctionType { let contract_to_check = db .load_contract(contract, &StacksEpochId::Epoch21)? .ok_or_else(|| { - CheckErrorKind::NoSuchContract(contract.name.to_string()) + StaticCheckErrorKind::NoSuchContract(contract.name.to_string()) })?; let trait_definition = db .get_defined_trait( @@ -585,8 +584,10 @@ impl FunctionType { &trait_id.name, &StacksEpochId::Epoch21, ) - .map_err(|_| CheckErrorKind::Expects("Failed to get trait".into()))? - .ok_or(CheckErrorKind::NoSuchContract( + .map_err(|_| { + StaticCheckErrorKind::Expects("Failed to get trait".into()) + })? + .ok_or(StaticCheckErrorKind::NoSuchContract( trait_id.contract_identifier.to_string(), ))?; contract_to_check.check_trait_compliance( @@ -598,7 +599,7 @@ impl FunctionType { (expected_type, value) => { if !expected_type.admits(&StacksEpochId::Epoch21, value)? { let actual_type = TypeSignature::type_of(value)?; - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -637,7 +638,7 @@ fn check_function_arg_signature( FunctionArgSignature::Single(expected_type) => { analysis_typecheck_cost(cost_tracker, expected_type, actual_type)?; if !expected_type.admits_type(&StacksEpochId::Epoch21, actual_type)? { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -654,7 +655,7 @@ fn check_function_arg_signature( } } if !admitted { - return Err(CheckErrorKind::UnionTypeError( + return Err(StaticCheckErrorKind::UnionTypeError( expected_types.clone(), Box::new(actual_type.clone()), ) @@ -735,14 +736,14 @@ pub fn clarity2_trait_check_trait_compliance( func, tracker, ) { - return Err(CheckErrorKind::IncompatibleTrait( + return Err(StaticCheckErrorKind::IncompatibleTrait( Box::new(expected_trait_identifier.clone()), Box::new(actual_trait_identifier.clone()), ) .into()); } } else { - return Err(CheckErrorKind::IncompatibleTrait( + return Err(StaticCheckErrorKind::IncompatibleTrait( Box::new(expected_trait_identifier.clone()), Box::new(actual_trait_identifier.clone()), ) @@ -763,7 +764,7 @@ fn clarity2_inner_type_check_type( tracker: &mut T, ) -> Result { if depth > MAX_TYPE_DEPTH { - return Err(CheckErrorKind::TypeSignatureTooDeep.into()); + return Err(StaticCheckErrorKind::TypeSignatureTooDeep.into()); } // Recurse into values to check embedded traits properly @@ -816,7 +817,7 @@ fn clarity2_inner_type_check_type( tracker, )?; } else { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -828,7 +829,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(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -848,7 +849,7 @@ fn clarity2_inner_type_check_type( )?; } None => { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -881,24 +882,24 @@ fn clarity2_inner_type_check_type( TypeSignature::CallableType(CallableSubtype::Principal(contract_identifier)), TypeSignature::CallableType(CallableSubtype::Trait(expected_trait_id)), ) => { - let contract_to_check = match db - .load_contract(contract_identifier, &StacksEpochId::Epoch21)? - { - Some(contract) => { - runtime_cost( - ClarityCostFunction::AnalysisFetchContractEntry, - tracker, - contract_analysis_size(&contract)?, - )?; - contract - } - None => { - runtime_cost(ClarityCostFunction::AnalysisFetchContractEntry, tracker, 1)?; - return Err( - CheckErrorKind::NoSuchContract(contract_identifier.to_string()).into(), - ); - } - }; + let contract_to_check = + match db.load_contract(contract_identifier, &StacksEpochId::Epoch21)? { + Some(contract) => { + runtime_cost( + ClarityCostFunction::AnalysisFetchContractEntry, + tracker, + contract_analysis_size(&contract)?, + )?; + contract + } + None => { + runtime_cost(ClarityCostFunction::AnalysisFetchContractEntry, tracker, 1)?; + return Err(StaticCheckErrorKind::NoSuchContract( + contract_identifier.to_string(), + ) + .into()); + } + }; let expected_trait = clarity2_lookup_trait(db, contract_context, expected_trait_id, tracker)?; contract_to_check.check_trait_compliance( @@ -926,7 +927,7 @@ fn clarity2_inner_type_check_type( (TypeSignature::NoType, _) => (), (_, _) => { if !expected_type.admits_type(&StacksEpochId::Epoch21, actual_type)? { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -948,7 +949,7 @@ fn clarity2_lookup_trait( if contract_context.is_contract(&trait_id.contract_identifier) { return Ok(contract_context .get_trait(trait_id) - .ok_or(CheckErrorKind::NoSuchTrait( + .ok_or(StaticCheckErrorKind::NoSuchTrait( trait_id.contract_identifier.to_string(), trait_id.name.to_string(), ))? @@ -975,7 +976,7 @@ fn clarity2_lookup_trait( } Ok(None) => { runtime_cost(ClarityCostFunction::AnalysisUseTraitEntry, tracker, 1)?; - Err(CheckErrorKind::NoSuchTrait( + Err(StaticCheckErrorKind::NoSuchTrait( trait_id.contract_identifier.to_string(), trait_id.name.to_string(), ) @@ -1013,14 +1014,14 @@ fn type_reserved_variable( let var_type = match variable { TxSender => TypeSignature::PrincipalType, TxSponsor => TypeSignature::new_option(TypeSignature::PrincipalType) - .map_err(|_| CheckErrorKind::Expects("Bad construction".into()))?, + .map_err(|_| StaticCheckErrorKind::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(|_| CheckErrorKind::Expects("Bad construction".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad construction".into()))?, NativeTrue => TypeSignature::BoolType, NativeFalse => TypeSignature::BoolType, TotalLiquidMicroSTX => TypeSignature::UIntType, @@ -1089,7 +1090,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new(expected_type), Box::new(return_type), ) @@ -1120,7 +1121,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } Err(e) => Err(e), })? - .ok_or_else(|| CheckErrorKind::Expects("Expected a depth result".into()))?; + .ok_or_else(|| StaticCheckErrorKind::Expects("Expected a depth result".into()))?; } runtime_cost(ClarityCostFunction::AnalysisStorage, self, size)?; @@ -1195,15 +1196,16 @@ impl<'a, 'b> TypeChecker<'a, 'b> { let type_return = self.type_check(&args[ix], context)?; if ix + 1 < args.len() { if type_return.is_response_type() { - return_failure = Err(CheckErrorKind::UncheckedIntermediaryResponses); + return_failure = Err(StaticCheckErrorKind::UncheckedIntermediaryResponses); } } else { last_return = Some(type_return); } } - let last_return = last_return - .ok_or_else(|| StaticCheckError::new(CheckErrorKind::CheckerImplementationFailure))?; + let last_return = last_return.ok_or_else(|| { + StaticCheckError::new(StaticCheckErrorKind::CheckerImplementationFailure) + })?; return_failure?; Ok(last_return) @@ -1266,9 +1268,13 @@ impl<'a, 'b> TypeChecker<'a, 'b> { } } if let Err(mut check_error) = check_result { - if let CheckErrorKind::IncorrectArgumentCount(expected, _actual) = *check_error.err { - check_error.err = - Box::new(CheckErrorKind::IncorrectArgumentCount(expected, args.len())); + if let StaticCheckErrorKind::IncorrectArgumentCount(expected, _actual) = + *check_error.err + { + check_error.err = Box::new(StaticCheckErrorKind::IncorrectArgumentCount( + expected, + args.len(), + )); check_error.diagnostic = Diagnostic::err(check_error.err.as_ref()); } // accumulate the checking costs @@ -1298,10 +1304,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result<(ClarityName, FixedFunction), StaticCheckError> { let (function_name, args) = signature .split_first() - .ok_or(CheckErrorKind::RequiresAtLeastArguments(1, 0))?; + .ok_or(StaticCheckErrorKind::RequiresAtLeastArguments(1, 0))?; let function_name = function_name .match_atom() - .ok_or(CheckErrorKind::BadFunctionName)?; + .ok_or(StaticCheckErrorKind::BadFunctionName)?; let args = parse_name_type_pairs::<(), StaticCheckError>( StacksEpochId::Epoch21, args, @@ -1310,7 +1316,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { )?; if self.function_return_tracker.is_some() { - return Err(CheckErrorKind::Expects( + return Err(StaticCheckErrorKind::Expects( "Interpreter error: Previous function define left dirty typecheck state.".into(), ) .into()); @@ -1366,7 +1372,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &return_type, ) .map_err(|_| { - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new(expected.clone()), Box::new(return_type), ) @@ -1406,10 +1412,10 @@ impl<'a, 'b> TypeChecker<'a, 'b> { // 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(|_| CheckErrorKind::BadMapTypeDefinition)?; + .map_err(|_| StaticCheckErrorKind::BadMapTypeDefinition)?; let value_type = TypeSignature::parse_type_repr(StacksEpochId::Epoch21, value_type, &mut ()) - .map_err(|_| CheckErrorKind::BadMapTypeDefinition)?; + .map_err(|_| StaticCheckErrorKind::BadMapTypeDefinition)?; Ok((map_name.clone(), (key_type, value_type))) } @@ -1441,19 +1447,21 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result { let (function_name, args) = expression .split_first() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::NonFunctionApplication)?; self.type_map.set_type(function_name, no_type())?; let function_name = function_name .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::UnknownFunction(function_name.to_string())), + _ => Err(StaticCheckErrorKind::UnknownFunction( + function_name.to_string(), + )), }?; for (expected_type, found_type) in function.args.iter().map(|x| &x.signature).zip(args) @@ -1485,7 +1493,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(CheckErrorKind::UndefinedVariable(name.to_string()).into()); + return Err(StaticCheckErrorKind::UndefinedVariable(name.to_string()).into()); } runtime_cost( @@ -1497,7 +1505,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { if let Some(type_result) = context.lookup_variable_type(name) { Ok(type_result.clone()) } else { - Err(CheckErrorKind::UndefinedVariable(name.to_string()).into()) + Err(StaticCheckErrorKind::UndefinedVariable(name.to_string()).into()) } } } @@ -1516,7 +1524,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { let contract_to_check = self .db .load_contract(contract_identifier, &StacksEpochId::Epoch21)? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( contract_identifier.to_string(), ))?; @@ -1526,13 +1534,13 @@ impl<'a, 'b> TypeChecker<'a, 'b> { &trait_identifier.contract_identifier, &StacksEpochId::Epoch21, )? - .ok_or(CheckErrorKind::NoSuchContract( + .ok_or(StaticCheckErrorKind::NoSuchContract( trait_identifier.contract_identifier.to_string(), ))?; let trait_definition = contract_defining_trait .get_defined_trait(&trait_identifier.name) - .ok_or(CheckErrorKind::NoSuchTrait( + .ok_or(StaticCheckErrorKind::NoSuchTrait( trait_identifier.contract_identifier.to_string(), trait_identifier.name.to_string(), ))?; @@ -1549,7 +1557,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: StaticCheckError = CheckErrorKind::TypeError( + let mut err: StaticCheckError = StaticCheckErrorKind::TypeError( Box::new(expected_type.clone()), Box::new(actual_type.clone()), ) @@ -1573,7 +1581,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { Atom(ref name) => self.lookup_variable(name, context)?, List(ref expression) => self.type_check_function_application(expression, context)?, TraitReference(_, _) | Field(_) => { - return Err(CheckErrorKind::UnexpectedTraitOrFieldReference.into()); + return Err(StaticCheckErrorKind::UnexpectedTraitOrFieldReference.into()); } }; @@ -1611,7 +1619,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { Atom(ref name) => self.lookup_variable(name, context)?, List(ref expression) => self.type_check_function_application(expression, context)?, TraitReference(_, _) | Field(_) => { - return Err(CheckErrorKind::UnexpectedTraitOrFieldReference.into()); + return Err(StaticCheckErrorKind::UnexpectedTraitOrFieldReference.into()); } }; @@ -1643,7 +1651,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let expected_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch21, var_type, &mut ()) - .map_err(|_e| CheckErrorKind::DefineVariableBadSignature)?; + .map_err(|_e| StaticCheckErrorKind::DefineVariableBadSignature)?; self.type_check_expects(initial, context, &expected_type)?; @@ -1671,7 +1679,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { ) -> Result<(ClarityName, TypeSignature), StaticCheckError> { let asset_type = TypeSignature::parse_type_repr::<()>(StacksEpochId::Epoch21, nft_type, &mut ()) - .map_err(|_| CheckErrorKind::DefineNFTBadSignature)?; + .map_err(|_| StaticCheckErrorKind::DefineNFTBadSignature)?; Ok((asset_name.clone(), asset_type)) } @@ -1746,9 +1754,9 @@ impl<'a, 'b> TypeChecker<'a, 'b> { .add_public_function_type(f_name, FunctionType::Fixed(f_type))?; return Ok(Some(())); } else { - return Err(CheckErrorKind::PublicFunctionMustReturnResponse(Box::new( - f_type.returns, - )) + return Err(StaticCheckErrorKind::PublicFunctionMustReturnResponse( + Box::new(f_type.returns), + ) .into()); } } @@ -1889,9 +1897,10 @@ 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( - CheckErrorKind::TraitReferenceUnknown(name.to_string()).into() - ); + return Err(StaticCheckErrorKind::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 098300af775..b6461217d75 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,9 @@ use stacks_common::consts::TOKEN_TRANSFER_MEMO_LENGTH; use super::{TypeChecker, TypingContext}; -use crate::vm::analysis::errors::{check_argument_count, CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{ + check_argument_count, StaticCheckError, StaticCheckErrorKind, +}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::representations::SymbolicExpression; @@ -30,13 +32,15 @@ pub fn check_special_get_owner( ) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) .cloned() - .ok_or_else(|| CheckErrorKind::NoSuchNFT(asset_name.to_string()))?; + .ok_or_else(|| StaticCheckErrorKind::NoSuchNFT(asset_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -58,10 +62,12 @@ pub fn check_special_get_balance( ) -> Result { check_argument_count(2, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -79,13 +85,15 @@ pub fn check_special_mint_asset( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? + .ok_or(StaticCheckErrorKind::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( @@ -110,7 +118,9 @@ pub fn check_special_mint_token( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -121,7 +131,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(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -137,13 +147,15 @@ pub fn check_special_transfer_asset( ) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let token_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(token_name) - .ok_or(CheckErrorKind::NoSuchNFT(token_name.to_string()))? + .ok_or(StaticCheckErrorKind::NoSuchNFT(token_name.to_string()))? .clone(); runtime_cost( @@ -169,7 +181,9 @@ pub fn check_special_transfer_token( ) -> Result { check_argument_count(4, args)?; - let token_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let token_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -181,7 +195,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(CheckErrorKind::NoSuchFT(token_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(token_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( @@ -225,7 +239,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(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, )); runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 0)?; @@ -248,10 +262,12 @@ pub fn check_special_get_token_supply( ) -> Result { check_argument_count(1, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; if !checker.contract_context.ft_exists(asset_name) { - return Err(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } runtime_cost(ClarityCostFunction::AnalysisTypeLookup, checker, 1)?; @@ -266,13 +282,15 @@ pub fn check_special_burn_asset( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; let expected_asset_type = checker .contract_context .get_nft_type(asset_name) - .ok_or(CheckErrorKind::NoSuchNFT(asset_name.to_string()))? + .ok_or(StaticCheckErrorKind::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( @@ -297,7 +315,9 @@ pub fn check_special_burn_token( ) -> Result { check_argument_count(3, args)?; - let asset_name = args[0].match_atom().ok_or(CheckErrorKind::BadTokenName)?; + let asset_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadTokenName)?; let expected_amount: TypeSignature = TypeSignature::UIntType; let expected_owner_type: TypeSignature = TypeSignature::PrincipalType; @@ -308,7 +328,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(CheckErrorKind::NoSuchFT(asset_name.to_string()).into()); + return Err(StaticCheckErrorKind::NoSuchFT(asset_name.to_string()).into()); } Ok(TypeSignature::ResponseType(Box::new(( 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 0b95c44f86c..ca520bced38 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,8 @@ use stacks_common::types::StacksEpochId; use crate::vm::analysis::type_checker::v2_1::{ - check_arguments_at_least, CheckErrorKind, StaticCheckError, TypeChecker, TypingContext, + check_arguments_at_least, StaticCheckError, StaticCheckErrorKind, TypeChecker, + TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; @@ -31,14 +32,16 @@ pub fn check_special_fetch_entry( ) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let map_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::NoSuchMap(map_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -55,7 +58,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -71,14 +74,16 @@ pub fn check_special_delete_entry( ) -> Result { check_arguments_at_least(2, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let map_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let (expected_key_type, _) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -88,7 +93,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) @@ -104,7 +109,9 @@ fn check_set_or_insert_entry( ) -> Result { check_arguments_at_least(3, args)?; - let map_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let map_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::BadMapName)?; let key_type = checker.type_check(&args[1], context)?; let value_type = checker.type_check(&args[2], context)?; @@ -112,7 +119,7 @@ fn check_set_or_insert_entry( let (expected_key_type, expected_value_type) = checker .contract_context .get_map_type(map_name) - .ok_or(CheckErrorKind::NoSuchMap(map_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchMap(map_name.to_string()))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -129,12 +136,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_key_type.clone()), Box::new(key_type), ))) } else if !expected_value_type.admits_type(&StacksEpochId::Epoch21, &value_type)? { - Err(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) 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 d91f0d7e781..b726967bd21 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::{CheckErrorKind, StaticCheckError, SyntaxBindingErrorType}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind, SyntaxBindingErrorType}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost, CostErrors, CostTracker}; use crate::vm::diagnostic::DiagnosableError; @@ -69,14 +69,17 @@ fn check_special_list_cons( for arg in args.iter() { // don't use map here, since type_check has side-effects. let checked = checker.type_check(arg, context)?; - let cost = checked.type_size().and_then(|ty_size| { - checker - .compute_cost( - ClarityCostFunction::AnalysisListItemsCheck, - &[ty_size.into()], - ) - .map_err(CheckErrorKind::from) - }); + let cost = checked + .type_size() + .map_err(StaticCheckErrorKind::from) + .and_then(|ty_size| { + checker + .compute_cost( + ClarityCostFunction::AnalysisListItemsCheck, + &[ty_size.into()], + ) + .map_err(StaticCheckErrorKind::from) + }); costs.push(cost); if let Some(cur_size) = entries_size { @@ -96,7 +99,7 @@ fn check_special_list_cons( checker.add_cost(cost?)?; } if entries_size.is_none() { - return Err(CheckErrorKind::ValueTooLarge.into()); + return Err(StaticCheckErrorKind::ValueTooLarge.into()); } let typed_args = result; TypeSignature::parent_list_type(&typed_args) @@ -155,10 +158,12 @@ fn inner_handle_tuple_get( let return_type = tuple_type_sig .field_type(field_to_get) - .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchTupleField( - field_to_get.to_string(), - tuple_type_sig.clone(), - )))? + .ok_or(StaticCheckError::new( + StaticCheckErrorKind::NoSuchTupleField( + field_to_get.to_string(), + tuple_type_sig.clone(), + ), + ))? .clone(); Ok(return_type) } @@ -172,7 +177,7 @@ fn check_special_get( let field_to_get = args[0] .match_atom() - .ok_or(CheckErrorKind::BadTupleFieldName)?; + .ok_or(StaticCheckErrorKind::BadTupleFieldName)?; let argument_type = checker.type_check(&args[1], context)?; @@ -184,10 +189,10 @@ fn check_special_get( let option_type = TypeSignature::new_option(inner_type)?; Ok(option_type) } else { - Err(CheckErrorKind::ExpectedTuple(value_type_sig).into()) + Err(StaticCheckErrorKind::ExpectedTuple(value_type_sig).into()) } } else { - Err(CheckErrorKind::ExpectedTuple(Box::new(argument_type)).into()) + Err(StaticCheckErrorKind::ExpectedTuple(Box::new(argument_type)).into()) } } @@ -201,13 +206,13 @@ fn check_special_merge( let res = checker.type_check(&args[0], context)?; let mut base = match res { TypeSignature::TupleType(tuple_sig) => Ok(tuple_sig), - _ => Err(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), + _ => Err(StaticCheckErrorKind::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(CheckErrorKind::ExpectedTuple(Box::new(res.clone()))), + _ => Err(StaticCheckErrorKind::ExpectedTuple(Box::new(res.clone()))), }?; runtime_cost( ClarityCostFunction::AnalysisCheckTupleMerge, @@ -255,7 +260,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(CheckErrorKind::BadTupleConstruction(format!( + cons_error = Err(StaticCheckErrorKind::BadTupleConstruction(format!( "type size of {type_size} bytes exceeds maximum of {MAX_VALUE_SIZE} bytes" ))); } @@ -265,8 +270,9 @@ pub fn check_special_tuple_cons( )?; cons_error?; - let tuple_signature = TupleTypeSignature::try_from(tuple_type_data) - .map_err(|e| CheckErrorKind::BadTupleConstruction(e.message()))?; + let tuple_signature = TupleTypeSignature::try_from(tuple_type_data).map_err(|e| { + StaticCheckErrorKind::BadTupleConstruction(StaticCheckErrorKind::from(e).message()) + })?; Ok(TypeSignature::TupleType(tuple_signature)) } @@ -281,7 +287,7 @@ fn check_special_let( let binding_list = args[0] .match_list() - .ok_or(StaticCheckError::new(CheckErrorKind::BadLetSyntax))?; + .ok_or(StaticCheckError::new(StaticCheckErrorKind::BadLetSyntax))?; let mut out_context = context.extend()?; @@ -294,9 +300,9 @@ 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(StaticCheckError::new(CheckErrorKind::NameAlreadyUsed( - var_name.to_string(), - ))); + return Err(StaticCheckError::new( + StaticCheckErrorKind::NameAlreadyUsed(var_name.to_string()), + )); } let typed_result = checker.type_check(var_sexp, &out_context)?; @@ -336,14 +342,14 @@ fn check_special_fetch_var( let var_name = args[0] .match_atom() - .ok_or(StaticCheckError::new(CheckErrorKind::BadMapName))?; + .ok_or(StaticCheckError::new(StaticCheckErrorKind::BadMapName))?; let value_type = checker .contract_context .get_persisted_variable_type(var_name) - .ok_or(StaticCheckError::new(CheckErrorKind::NoSuchDataVariable( - var_name.to_string(), - )))?; + .ok_or(StaticCheckError::new( + StaticCheckErrorKind::NoSuchDataVariable(var_name.to_string()), + ))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -361,14 +367,18 @@ fn check_special_set_var( ) -> Result { check_arguments_at_least(2, args)?; - let var_name = args[0].match_atom().ok_or(CheckErrorKind::BadMapName)?; + let var_name = args[0] + .match_atom() + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::NoSuchDataVariable(var_name.to_string()))?; + .ok_or(StaticCheckErrorKind::NoSuchDataVariable( + var_name.to_string(), + ))?; runtime_cost( ClarityCostFunction::AnalysisTypeLookup, @@ -378,7 +388,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(StaticCheckError::new(CheckErrorKind::TypeError( + Err(StaticCheckError::new(StaticCheckErrorKind::TypeError( Box::new(expected_value_type.clone()), Box::new(value_type), ))) @@ -407,7 +417,9 @@ fn check_special_equals( costs.push(cost); arg_type = Some( TypeSignature::least_supertype(&StacksEpochId::Epoch21, &x_type, &cur_type) - .map_err(|_| CheckErrorKind::TypeError(Box::new(x_type), Box::new(cur_type))), + .map_err(|_| { + StaticCheckErrorKind::TypeError(Box::new(x_type), Box::new(cur_type)) + }), ); } } @@ -418,7 +430,9 @@ fn check_special_equals( // check if there was a least supertype failure. arg_type.ok_or_else(|| { - CheckErrorKind::Expects("Arg type should be set because arguments checked for >= 1".into()) + StaticCheckErrorKind::Expects( + "Arg type should be set because arguments checked for >= 1".into(), + ) })??; Ok(TypeSignature::BoolType) @@ -441,9 +455,11 @@ fn check_special_if( analysis_typecheck_cost(checker, expr1, expr2)?; TypeSignature::least_supertype(&StacksEpochId::Epoch21, expr1, expr2) + .map_err(StaticCheckErrorKind::from) .and_then(|t| t.concretize()) .map_err(|_| { - CheckErrorKind::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())).into() + StaticCheckErrorKind::IfArmsMustMatch(Box::new(expr1.clone()), Box::new(expr2.clone())) + .into() }) } @@ -455,7 +471,7 @@ fn check_contract_call( check_arguments_at_least(2, args)?; let func_name = args[1].match_atom().ok_or(StaticCheckError::new( - CheckErrorKind::ContractCallExpectName, + StaticCheckErrorKind::ContractCallExpectName, ))?; checker.type_map.set_type(&args[1], no_type())?; @@ -480,10 +496,12 @@ fn check_contract_call( { Ok(function) } else { - Err(StaticCheckError::new(CheckErrorKind::NoSuchPublicFunction( - contract_identifier.to_string(), - func_name.to_string(), - ))) + Err(StaticCheckError::new( + StaticCheckErrorKind::NoSuchPublicFunction( + contract_identifier.to_string(), + func_name.to_string(), + ), + )) } }?; @@ -503,7 +521,7 @@ fn check_contract_call( let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, _ => { - return Err(CheckErrorKind::TraitReferenceUnknown( + return Err(StaticCheckErrorKind::TraitReferenceUnknown( trait_instance.to_string(), ) .into()); @@ -513,15 +531,14 @@ fn check_contract_call( runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; let trait_signature = checker.contract_context.get_trait(trait_id).ok_or( - CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), + StaticCheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), + )?; + let func_signature = trait_signature.get(func_name).ok_or( + StaticCheckErrorKind::TraitMethodUnknown( + trait_id.name.to_string(), + func_name.to_string(), + ), )?; - let func_signature = - trait_signature - .get(func_name) - .ok_or(CheckErrorKind::TraitMethodUnknown( - trait_id.name.to_string(), - func_name.to_string(), - ))?; runtime_cost( ClarityCostFunction::AnalysisLookupFunctionTypes, @@ -555,10 +572,12 @@ fn check_contract_call( { Ok(function) } else { - Err(StaticCheckError::new(CheckErrorKind::NoSuchPublicFunction( - contract_identifier.to_string(), - func_name.to_string(), - ))) + Err(StaticCheckError::new( + StaticCheckErrorKind::NoSuchPublicFunction( + contract_identifier.to_string(), + func_name.to_string(), + ), + )) } }?; @@ -574,7 +593,7 @@ fn check_contract_call( } Some(var_type) => { // Any other typed constant is an error - return Err(CheckErrorKind::ExpectedCallableType(Box::new( + return Err(StaticCheckErrorKind::ExpectedCallableType(Box::new( var_type.clone(), )) .into()); @@ -584,7 +603,7 @@ fn check_contract_call( let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, _ => { - return Err(CheckErrorKind::TraitReferenceUnknown( + return Err(StaticCheckErrorKind::TraitReferenceUnknown( trait_instance.to_string(), ) .into()); @@ -594,10 +613,10 @@ fn check_contract_call( runtime_cost(ClarityCostFunction::AnalysisLookupFunction, checker, 0)?; let trait_signature = checker.contract_context.get_trait(trait_id).ok_or( - CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), + StaticCheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()), )?; let func_signature = trait_signature.get(func_name).ok_or( - CheckErrorKind::TraitMethodUnknown( + StaticCheckErrorKind::TraitMethodUnknown( trait_id.name.to_string(), func_name.to_string(), ), @@ -616,7 +635,7 @@ fn check_contract_call( } _ => { return Err(StaticCheckError::new( - CheckErrorKind::ContractCallExpectName, + StaticCheckErrorKind::ContractCallExpectName, )) } }; @@ -640,14 +659,18 @@ fn check_contract_of( SymbolicExpressionType::Atom(trait_instance) => trait_instance, _ => { return Err(StaticCheckError::new( - CheckErrorKind::ContractOfExpectsTrait, + StaticCheckErrorKind::ContractOfExpectsTrait, )) } }; let trait_id = match context.lookup_trait_reference_type(trait_instance) { Some(trait_id) => trait_id, - _ => return Err(CheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into()), + _ => { + return Err( + StaticCheckErrorKind::TraitReferenceUnknown(trait_instance.to_string()).into(), + ) + } }; runtime_cost(ClarityCostFunction::ContractOf, checker, 1)?; @@ -655,7 +678,7 @@ fn check_contract_of( checker .contract_context .get_trait(trait_id) - .ok_or_else(|| CheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()))?; + .ok_or_else(|| StaticCheckErrorKind::TraitReferenceUnknown(trait_id.name.to_string()))?; Ok(TypeSignature::PrincipalType) } @@ -669,7 +692,7 @@ fn check_principal_of( checker.type_check_expects(&args[0], context, &TypeSignature::BUFFER_33)?; Ok( TypeSignature::new_response(TypeSignature::PrincipalType, TypeSignature::UIntType) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -701,13 +724,13 @@ fn check_principal_construct( ("error_code".into(), TypeSignature::UIntType), ( "value".into(), - TypeSignature::new_option(TypeSignature::PrincipalType).map_err(|_| CheckErrorKind::Expects("FATAL: failed to create (optional principal) type signature".into()))?, + TypeSignature::new_option(TypeSignature::PrincipalType).map_err(|_| StaticCheckErrorKind::Expects("FATAL: failed to create (optional principal) type signature".into()))?, ), ]) - .map_err(|_| CheckErrorKind::Expects("FAIL: PrincipalConstruct failed to initialize type signature".into()))? + .map_err(|_| StaticCheckErrorKind::Expects("FAIL: PrincipalConstruct failed to initialize type signature".into()))? .into() ) - .map_err(|_| CheckErrorKind::Expects("FATAL: failed to create `(response principal { error_code: uint, principal: (optional principal) })` type signature".into()))? + .map_err(|_| StaticCheckErrorKind::Expects("FATAL: failed to create `(response principal { error_code: uint, principal: (optional principal) })` type signature".into()))? ) } @@ -721,7 +744,7 @@ fn check_secp256k1_recover( checker.type_check_expects(&args[1], context, &TypeSignature::BUFFER_65)?; Ok( TypeSignature::new_response(TypeSignature::BUFFER_33, TypeSignature::UIntType) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, ) } @@ -745,13 +768,13 @@ fn check_get_block_info( check_arguments_at_least(2, args)?; let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( - CheckErrorKind::GetBlockInfoExpectPropertyName, + StaticCheckErrorKind::GetBlockInfoExpectPropertyName, ))?; let block_info_prop = BlockInfoProperty::lookup_by_name_at_version(block_info_prop_str, &checker.clarity_version) .ok_or(StaticCheckError::new( - CheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), + StaticCheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), ))?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -760,8 +783,8 @@ fn check_get_block_info( } // # Errors -// - `CheckErrorKind::GetBurnBlockInfoExpectPropertyName` when `args[0]` is not a valid `ClarityName`. -// - `CheckErrorKind::NoSuchBlockInfoProperty` when `args[0]` does not name a `BurnBlockInfoProperty`. +// - `StaticCheckErrorKind::GetBurnBlockInfoExpectPropertyName` when `args[0]` is not a valid `ClarityName`. +// - `StaticCheckErrorKind::NoSuchBlockInfoProperty` when `args[0]` does not name a `BurnBlockInfoProperty`. fn check_get_burn_block_info( checker: &mut TypeChecker, args: &[SymbolicExpression], @@ -770,19 +793,19 @@ fn check_get_burn_block_info( check_argument_count(2, args)?; let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( - CheckErrorKind::GetBurnBlockInfoExpectPropertyName, + StaticCheckErrorKind::GetBurnBlockInfoExpectPropertyName, ))?; let block_info_prop = BurnBlockInfoProperty::lookup_by_name(block_info_prop_str).ok_or(StaticCheckError::new( - CheckErrorKind::NoSuchBlockInfoProperty(block_info_prop_str.to_string()), + StaticCheckErrorKind::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(|_| { - CheckErrorKind::Expects("FAILED to type valid burn info property".into()) + StaticCheckErrorKind::Expects("FAILED to type valid burn info property".into()) })?, )?) } @@ -795,11 +818,11 @@ fn check_get_stacks_block_info( check_argument_count(2, args)?; let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( - CheckErrorKind::GetStacksBlockInfoExpectPropertyName, + StaticCheckErrorKind::GetStacksBlockInfoExpectPropertyName, ))?; let block_info_prop = StacksBlockInfoProperty::lookup_by_name(block_info_prop_str).ok_or( - StaticCheckError::new(CheckErrorKind::NoSuchStacksBlockInfoProperty( + StaticCheckError::new(StaticCheckErrorKind::NoSuchStacksBlockInfoProperty( block_info_prop_str.to_string(), )), )?; @@ -817,12 +840,12 @@ fn check_get_tenure_info( check_argument_count(2, args)?; let block_info_prop_str = args[0].match_atom().ok_or(StaticCheckError::new( - CheckErrorKind::GetTenureInfoExpectPropertyName, + StaticCheckErrorKind::GetTenureInfoExpectPropertyName, ))?; let block_info_prop = TenureInfoProperty::lookup_by_name(block_info_prop_str).ok_or(StaticCheckError::new( - CheckErrorKind::NoSuchTenureInfoProperty(block_info_prop_str.to_string()), + StaticCheckErrorKind::NoSuchTenureInfoProperty(block_info_prop_str.to_string()), ))?; checker.type_check_expects(&args[1], context, &TypeSignature::UIntType)?; @@ -852,7 +875,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 { @@ -881,7 +904,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::IntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -892,7 +915,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -903,7 +926,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -914,11 +937,12 @@ impl TypedNativeFunction { Simple(SimpleNativeFunction(FunctionType::Fixed(FixedFunction { args: vec![FunctionArg::new( TypeSignature::SequenceType(SequenceSubtype::BufferType( - BufferLength::try_from(16_u32) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + BufferLength::try_from(16_u32).map_err(|_| { + StaticCheckErrorKind::Expects("Bad constructor".into()) + })?, )), ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -930,11 +954,12 @@ impl TypedNativeFunction { Simple(SimpleNativeFunction(FunctionType::Fixed(FixedFunction { args: vec![FunctionArg::new( TypeSignature::SequenceType(SequenceSubtype::BufferType( - BufferLength::try_from(16_u32) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + BufferLength::try_from(16_u32).map_err(|_| { + StaticCheckErrorKind::Expects("Bad constructor".into()) + })?, )), ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -970,7 +995,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::BoolType, ClarityName::try_from("value".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1023,7 +1048,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("owner".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1035,7 +1060,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("principal".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1043,7 +1068,8 @@ 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(), TypeSignature::BUFFER_1), ("hash-bytes".into(), TypeSignature::BUFFER_20), @@ -1052,11 +1078,13 @@ impl TypedNativeFunction { TypeSignature::new_option( TypeSignature::CONTRACT_NAME_STRING_ASCII_MAX, ) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| { + StaticCheckErrorKind::Expects("Bad constructor".into()) + })?, ), ]) .map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: PrincipalDestruct failed to initialize type signature" .into(), ) @@ -1072,7 +1100,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("owner".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1083,7 +1111,7 @@ impl TypedNativeFunction { ("unlock-height".into(), TypeSignature::UIntType), ]) .map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: StxGetAccount failed to initialize type signature".into(), ) })? @@ -1094,7 +1122,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::UIntType, ClarityName::try_from("amount".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1102,7 +1130,7 @@ impl TypedNativeFunction { FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("sender".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1112,7 +1140,7 @@ impl TypedNativeFunction { TypeSignature::BoolType, TypeSignature::UIntType, ) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, }))), StxTransfer => Special(SpecialNativeFunction(&assets::check_special_stx_transfer)), StxTransferMemo => Special(SpecialNativeFunction( @@ -1195,7 +1223,7 @@ impl TypedNativeFunction { args: vec![FunctionArg::new( TypeSignature::PrincipalType, ClarityName::try_from("contract".to_owned()).map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::Expects( "FAIL: ClarityName failed to accept default arg name".into(), ) })?, @@ -1204,7 +1232,7 @@ impl TypedNativeFunction { TypeSignature::BUFFER_32, TypeSignature::UIntType, ) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, }))), ToAscii => Simple(SimpleNativeFunction(FunctionType::UnionArgs( vec![ @@ -1220,7 +1248,7 @@ impl TypedNativeFunction { TypeSignature::UIntType, ) .map_err(|_| { - CheckErrorKind::Expects( + StaticCheckErrorKind::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 b4f01b196c7..57406396d71 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,8 +19,8 @@ use clarity_types::types::TypeSignature; use stacks_common::types::StacksEpochId; use super::{ - check_argument_count, check_arguments_at_least, no_type, CheckErrorKind, StaticCheckError, - TypeChecker, + check_argument_count, check_arguments_at_least, no_type, StaticCheckError, + StaticCheckErrorKind, TypeChecker, }; use crate::vm::analysis::type_checker::contexts::TypingContext; use crate::vm::costs::cost_functions::ClarityCostFunction; @@ -83,7 +83,7 @@ pub fn check_special_is_response( if let TypeSignature::ResponseType(_types) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrorKind::ExpectedResponseType(Box::new(input.clone())).into()) + Err(StaticCheckErrorKind::ExpectedResponseType(Box::new(input.clone())).into()) } } @@ -101,7 +101,7 @@ pub fn check_special_is_optional( if let TypeSignature::OptionalType(_type) = input { Ok(TypeSignature::BoolType) } else { - Err(CheckErrorKind::ExpectedOptionalType(Box::new(input.clone())).into()) + Err(StaticCheckErrorKind::ExpectedOptionalType(Box::new(input.clone())).into()) } } @@ -121,12 +121,15 @@ pub fn check_special_default_to( let contained_type = *input_type; TypeSignature::least_supertype(&StacksEpochId::Epoch21, &default, &contained_type).map_err( |_| { - CheckErrorKind::DefaultTypesMustMatch(Box::new(default), Box::new(contained_type)) - .into() + StaticCheckErrorKind::DefaultTypesMustMatch( + Box::new(default), + Box::new(contained_type), + ) + .into() }, ) } else { - Err(CheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) + Err(StaticCheckErrorKind::ExpectedOptionalType(Box::new(input)).into()) } } @@ -154,7 +157,7 @@ fn inner_unwrap( match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(*input_type) } @@ -162,12 +165,12 @@ fn inner_unwrap( TypeSignature::ResponseType(response_type) => { let ok_type = response_type.0; if ok_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { Ok(ok_type) } } - _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(StaticCheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } @@ -180,12 +183,12 @@ fn inner_unwrap_err( if let TypeSignature::ResponseType(response_type) = input { let err_type = response_type.1; if err_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { Ok(err_type) } } else { - Err(CheckErrorKind::ExpectedResponseType(Box::new(input)).into()) + Err(StaticCheckErrorKind::ExpectedResponseType(Box::new(input)).into()) } } @@ -233,7 +236,7 @@ pub fn check_special_try_ret( match input { TypeSignature::OptionalType(input_type) => { if input_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else { checker.track_return_type(TypeSignature::new_option(TypeSignature::NoType)?)?; Ok(*input_type) @@ -242,9 +245,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(CheckErrorKind::CouldNotDetermineResponseOkType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseOkType.into()) } else if err_type.is_no_type() { - Err(CheckErrorKind::CouldNotDetermineResponseErrType.into()) + Err(StaticCheckErrorKind::CouldNotDetermineResponseErrType.into()) } else { checker.track_return_type(TypeSignature::new_response( TypeSignature::NoType, @@ -253,7 +256,7 @@ pub fn check_special_try_ret( Ok(ok_type) } } - _ => Err(CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), + _ => Err(StaticCheckErrorKind::ExpectedOptionalOrResponseType(Box::new(input)).into()), } } @@ -306,7 +309,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(CheckErrorKind::NameAlreadyUsed(bind_name.into()).into()); + return Err(StaticCheckErrorKind::NameAlreadyUsed(bind_name.into()).into()); } inner_context.add_variable_type(bind_name, bind_type, checker.clarity_version); @@ -325,22 +328,22 @@ fn check_special_match_opt( context: &TypingContext, ) -> Result { if args.len() != 3 { - Err(CheckErrorKind::BadMatchOptionSyntax(Box::new( - CheckErrorKind::IncorrectArgumentCount(4, args.len() + 1), + Err(StaticCheckErrorKind::BadMatchOptionSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(4, args.len() + 1), )))?; } let bind_name = args[0] .match_atom() .ok_or_else(|| { - CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)) + StaticCheckErrorKind::BadMatchOptionSyntax(Box::new(StaticCheckErrorKind::ExpectedName)) })? .clone(); let some_branch = &args[1]; let none_branch = &args[2]; if option_type.is_no_type() { - return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); + return Err(StaticCheckErrorKind::CouldNotDetermineMatchTypes.into()); } let some_branch_type = @@ -355,8 +358,11 @@ fn check_special_match_opt( &none_branch_type, ) .map_err(|_| { - CheckErrorKind::MatchArmsMustMatch(Box::new(some_branch_type), Box::new(none_branch_type)) - .into() + StaticCheckErrorKind::MatchArmsMustMatch( + Box::new(some_branch_type), + Box::new(none_branch_type), + ) + .into() }) } @@ -367,22 +373,26 @@ fn check_special_match_resp( context: &TypingContext, ) -> Result { if args.len() != 4 { - Err(CheckErrorKind::BadMatchResponseSyntax(Box::new( - CheckErrorKind::IncorrectArgumentCount(5, args.len() + 1), + Err(StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(5, args.len() + 1), )))?; } let ok_bind_name = args[0] .match_atom() .ok_or_else(|| { - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )) })? .clone(); let ok_branch = &args[1]; let err_bind_name = args[2] .match_atom() .ok_or_else(|| { - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)) + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )) })? .clone(); let err_branch = &args[3]; @@ -390,7 +400,7 @@ fn check_special_match_resp( let (ok_type, err_type) = resp_type; if ok_type.is_no_type() || err_type.is_no_type() { - return Err(CheckErrorKind::CouldNotDetermineMatchTypes.into()); + return Err(StaticCheckErrorKind::CouldNotDetermineMatchTypes.into()); } let ok_branch_type = eval_with_new_binding(ok_branch, ok_bind_name, ok_type, checker, context)?; @@ -401,8 +411,11 @@ fn check_special_match_resp( TypeSignature::least_supertype(&StacksEpochId::Epoch21, &ok_branch_type, &err_branch_type) .map_err(|_| { - CheckErrorKind::MatchArmsMustMatch(Box::new(ok_branch_type), Box::new(err_branch_type)) - .into() + StaticCheckErrorKind::MatchArmsMustMatch( + Box::new(ok_branch_type), + Box::new(err_branch_type), + ) + .into() }) } @@ -422,6 +435,6 @@ pub fn check_special_match( TypeSignature::ResponseType(resp_type) => { check_special_match_resp(*resp_type, checker, &args[1..], context) } - _ => Err(CheckErrorKind::BadMatchInput(Box::new(input)).into()), + _ => Err(StaticCheckErrorKind::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 c2e162dae25..ab81b4a5d22 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,8 +18,8 @@ use stacks_common::types::StacksEpochId; use super::{SimpleNativeFunction, TypedNativeFunction}; use crate::vm::analysis::type_checker::v2_1::{ - check_argument_count, check_arguments_at_least, CheckErrorKind, StaticCheckError, TypeChecker, - TypingContext, + check_argument_count, check_arguments_at_least, StaticCheckError, StaticCheckErrorKind, + TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost, CostTracker}; @@ -44,14 +44,15 @@ fn get_simple_native_or_user_define( { Ok(function_type) } else { - Err( - CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()) - .into(), + Err(StaticCheckErrorKind::IllegalOrUnknownFunctionApplication( + function_name.to_string(), ) + .into()) } } else { checker.get_function_type(function_name).ok_or( - CheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()).into(), + StaticCheckErrorKind::IllegalOrUnknownFunctionApplication(function_name.to_string()) + .into(), ) } } @@ -65,7 +66,7 @@ pub fn check_special_map( let function_name = args[0] .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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)?; @@ -107,7 +108,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(CheckErrorKind::ExpectedSequence(Box::new(argument_type)).into()); + return Err(StaticCheckErrorKind::ExpectedSequence(Box::new(argument_type)).into()); } }; @@ -137,8 +138,8 @@ pub fn check_special_map( } if let Err(mut check_error) = check_result { - if let CheckErrorKind::IncorrectArgumentCount(expected, _actual) = *check_error.err { - check_error.err = Box::new(CheckErrorKind::IncorrectArgumentCount( + if let StaticCheckErrorKind::IncorrectArgumentCount(expected, _actual) = *check_error.err { + check_error.err = Box::new(StaticCheckErrorKind::IncorrectArgumentCount( expected, args.len().saturating_sub(1), )); @@ -159,7 +160,7 @@ pub fn check_special_map( context.clarity_version, )?; TypeSignature::list_of(mapped_type, min_args) - .map_err(|_| CheckErrorKind::ConstructedListTooLarge.into()) + .map_err(|_| StaticCheckErrorKind::ConstructedListTooLarge.into()) } pub fn check_special_filter( @@ -171,7 +172,7 @@ pub fn check_special_filter( let function_name = args[0] .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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)?; @@ -182,7 +183,7 @@ pub fn check_special_filter( { let input_type = match argument_type { TypeSignature::SequenceType(ref sequence_type) => Ok(sequence_type.unit_type()), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new( + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new( argument_type.clone(), ))), }?; @@ -195,7 +196,7 @@ pub fn check_special_filter( )?; if TypeSignature::BoolType != filter_type { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BoolType), Box::new(filter_type), ) @@ -215,7 +216,7 @@ pub fn check_special_fold( let function_name = args[0] .match_atom() - .ok_or(CheckErrorKind::NonFunctionApplication)?; + .ok_or(StaticCheckErrorKind::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)?; @@ -225,7 +226,9 @@ pub fn check_special_fold( let input_type = match argument_type { TypeSignature::SequenceType(sequence_type) => Ok(sequence_type.unit_type()), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(argument_type))), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new( + argument_type, + ))), }?; let initial_value_type = checker.type_check(&args[2], context)?; @@ -283,29 +286,29 @@ pub fn check_special_concat( )?; let new_len = lhs_max_len .checked_add(rhs_max_len) - .ok_or(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::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(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::MaxLengthOverflow)?; TypeSignature::SequenceType(StringType(UTF8(size.try_into()?))) } (_, _) => { - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(lhs_type.clone()), Box::new(rhs_type.clone()), ) @@ -313,7 +316,7 @@ pub fn check_special_concat( } } } - _ => return Err(CheckErrorKind::ExpectedSequence(Box::new(lhs_type.clone())).into()), + _ => return Err(StaticCheckErrorKind::ExpectedSequence(Box::new(lhs_type.clone())).into()), }; Ok(res) } @@ -342,11 +345,11 @@ pub fn check_special_append( )?; let new_len = lhs_max_len .checked_add(1) - .ok_or(CheckErrorKind::MaxLengthOverflow)?; + .ok_or(StaticCheckErrorKind::MaxLengthOverflow)?; let return_type = TypeSignature::list_of(list_entry_type, new_len)?; Ok(return_type) } - _ => Err(CheckErrorKind::ExpectedListApplication.into()), + _ => Err(StaticCheckErrorKind::ExpectedListApplication.into()), } } @@ -361,7 +364,7 @@ pub fn check_special_as_max_len( SymbolicExpressionType::LiteralValue(Value::UInt(expected_len)) => expected_len, _ => { let expected_len_type = checker.type_check(&args[1], context)?; - return Err(CheckErrorKind::TypeError( + return Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(expected_len_type), ) @@ -378,7 +381,7 @@ pub fn check_special_as_max_len( .set_type(&args[1], TypeSignature::UIntType)?; let expected_len = - u32::try_from(expected_len).map_err(|_e| CheckErrorKind::MaxLengthOverflow)?; + u32::try_from(expected_len).map_err(|_e| StaticCheckErrorKind::MaxLengthOverflow)?; let sequence = checker.type_check(&args[0], context)?; runtime_cost(ClarityCostFunction::AnalysisIterableFunc, checker, 0)?; @@ -404,7 +407,7 @@ pub fn check_special_as_max_len( StringUTF8Length::try_from(expected_len)?, )))), )), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(sequence)).into()), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new(sequence)).into()), } } @@ -420,7 +423,9 @@ pub fn check_special_len( match collection_type { TypeSignature::SequenceType(_) => Ok(()), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type))), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new( + collection_type, + ))), }?; Ok(TypeSignature::UIntType) @@ -449,16 +454,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(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, )))), )), TypeSignature::SequenceType(StringType(UTF8(_))) => Ok(TypeSignature::OptionalType( Box::new(TypeSignature::SequenceType(StringType(UTF8( StringUTF8Length::try_from(1u32) - .map_err(|_| CheckErrorKind::Expects("Bad constructor".into()))?, + .map_err(|_| StaticCheckErrorKind::Expects("Bad constructor".into()))?, )))), )), - _ => Err(CheckErrorKind::ExpectedSequence(Box::new(collection_type)).into()), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new(collection_type)).into()), } } @@ -474,7 +479,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(CheckErrorKind::ExpectedSequence(Box::new(list_type))), + _ => Err(StaticCheckErrorKind::ExpectedSequence(Box::new(list_type))), }?; checker.type_check_expects(&args[1], context, &expected_input_type)?; @@ -497,7 +502,7 @@ pub fn check_special_slice( TypeSignature::SequenceType(seq) => { TypeSignature::new_option(TypeSignature::SequenceType(seq))? } - _ => return Err(CheckErrorKind::ExpectedSequence(Box::new(seq_type)).into()), + _ => return Err(StaticCheckErrorKind::ExpectedSequence(Box::new(seq_type)).into()), }; // Check left position argument @@ -521,7 +526,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(CheckErrorKind::ExpectedSequence(Box::new(input_type)).into()), + _ => return Err(StaticCheckErrorKind::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 cd2c5620c04..e8a4eeadaac 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::CheckErrorKind; +use crate::vm::analysis::errors::StaticCheckErrorKind; 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 = [ - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::BadTokenName, - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::NoSuchNFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::NoSuchNFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::NoSuchNFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::NoSuchNFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(string_ascii_type(15)), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::NoSuchNFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::NoSuchNFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(string_ascii_type(10)), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::BadTokenName, - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::BadTokenName, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::BoolType), ), - CheckErrorKind::DefineNFTBadSignature, - CheckErrorKind::TypeError( + StaticCheckErrorKind::DefineNFTBadSignature, + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::NoSuchFT("stackoos".to_string()), - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::NoSuchFT("stackoos".to_string()), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::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 18d3ae19d52..1afb27a6a42 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,10 @@ use serde_json; use stacks_common::types::StacksEpochId; use crate::vm::analysis::contract_interface_builder::build_contract_interface; -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, ContractAnalysis, - StaticCheckError, + StaticCheckError, StaticCheckErrorKind, }; use crate::vm::ast::parse; use crate::vm::costs::LimitedCostTracker; @@ -494,7 +493,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, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*err.err, StaticCheckErrorKind::TypeError(_, _))); } #[test] @@ -535,12 +534,12 @@ fn test_bad_map_usage() { for contract in tests.iter() { let err = mem_type_check(contract).unwrap_err(); - assert!(matches!(*err.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*err.err, StaticCheckErrorKind::TypeError(_, _))); } assert!(matches!( *mem_type_check(unhandled_option).unwrap_err().err, - CheckErrorKind::UnionTypeError(_, _) + StaticCheckErrorKind::UnionTypeError(_, _) )); } @@ -629,7 +628,7 @@ fn test_expects() { eprintln!("unmatched_return_types returned check error: {err}"); assert!(matches!( *err.err, - CheckErrorKind::ReturnTypesMustMatch(_, _) + StaticCheckErrorKind::ReturnTypesMustMatch(_, _) )); } @@ -637,21 +636,21 @@ fn test_expects() { eprintln!("bad_default_types returned check error: {err}"); assert!(matches!( *err.err, - CheckErrorKind::DefaultTypesMustMatch(_, _) + StaticCheckErrorKind::DefaultTypesMustMatch(_, _) )); let err = mem_type_check(notype_response_type).unwrap_err(); eprintln!("notype_response_type returned check error: {err}"); assert!(matches!( *err.err, - CheckErrorKind::CouldNotDetermineResponseErrType + StaticCheckErrorKind::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, - CheckErrorKind::CouldNotDetermineResponseOkType + StaticCheckErrorKind::CouldNotDetermineResponseOkType )); } @@ -687,7 +686,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 { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -714,7 +713,7 @@ fn test_bad_principal_to_trait() { let err = mem_type_check(bad_principal_to_trait).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::PrincipalType, @@ -727,7 +726,7 @@ fn test_bad_principal_to_trait() { }; let err = mem_type_check_v1(bad_principal_to_trait).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::PrincipalType, @@ -756,7 +755,7 @@ fn test_bad_other_trait() { let err = mem_type_check(bad_other_trait).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, actual) => { + StaticCheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -764,7 +763,7 @@ fn test_bad_other_trait() { }; let err = mem_type_check_v1(bad_other_trait).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, actual) => match (&*expected, &*actual) { + StaticCheckErrorKind::TypeError(expected, actual) => match (&*expected, &*actual) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -797,7 +796,7 @@ fn test_embedded_trait() { mem_type_check(embedded_trait).unwrap(); let err = mem_type_check_v1(embedded_trait).unwrap_err(); match *err.err { - CheckErrorKind::TraitReferenceUnknown(name) => { + StaticCheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "contract"); } _ => panic!("Unexpected error: {err:?}"), @@ -827,7 +826,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 { - CheckErrorKind::TraitReferenceUnknown(name) => { + StaticCheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "contract"); } _ => panic!("Unexpected error: {err:?}"), @@ -860,7 +859,7 @@ fn test_bad_embedded_trait() { let err = mem_type_check(bad_embedded_trait).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, actual) => { + StaticCheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-12"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -868,7 +867,7 @@ fn test_bad_embedded_trait() { }; let err = mem_type_check_v1(bad_embedded_trait).unwrap_err(); match *err.err { - CheckErrorKind::TraitReferenceUnknown(name) => { + StaticCheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "contract"); } _ => panic!("Unexpected error: {err:?}"), @@ -890,7 +889,7 @@ fn test_let_trait() { mem_type_check(let_trait).unwrap(); let err = mem_type_check_v1(let_trait).unwrap_err(); match *err.err { - CheckErrorKind::TraitReferenceUnknown(name) => { + StaticCheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "t1"); } _ => panic!("Unexpected error: {err:?}"), @@ -916,7 +915,7 @@ fn test_let3_trait() { mem_type_check(let3_trait).unwrap(); let err = mem_type_check_v1(let3_trait).unwrap_err(); match *err.err { - CheckErrorKind::TraitReferenceUnknown(name) => { + StaticCheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "t3"); } _ => panic!("Unexpected error: {err:?}"), @@ -971,7 +970,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 { - CheckErrorKind::TraitReferenceUnknown(name) => { + StaticCheckErrorKind::TraitReferenceUnknown(name) => { assert_eq!(name.as_str(), "t4"); } _ => panic!("Unexpected error: {err:?}"), @@ -995,7 +994,7 @@ fn test_trait_args_differ() { let err = mem_type_check(trait_args_differ).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, actual) => { + StaticCheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -1003,7 +1002,7 @@ fn test_trait_args_differ() { }; let err = mem_type_check_v1(trait_args_differ).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1033,7 +1032,7 @@ fn test_trait_arg_counts_differ1() { let err = mem_type_check(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, found) => { + StaticCheckErrorKind::IncompatibleTrait(expected, found) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(found.name.as_str(), "trait-1"); } @@ -1041,7 +1040,7 @@ fn test_trait_arg_counts_differ1() { }; let err = mem_type_check_v1(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1071,7 +1070,7 @@ fn test_trait_arg_counts_differ2() { let err = mem_type_check(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, found) => { + StaticCheckErrorKind::IncompatibleTrait(expected, found) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(found.name.as_str(), "trait-1"); } @@ -1079,7 +1078,7 @@ fn test_trait_arg_counts_differ2() { }; let err = mem_type_check_v1(trait_to_compatible_trait).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1109,7 +1108,7 @@ fn test_trait_ret_ty_differ() { let err = mem_type_check(trait_ret_ty_differ).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, actual) => { + StaticCheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -1117,7 +1116,7 @@ fn test_trait_ret_ty_differ() { }; let err = mem_type_check_v1(trait_ret_ty_differ).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1155,7 +1154,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 { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1192,7 +1191,7 @@ fn test_trait_with_bad_trait_arg() { let err = mem_type_check(trait_with_bad_trait_arg).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, actual) => { + StaticCheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-b"); assert_eq!(actual.name.as_str(), "trait-a"); } @@ -1200,7 +1199,7 @@ fn test_trait_with_bad_trait_arg() { }; let err = mem_type_check_v1(trait_with_bad_trait_arg).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1238,7 +1237,7 @@ fn test_trait_with_superset_trait_arg() { let err = mem_type_check(trait_with_superset_trait_arg).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, actual) => { + StaticCheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-b"); assert_eq!(actual.name.as_str(), "trait-a"); } @@ -1248,7 +1247,7 @@ fn test_trait_with_superset_trait_arg() { let err = mem_type_check_v1(trait_with_superset_trait_arg).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1287,7 +1286,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 { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1311,7 +1310,7 @@ fn test_trait_with_duplicate_method() { let err = mem_type_check(trait_with_duplicate_method).unwrap_err(); match *err.err { - CheckErrorKind::DefineTraitDuplicateMethod(method_name) => { + StaticCheckErrorKind::DefineTraitDuplicateMethod(method_name) => { assert_eq!(method_name.as_str(), "foo"); } _ => panic!("Unexpected error: {err:?}"), @@ -1340,7 +1339,7 @@ fn test_trait_to_subtrait_and_back() { let err = mem_type_check(trait_to_subtrait_and_back).unwrap_err(); match *err.err { - CheckErrorKind::IncompatibleTrait(expected, actual) => { + StaticCheckErrorKind::IncompatibleTrait(expected, actual) => { assert_eq!(expected.name.as_str(), "trait-2"); assert_eq!(actual.name.as_str(), "trait-1"); } @@ -1348,7 +1347,7 @@ fn test_trait_to_subtrait_and_back() { }; let err = mem_type_check_v1(trait_to_subtrait_and_back).unwrap_err(); match *err.err { - CheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { + StaticCheckErrorKind::TypeError(expected, found) => match (&*expected, &*found) { ( TypeSignature::CallableType(CallableSubtype::Trait(expected_trait)), TypeSignature::CallableType(CallableSubtype::Trait(found_trait)), @@ -1395,7 +1394,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 { - CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + StaticCheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1409,7 +1408,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 { - CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + StaticCheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1441,7 +1440,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 { - CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + StaticCheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1455,7 +1454,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 { - CheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { + StaticCheckErrorKind::IfArmsMustMatch(type1, type2) => match (&*type1, &*type2) { ( TypeSignature::CallableType(CallableSubtype::Trait(trait1)), TypeSignature::CallableType(CallableSubtype::Trait(trait2)), @@ -1514,7 +1513,7 @@ fn test_traits_multi_contract(#[case] version: ClarityVersion) { match result { Ok(_) if version >= ClarityVersion::Clarity2 => (), Err(StaticCheckError { err, .. }) if version < ClarityVersion::Clarity2 => match *err { - CheckErrorKind::TraitMethodUnknown(trait_name, function) => { + StaticCheckErrorKind::TraitMethodUnknown(trait_name, function) => { assert_eq!(trait_name.as_str(), "a"); assert_eq!(function.as_str(), "do-it"); } @@ -3394,7 +3393,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? 123)", "int type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::IntType), )), @@ -3402,7 +3401,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? u123)", "uint type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::UIntType), )), @@ -3410,7 +3409,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? true)", "bool type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::BoolType), )), @@ -3418,7 +3417,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? 0x1234)", "buffer type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(2u32).unwrap(), @@ -3428,7 +3427,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(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(BufferLength::try_from(43u32).unwrap()), @@ -3438,7 +3437,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(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::UTF8(StringUTF8Length::try_from(40u32).unwrap()), @@ -3448,7 +3447,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? (list 1 2 3))", "list type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::SequenceType(SequenceSubtype::ListType( ListTypeData::new_list(TypeSignature::IntType, 3).unwrap(), @@ -3458,7 +3457,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? { a: 1, b: u2 })", "tuple type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::TupleType( vec![ @@ -3473,7 +3472,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? (some u789))", "optional type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::new_option(TypeSignature::UIntType).unwrap()), )), @@ -3481,7 +3480,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc ( "(contract-hash? (ok true))", "response type", - Err(CheckErrorKind::TypeError( + Err(StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new( TypeSignature::new_response(TypeSignature::BoolType, TypeSignature::NoType) @@ -3498,7 +3497,7 @@ fn test_contract_hash(#[case] version: ClarityVersion, #[case] epoch: StacksEpoc let expected = if version >= ClarityVersion::Clarity4 { clarity4_expected } else { - &Err(CheckErrorKind::UnknownFunction( + &Err(StaticCheckErrorKind::UnknownFunction( "contract-hash?".to_string(), )) }; @@ -3564,7 +3563,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( &format!("(to-ascii? 0x{})", "ff".repeat(524285)), "oversized buffer type", - Err(CheckErrorKind::UnionTypeError( + Err(StaticCheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::SequenceType(SequenceSubtype::BufferType( BufferLength::try_from(524285u32).unwrap(), @@ -3579,7 +3578,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(CheckErrorKind::UnionTypeError( + Err(StaticCheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::SequenceType(SequenceSubtype::StringType( StringSubtype::ASCII(BufferLength::try_from(43u32).unwrap()), @@ -3589,7 +3588,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? (list 1 2 3))", "list type", - Err(CheckErrorKind::UnionTypeError( + Err(StaticCheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::SequenceType(SequenceSubtype::ListType( ListTypeData::new_list(TypeSignature::IntType, 3).unwrap(), @@ -3599,7 +3598,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? { a: 1, b: u2 })", "tuple type", - Err(CheckErrorKind::UnionTypeError( + Err(StaticCheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::TupleType( vec![ @@ -3614,7 +3613,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? (some u789))", "optional type", - Err(CheckErrorKind::UnionTypeError( + Err(StaticCheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new(TypeSignature::new_option(TypeSignature::UIntType).unwrap()), )), @@ -3622,7 +3621,7 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ( "(to-ascii? (ok true))", "response type", - Err(CheckErrorKind::UnionTypeError( + Err(StaticCheckErrorKind::UnionTypeError( to_ascii_expected_types.clone(), Box::new( TypeSignature::new_response(TypeSignature::BoolType, TypeSignature::NoType) @@ -3639,7 +3638,9 @@ fn test_to_ascii(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) let expected = if version >= ClarityVersion::Clarity4 { clarity4_expected } else { - &Err(CheckErrorKind::UnknownFunction("to-ascii?".to_string())) + &Err(StaticCheckErrorKind::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 fb5004ca2c2..4b5cabeccac 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 @@ -21,7 +21,7 @@ use rstest::rstest; use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::errors::{CheckErrorKind, StaticCheckError, SyntaxBindingError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind, SyntaxBindingError}; use crate::vm::analysis::mem_type_check as mem_run_analysis; use crate::vm::analysis::types::ContractAnalysis; use crate::vm::ast::build_ast; @@ -90,26 +90,26 @@ fn test_from_consensus_buff() { let bad = [ ( "(from-consensus-buff?)", - CheckErrorKind::IncorrectArgumentCount(2, 0), + StaticCheckErrorKind::IncorrectArgumentCount(2, 0), ), ( "(from-consensus-buff? 0x00 0x00 0x00)", - CheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), ), ( "(from-consensus-buff? 0x00 0x00)", - CheckErrorKind::InvalidTypeDescription, + StaticCheckErrorKind::InvalidTypeDescription, ), ( "(from-consensus-buff? int u6)", - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_MAX), Box::new(TypeSignature::UIntType), ), ), ( "(from-consensus-buff? (buff 1048576) 0x00)", - CheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, ), ]; @@ -186,26 +186,26 @@ fn test_to_consensus_buff() { let bad = [ ( "(to-consensus-buff?)", - CheckErrorKind::IncorrectArgumentCount(1, 0), + StaticCheckErrorKind::IncorrectArgumentCount(1, 0), ), ( "(to-consensus-buff? 0x00 0x00)", - CheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), ), ( "(define-private (my-func (x (buff 1048576))) (to-consensus-buff? x))", - CheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, ), ( "(define-private (my-func (x (buff 1048570))) (to-consensus-buff? x))", - CheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, ), ( "(define-private (my-func (x (buff 1048567))) (to-consensus-buff? x))", - CheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, ), ]; @@ -264,10 +264,10 @@ fn test_get_block_info() { "(get-block-info? time)", ]; let bad_expected = [ - 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), + StaticCheckErrorKind::NoSuchBlockInfoProperty("none".to_string()), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::RequiresAtLeastArguments(2, 1), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -299,7 +299,7 @@ fn test_get_block_info() { } for good_test in good_v210.iter() { - if let CheckErrorKind::NoSuchBlockInfoProperty(_) = + if let StaticCheckErrorKind::NoSuchBlockInfoProperty(_) = *type_check_helper_v1(good_test).unwrap_err().err { } else { @@ -320,10 +320,10 @@ fn test_get_burn_block_info() { r#"(get-burn-block-info? header-hash "a")"#, ]; let bad_expected = [ - CheckErrorKind::NoSuchBlockInfoProperty("none".to_string()), - CheckErrorKind::IncorrectArgumentCount(2, 0), - CheckErrorKind::IncorrectArgumentCount(2, 1), - CheckErrorKind::TypeError( + StaticCheckErrorKind::NoSuchBlockInfoProperty("none".to_string()), + StaticCheckErrorKind::IncorrectArgumentCount(2, 0), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError( Box::new(UIntType), Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(1u32).expect("BufferLength::try_from failed"), @@ -364,10 +364,10 @@ fn test_define_trait(#[case] version: ClarityVersion, #[case] epoch: StacksEpoch "(define-trait)", ]; let bad_expected = [ - CheckErrorKind::InvalidTypeDescription, - CheckErrorKind::DefineTraitBadSignature, - CheckErrorKind::DefineTraitBadSignature, - CheckErrorKind::InvalidTypeDescription, + StaticCheckErrorKind::InvalidTypeDescription, + StaticCheckErrorKind::DefineTraitBadSignature, + StaticCheckErrorKind::DefineTraitBadSignature, + StaticCheckErrorKind::InvalidTypeDescription, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -462,42 +462,42 @@ fn test_stx_ops() { "(stx-get-balance 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)" ]; let bad_expected = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), ), - 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( + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(3, 5), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(OptionalType(Box::from(PrincipalType))), ), - CheckErrorKind::IncorrectArgumentCount(3, 4), - CheckErrorKind::TypeError( + StaticCheckErrorKind::IncorrectArgumentCount(3, 4), + StaticCheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), ), - 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( + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(4, 5), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(OptionalType(Box::from(PrincipalType))), ), - 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), + StaticCheckErrorKind::IncorrectArgumentCount(4, 3), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::TypeError(Box::new(PrincipalType), Box::new(BoolType)), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -526,7 +526,7 @@ fn test_tx_sponsor() { ]; let bad = ["(stx-transfer? u10 tx-sponsor? 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G)"]; - let bad_expected = [CheckErrorKind::TypeError( + let bad_expected = [StaticCheckErrorKind::TypeError( Box::new(PrincipalType), Box::new(OptionalType(Box::from(PrincipalType))), )]; @@ -594,7 +594,7 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack let bad = [ ( "(unwrap-err! (some 2) 2)", - CheckErrorKind::ExpectedResponseType(Box::new(TypeSignature::from_string( + StaticCheckErrorKind::ExpectedResponseType(Box::new(TypeSignature::from_string( "(optional int)", version, epoch, @@ -602,92 +602,101 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack ), ( "(unwrap! (err 3) 2)", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-err-panic (ok 3))", - CheckErrorKind::CouldNotDetermineResponseErrType, + StaticCheckErrorKind::CouldNotDetermineResponseErrType, ), ( "(unwrap-panic none)", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(define-private (foo) (if (> 1 0) none none)) (unwrap-panic (foo))", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(unwrap-panic (err 3))", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(match none inner-value (/ 1 0) (+ 1 8))", - CheckErrorKind::CouldNotDetermineMatchTypes, + StaticCheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (ok 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrorKind::CouldNotDetermineMatchTypes, + StaticCheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(match (err 1) ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrorKind::CouldNotDetermineMatchTypes, + StaticCheckErrorKind::CouldNotDetermineMatchTypes, ), ( "(define-private (foo) (if (> 1 0) (ok 1) (err u8))) (match (foo) ok-val (+ 1 ok-val) err-val (/ err-val u0))", - CheckErrorKind::MatchArmsMustMatch( + StaticCheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value) (> 1 28))", - CheckErrorKind::MatchArmsMustMatch( + StaticCheckErrorKind::MatchArmsMustMatch( Box::new(TypeSignature::IntType), Box::new(TypeSignature::BoolType), ), ), ( "(match (some 1) inner-value (+ 1 inner-value))", - CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::IncorrectArgumentCount( - 4, 3, - ))), + StaticCheckErrorKind::BadMatchOptionSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(4, 3), + )), ), ( "(match (ok 1) inner-value (+ 1 inner-value))", - CheckErrorKind::BadMatchResponseSyntax(Box::new( - CheckErrorKind::IncorrectArgumentCount(5, 3), + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::IncorrectArgumentCount(5, 3), )), ), ( "(match (ok 1) 1 (+ 1 1) err-val (+ 2 err-val))", - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )), ), ( "(match (ok 1) ok-val (+ 1 1) (+ 3 4) (+ 2 err-val))", - CheckErrorKind::BadMatchResponseSyntax(Box::new(CheckErrorKind::ExpectedName)), + StaticCheckErrorKind::BadMatchResponseSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )), ), ( "(match (some 1) 2 (+ 1 1) (+ 3 4))", - CheckErrorKind::BadMatchOptionSyntax(Box::new(CheckErrorKind::ExpectedName)), + StaticCheckErrorKind::BadMatchOptionSyntax(Box::new( + StaticCheckErrorKind::ExpectedName, + )), + ), + ( + "(match)", + StaticCheckErrorKind::RequiresAtLeastArguments(1, 0), ), - ("(match)", CheckErrorKind::RequiresAtLeastArguments(1, 0)), ( "(match 1 ok-val (/ ok-val 0) err-val (+ err-val 7))", - CheckErrorKind::BadMatchInput(Box::new(TypeSignature::from_string( + StaticCheckErrorKind::BadMatchInput(Box::new(TypeSignature::from_string( "int", version, epoch, ))), ), ( "(default-to 3 5)", - CheckErrorKind::ExpectedOptionalType(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::ExpectedOptionalType(Box::new(TypeSignature::IntType)), ), ( "(define-private (foo (x int)) (match (some 3) x (+ x 2) 5))", - CheckErrorKind::NameAlreadyUsed("x".to_string()), + StaticCheckErrorKind::NameAlreadyUsed("x".to_string()), ), ( "(define-private (t1 (x uint)) (if (> x u1) (ok x) (err false))) @@ -695,7 +704,7 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack (if (> x u4) (err u3) (ok (+ u2 (try! (t1 x))))))", - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -710,7 +719,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))))", - CheckErrorKind::ReturnTypesMustMatch( + StaticCheckErrorKind::ReturnTypesMustMatch( Box::new( TypeSignature::new_response(TypeSignature::NoType, TypeSignature::BoolType) .unwrap(), @@ -720,23 +729,23 @@ fn test_destructuring_opts(#[case] version: ClarityVersion, #[case] epoch: Stack ), ( "(try! (ok 3))", - CheckErrorKind::CouldNotDetermineResponseErrType, + StaticCheckErrorKind::CouldNotDetermineResponseErrType, ), ( "(try! none)", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(try! (err 3))", - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ), ( "(try! 3)", - CheckErrorKind::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::ExpectedOptionalOrResponseType(Box::new(TypeSignature::IntType)), ), ( "(try! (ok 3) 4)", - CheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), ), ]; @@ -759,14 +768,14 @@ fn test_at_block() { let bad = [ ( "(at-block (sha512 u0) u1)", - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_32), Box::new(TypeSignature::BUFFER_64), ), ), ( "(at-block (sha256 u0) u1 u2)", - CheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), ), ]; @@ -800,7 +809,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)", - CheckErrorKind::UnexpectedTraitOrFieldReference, + StaticCheckErrorKind::UnexpectedTraitOrFieldReference, )]; for (bad_test, expected) in bad.iter() { @@ -847,23 +856,23 @@ fn test_bitwise_bad_checks() { "(bit-or 1 2 u4)", ]; let bad_expected = [ - CheckErrorKind::IncorrectArgumentCount(2, 1), - CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(5u32).unwrap(), )))), ), - 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)), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -888,12 +897,12 @@ fn test_simple_arithmetic_checks() { "(and (or true false) (+ 1 2 3))", ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::RequiresAtLeastArguments(1, 0), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::UndefinedVariable("x".to_string()), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -954,14 +963,14 @@ fn test_simple_hash_checks() { for bad_test in bad_types.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrorKind::UnionTypeError(_, _) + StaticCheckErrorKind::UnionTypeError(_, _) )); } for bad_test in invalid_args.iter() { assert!(matches!( *type_check_helper(bad_test).unwrap_err().err, - CheckErrorKind::IncorrectArgumentCount(_, _) + StaticCheckErrorKind::IncorrectArgumentCount(_, _) )); } } @@ -984,10 +993,10 @@ fn test_simple_ifs() { ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::IfArmsMustMatch(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IfArmsMustMatch(Box::new(ascii_type(1)), Box::new(BoolType)), + StaticCheckErrorKind::IncorrectArgumentCount(3, 0), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1020,9 +1029,9 @@ fn test_simple_lets() { ]; let bad_expected = [ - CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), - CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), @@ -1095,47 +1104,47 @@ fn test_index_of() { ]; let bad_expected = [ - CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_MIN), Box::new(TypeSignature::STRING_ASCII_MIN), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::STRING_UTF8_MIN), Box::new(TypeSignature::STRING_ASCII_MIN), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::STRING_ASCII_MIN), Box::new(TypeSignature::STRING_UTF8_MIN), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 1).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::IntType, 2).unwrap()), ), - CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_MIN), Box::new(TypeSignature::STRING_ASCII_MIN), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::STRING_UTF8_MIN), Box::new(TypeSignature::STRING_ASCII_MIN), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::STRING_ASCII_MIN), Box::new(TypeSignature::STRING_UTF8_MIN), ), - CheckErrorKind::CouldNotDetermineType, - CheckErrorKind::CouldNotDetermineType, - CheckErrorKind::CouldNotDetermineType, + StaticCheckErrorKind::CouldNotDetermineType, + StaticCheckErrorKind::CouldNotDetermineType, + StaticCheckErrorKind::CouldNotDetermineType, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -1179,16 +1188,16 @@ fn test_element_at() { ]; let bad_expected = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::UIntType), Box::new(TypeSignature::IntType), ), - CheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(TypeSignature::IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1220,12 +1229,12 @@ fn test_eqs(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::list_of(IntType, 1).unwrap()), Box::new(IntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(optional bool)", version, @@ -1263,9 +1272,9 @@ fn test_asserts() { ]; let bad_expected = [ - CheckErrorKind::IncorrectArgumentCount(2, 1), - CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1329,23 +1338,23 @@ fn test_lists() { "(map + (list 1 2 3 4 5) (list true true true true true))", ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::UnknownFunction("ynot".to_string()), + StaticCheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(UIntType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1386,20 +1395,20 @@ fn test_buff() { "(len 1)", ]; let bad_expected = [ - 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)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(buff_type(20))), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::UnknownFunction("ynot".to_string()), + StaticCheckErrorKind::IllegalOrUnknownFunctionApplication("if".to_string()), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::UnionTypeError(vec![IntType, UIntType], Box::new(BoolType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(UIntType)), + StaticCheckErrorKind::ExpectedSequence(Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -1467,9 +1476,9 @@ fn test_native_as_max_len() { "(as-max-len? 0x01 u1048577)", ]; let bad_expected = [ - CheckErrorKind::ValueTooLarge, - CheckErrorKind::ValueTooLarge, - CheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, + StaticCheckErrorKind::ValueTooLarge, ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); @@ -1513,9 +1522,9 @@ fn test_native_append() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1553,9 +1562,9 @@ fn test_slice_list() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1584,9 +1593,9 @@ fn test_slice_buff() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1618,9 +1627,9 @@ fn test_slice_ascii() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1649,9 +1658,9 @@ fn test_slice_utf8() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1697,17 +1706,17 @@ fn test_replace_at_list() { ]; let bad_expected = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(IntType), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - 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( + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(3, 4), + StaticCheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError( Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), @@ -1755,20 +1764,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 = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(BufferType(buff_len.clone()))), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(BufferType(buff_len.clone()))), Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), ), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(3, 4), - CheckErrorKind::IncorrectArgumentCount(3, 2), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(3, 4), + StaticCheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError( Box::new(SequenceType(BufferType(buff_len))), Box::new(SequenceType(BufferType(buff_len_two))), ), @@ -1813,20 +1822,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 = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII(buff_len.clone())))), Box::new(SequenceType(BufferType(buff_len.clone()))), ), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(3, 4), - CheckErrorKind::IncorrectArgumentCount(3, 2), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(3, 4), + StaticCheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII(buff_len)))), Box::new(SequenceType(StringType(ASCII(buff_len_two)))), ), @@ -1871,20 +1880,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 = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8(str_len.clone())))), Box::new(SequenceType(ListType( ListTypeData::new_list(IntType, 1).unwrap(), ))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8(str_len.clone())))), Box::new(SequenceType(BufferType(buff_len))), ), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(3, 4), - CheckErrorKind::IncorrectArgumentCount(3, 2), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::IncorrectArgumentCount(3, 4), + StaticCheckErrorKind::IncorrectArgumentCount(3, 2), + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8(str_len)))), Box::new(SequenceType(StringType(UTF8(str_len_two)))), ), @@ -1913,9 +1922,9 @@ fn test_native_concat() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(UIntType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::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); @@ -1998,8 +2007,8 @@ fn test_tuples() { ]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -2023,7 +2032,7 @@ fn test_empty_tuple_should_fail() { assert_eq!( *mem_type_check(contract_src).unwrap_err().err, - CheckErrorKind::EmptyTuplesNotAllowed, + StaticCheckErrorKind::EmptyTuplesNotAllowed, ); } @@ -2103,9 +2112,9 @@ fn test_simple_uints() { let bad = ["(> u1 1)", "(to-uint true)", "(to-int false)"]; let bad_expected = [ - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), - CheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), - CheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(IntType)), + StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::TypeError(Box::new(UIntType), Box::new(BoolType)), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -2137,9 +2146,9 @@ fn test_buffer_to_ints() { ]; let bad_expected = [ - CheckErrorKind::IncorrectArgumentCount(1, 2), - CheckErrorKind::IncorrectArgumentCount(1, 0), - CheckErrorKind::TypeError( + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 0), + StaticCheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap(), ))), @@ -2147,7 +2156,7 @@ fn test_buffer_to_ints() { BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(16_u32).unwrap(), ))), @@ -2211,37 +2220,37 @@ fn test_string_to_ints() { ]; let bad_expected = [ - CheckErrorKind::IncorrectArgumentCount(1, 2), - CheckErrorKind::IncorrectArgumentCount(1, 0), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 0), + StaticCheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(BufferType( BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(1_u32).unwrap(), )))), ), - CheckErrorKind::IncorrectArgumentCount(1, 2), - CheckErrorKind::IncorrectArgumentCount(1, 0), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 0), + StaticCheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(BufferType( BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::UnionTypeError( vec![IntType, UIntType], Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(1_u32).unwrap(), )))), ), - CheckErrorKind::IncorrectArgumentCount(1, 2), - CheckErrorKind::IncorrectArgumentCount(1, 0), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 0), + StaticCheckErrorKind::UnionTypeError( vec![ TypeSignature::STRING_ASCII_MAX, TypeSignature::STRING_UTF8_MAX, @@ -2250,16 +2259,16 @@ fn test_string_to_ints() { BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::UnionTypeError( vec![ TypeSignature::STRING_ASCII_MAX, TypeSignature::STRING_UTF8_MAX, ], Box::new(IntType), ), - CheckErrorKind::IncorrectArgumentCount(1, 2), - CheckErrorKind::IncorrectArgumentCount(1, 0), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 0), + StaticCheckErrorKind::UnionTypeError( vec![ TypeSignature::STRING_ASCII_MAX, TypeSignature::STRING_UTF8_MAX, @@ -2268,7 +2277,7 @@ fn test_string_to_ints() { BufferLength::try_from(17_u32).unwrap(), ))), ), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::UnionTypeError( vec![ TypeSignature::STRING_ASCII_MAX, TypeSignature::STRING_UTF8_MAX, @@ -2323,7 +2332,7 @@ fn test_response_inference(#[case] version: ClarityVersion, #[case] epoch: Stack ]; let bad_expected = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::from_string( "(response bool int)", version, @@ -2331,8 +2340,8 @@ fn test_response_inference(#[case] version: ClarityVersion, #[case] epoch: Stack )), Box::new(BoolType), ), - CheckErrorKind::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), - CheckErrorKind::CouldNotDetermineResponseOkType, + StaticCheckErrorKind::ReturnTypesMustMatch(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::CouldNotDetermineResponseOkType, ]; for (good_test, expected) in good.iter().zip(expected.iter()) { @@ -2450,7 +2459,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 { - CheckErrorKind::TypeError(t1, t2) => { + StaticCheckErrorKind::TypeError(t1, t2) => { *t1 == TypeSignature::from_string("(optional bool)", version, epoch) && *t2 == TypeSignature::from_string("(optional int)", version, epoch) } @@ -2460,7 +2469,7 @@ fn test_options(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) { } else { assert!( match *mem_run_analysis(contract, version, epoch).unwrap_err().err { - CheckErrorKind::TypeError(t1, t2) => { + StaticCheckErrorKind::TypeError(t1, t2) => { *t1 == TypeSignature::from_string("bool", version, epoch) && *t2 == TypeSignature::from_string("int", version, epoch) } @@ -2569,7 +2578,7 @@ fn test_missing_value_on_declaration_should_fail() { let res = mem_type_check(contract_src).unwrap_err(); assert!(matches!( *res.err, - CheckErrorKind::IncorrectArgumentCount(_, _) + StaticCheckErrorKind::IncorrectArgumentCount(_, _) )); } @@ -2580,7 +2589,7 @@ fn test_mismatching_type_on_declaration_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } #[test] @@ -2596,7 +2605,7 @@ fn test_mismatching_type_on_update_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } #[test] @@ -2608,7 +2617,10 @@ fn test_direct_access_to_persisted_var_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } #[test] @@ -2623,7 +2635,7 @@ fn test_data_var_shadowed_by_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2636,7 +2648,10 @@ fn test_mutating_unknown_data_var_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::NoSuchDataVariable(_) + )); } #[test] @@ -2647,7 +2662,10 @@ fn test_accessing_unknown_data_var_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NoSuchDataVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::NoSuchDataVariable(_) + )); } #[test] @@ -2658,7 +2676,7 @@ fn test_let_shadowed_by_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2670,7 +2688,7 @@ fn test_let_shadowed_by_nested_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2683,7 +2701,7 @@ fn test_define_constant_shadowed_by_let_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2695,7 +2713,7 @@ fn test_define_constant_shadowed_by_argument_should_fail() { "#; let res = mem_type_check(contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::NameAlreadyUsed(_))); + assert!(matches!(*res.err, StaticCheckErrorKind::NameAlreadyUsed(_))); } #[test] @@ -2895,7 +2913,7 @@ fn test_fetch_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -2910,7 +2928,10 @@ fn test_fetch_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -2952,7 +2973,7 @@ fn test_insert_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -2970,7 +2991,10 @@ fn test_insert_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -3010,7 +3034,7 @@ fn test_delete_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -3025,7 +3049,10 @@ fn test_delete_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -3069,7 +3096,7 @@ fn test_set_entry_mismatching_type_signatures() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::TypeError(_, _))); + assert!(matches!(*res.err, StaticCheckErrorKind::TypeError(_, _))); } } @@ -3087,7 +3114,10 @@ fn test_set_entry_unbound_variables() { ({case}))" ); let res = mem_type_check(&contract_src).unwrap_err(); - assert!(matches!(*res.err, CheckErrorKind::UndefinedVariable(_))); + assert!(matches!( + *res.err, + StaticCheckErrorKind::UndefinedVariable(_) + )); } } @@ -3203,7 +3233,7 @@ fn test_buff_negative_len() { (func 0x00)"; let res = mem_type_check(contract_src).unwrap_err(); - assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); + assert_eq!(*res.err, StaticCheckErrorKind::ValueOutOfBounds); } #[test] @@ -3212,7 +3242,7 @@ fn test_string_ascii_negative_len() { (func \"\")"; let res = mem_type_check(contract_src).unwrap_err(); - assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); + assert_eq!(*res.err, StaticCheckErrorKind::ValueOutOfBounds); } #[test] @@ -3221,7 +3251,7 @@ fn test_string_utf8_negative_len() { (func u\"\")"; let res = mem_type_check(contract_src).unwrap_err(); - assert_eq!(*res.err, CheckErrorKind::ValueOutOfBounds); + assert_eq!(*res.err, StaticCheckErrorKind::ValueOutOfBounds); } #[test] @@ -3265,7 +3295,7 @@ fn test_comparison_types() { r#"(>= "aaa" "aaa" "aaa")"#, ]; let bad_expected = [ - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::UnionTypeError( vec![ IntType, UIntType, @@ -3279,7 +3309,7 @@ fn test_comparison_types() { ], Box::new(PrincipalType), ), - CheckErrorKind::UnionTypeError( + StaticCheckErrorKind::UnionTypeError( vec![ IntType, UIntType, @@ -3295,7 +3325,7 @@ fn test_comparison_types() { ListTypeData::new_list(IntType, 3).unwrap(), ))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(UTF8( StringUTF8Length::try_from(3u32).unwrap(), )))), @@ -3303,7 +3333,7 @@ fn test_comparison_types() { BufferLength::try_from(2_u32).unwrap(), )))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(StringType(ASCII( BufferLength::try_from(3_u32).unwrap(), )))), @@ -3311,7 +3341,7 @@ fn test_comparison_types() { BufferLength::try_from(2_u32).unwrap(), ))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), @@ -3319,7 +3349,7 @@ fn test_comparison_types() { StringUTF8Length::try_from(3u32).unwrap(), )))), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(SequenceType(BufferType( BufferLength::try_from(2_u32).unwrap(), ))), @@ -3327,9 +3357,9 @@ fn test_comparison_types() { BufferLength::try_from(3_u32).unwrap(), )))), ), - CheckErrorKind::IncorrectArgumentCount(2, 0), - CheckErrorKind::IncorrectArgumentCount(2, 1), - CheckErrorKind::IncorrectArgumentCount(2, 3), + StaticCheckErrorKind::IncorrectArgumentCount(2, 0), + StaticCheckErrorKind::IncorrectArgumentCount(2, 1), + StaticCheckErrorKind::IncorrectArgumentCount(2, 3), ]; for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { @@ -3358,9 +3388,9 @@ fn test_principal_destruct() { r#"(principal-destruct? 0x22)"#, ]; let bad_expected = [ - CheckErrorKind::IncorrectArgumentCount(1, 2), - CheckErrorKind::IncorrectArgumentCount(1, 0), - CheckErrorKind::TypeError( + StaticCheckErrorKind::IncorrectArgumentCount(1, 2), + StaticCheckErrorKind::IncorrectArgumentCount(1, 0), + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::PrincipalType), Box::new(TypeSignature::BUFFER_1), ), @@ -3414,17 +3444,17 @@ fn test_principal_construct() { // Too few arguments, just has the `(buff 1)`. ( r#"(principal-construct? 0x22)"#, - CheckErrorKind::RequiresAtLeastArguments(2, 1), + StaticCheckErrorKind::RequiresAtLeastArguments(2, 1), ), // Too few arguments, just hs the `(buff 20)`. ( r#"(principal-construct? 0xfa6bf38ed557fe417333710d6033e9419391a320)"#, - CheckErrorKind::RequiresAtLeastArguments(2, 1), + StaticCheckErrorKind::RequiresAtLeastArguments(2, 1), ), // The first buffer is too long, should be `(buff 1)`. ( r#"(principal-construct? 0xfa6bf38ed557fe417333710d6033e9419391a320 0xfa6bf38ed557fe417333710d6033e9419391a320)"#, - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_1), Box::new(TypeSignature::BUFFER_20), ), @@ -3432,7 +3462,7 @@ fn test_principal_construct() { // The second buffer is too long, should be `(buff 20)`. ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a32009)"#, - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::BUFFER_20), Box::new(TypeSignature::SequenceType(SequenceSubtype::BufferType( 21_u32.try_into().unwrap(), @@ -3442,12 +3472,15 @@ fn test_principal_construct() { // `int` argument instead of `(buff 1)` for version. ( r#"(principal-construct? 22 0xfa6bf38ed557fe417333710d6033e9419391a320)"#, - CheckErrorKind::TypeError(Box::new(TypeSignature::BUFFER_1), Box::new(IntType.clone())), + StaticCheckErrorKind::TypeError( + Box::new(TypeSignature::BUFFER_1), + Box::new(IntType.clone()), + ), ), // `name` argument is too long ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a320 "foooooooooooooooooooooooooooooooooooooooo")"#, - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::CONTRACT_NAME_STRING_ASCII_MAX), Box::new(SequenceType(StringType(ASCII(41_u32.try_into().unwrap())))), ), @@ -3455,7 +3488,7 @@ fn test_principal_construct() { // bad argument type for `name` ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a320 u123)"#, - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::CONTRACT_NAME_STRING_ASCII_MAX), Box::new(UIntType), ), @@ -3463,7 +3496,7 @@ fn test_principal_construct() { // too many arguments ( r#"(principal-construct? 0x22 0xfa6bf38ed557fe417333710d6033e9419391a320 "foo" "bar")"#, - CheckErrorKind::RequiresAtMostArguments(3, 4), + StaticCheckErrorKind::RequiresAtMostArguments(3, 4), ), ]; @@ -3517,7 +3550,7 @@ fn test_trait_args() { )"]; let contract_identifier = QualifiedContractIdentifier::transient(); - let bad_expected = [CheckErrorKind::IncompatibleTrait( + let bad_expected = [StaticCheckErrorKind::IncompatibleTrait( Box::new(TraitIdentifier { name: ClarityName::from("trait-foo"), contract_identifier: contract_identifier.clone(), @@ -3683,15 +3716,15 @@ fn test_list_arg(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ", ]; let bad_expected = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::IntType, 4).unwrap()), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::UIntType, 1).unwrap()), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new( TypeSignature::list_of( @@ -3703,15 +3736,15 @@ fn test_list_arg(#[case] version: ClarityVersion, #[case] epoch: StacksEpochId) ), ]; let bad_expected2 = [ - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::list_of(TypeSignature::IntType, 3).unwrap()), Box::new(TypeSignature::list_of(TypeSignature::IntType, 4).unwrap()), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::UIntType), ), - CheckErrorKind::TypeError( + StaticCheckErrorKind::TypeError( Box::new(TypeSignature::IntType), Box::new(TypeSignature::list_of(TypeSignature::NoType, 0).unwrap()), ), @@ -3823,17 +3856,17 @@ fn test_simple_bad_syntax_bindings() { "(from-consensus-buff? (tuple (a (string-ascii -12))) 0x00)", ]; let expected = [ - 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, + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_list(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_invalid_length(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::let_binding_not_atom(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_list(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::eval_binding_invalid_length(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::eval_binding_not_atom(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_list(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_invalid_length(0)), + StaticCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::tuple_cons_not_atom(0)), + StaticCheckErrorKind::ValueOutOfBounds, + StaticCheckErrorKind::ValueOutOfBounds, ]; for (bad_code, expected_err) in bad.iter().zip(expected.iter()) { @@ -3857,9 +3890,9 @@ fn test_nested_bad_type_signature_syntax_bindings() { ]; let expected = [ - CheckErrorKind::ValueOutOfBounds, - CheckErrorKind::InvalidTypeDescription, - CheckErrorKind::ValueOutOfBounds, + StaticCheckErrorKind::ValueOutOfBounds, + StaticCheckErrorKind::InvalidTypeDescription, + StaticCheckErrorKind::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 1be8f15918e..58f08e8de95 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::{CheckErrorKind, StaticCheckError}; +use crate::vm::analysis::errors::{StaticCheckError, StaticCheckErrorKind}; use crate::vm::analysis::type_checker::contexts::TypeMap; use crate::vm::costs::LimitedCostTracker; use crate::vm::types::signatures::FunctionSignature; @@ -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(CheckErrorKind::BadTraitImplementation( + return Err(StaticCheckErrorKind::BadTraitImplementation( trait_name, func_name.to_string(), ) @@ -250,7 +250,7 @@ impl ContractAnalysis { } if !expected_sig.returns.admits_type(epoch, &func.returns)? { - return Err(CheckErrorKind::BadTraitImplementation( + return Err(StaticCheckErrorKind::BadTraitImplementation( trait_name, func_name.to_string(), ) @@ -258,7 +258,7 @@ impl ContractAnalysis { } } (_, _) => { - return Err(CheckErrorKind::BadTraitImplementation( + return Err(StaticCheckErrorKind::BadTraitImplementation( trait_name, func_name.to_string(), ) diff --git a/clarity/src/vm/clarity.rs b/clarity/src/vm/clarity.rs index ef51074c72a..bd06b628c46 100644 --- a/clarity/src/vm/clarity.rs +++ b/clarity/src/vm/clarity.rs @@ -2,7 +2,9 @@ use std::fmt; use stacks_common::types::StacksEpochId; -use crate::vm::analysis::{AnalysisDatabase, CheckErrorKind, ContractAnalysis, StaticCheckError}; +use crate::vm::analysis::{ + AnalysisDatabase, CheckErrorKind, ContractAnalysis, StaticCheckError, StaticCheckErrorKind, +}; use crate::vm::ast::errors::{ParseError, ParseErrorKind}; use crate::vm::ast::ContractAST; use crate::vm::contexts::{AssetMap, Environment, OwnedEnvironment}; @@ -76,17 +78,18 @@ impl std::error::Error for ClarityError { } } +#[cfg(any(test, feature = "testing"))] impl From for ClarityError { fn from(e: StaticCheckError) -> Self { match *e.err { - CheckErrorKind::CostOverflow => { + StaticCheckErrorKind::CostOverflow => { ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - CheckErrorKind::CostBalanceExceeded(a, b) => ClarityError::CostError(a, b), - CheckErrorKind::MemoryBalanceExceeded(_a, _b) => { + StaticCheckErrorKind::CostBalanceExceeded(a, b) => ClarityError::CostError(a, b), + StaticCheckErrorKind::MemoryBalanceExceeded(_a, _b) => { ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } - CheckErrorKind::ExecutionTimeExpired => { + StaticCheckErrorKind::ExecutionTimeExpired => { ClarityError::CostError(ExecutionCost::max_value(), ExecutionCost::max_value()) } _ => ClarityError::StaticCheck(e), @@ -255,7 +258,7 @@ pub trait TransactionConnection: ClarityConnection { let cost_track = contract_analysis.take_contract_cost_tracker(); (cost_track, Ok((contract_ast, contract_analysis))) } - Err(e) => (e.1, Err(e.0.into())), + Err(e) => (e.1, Err(ClarityError::StaticCheck(e.0))), } }) } @@ -275,13 +278,13 @@ pub trait TransactionConnection: ClarityConnection { Ok(_) => { let result = db .commit() - .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()); + .map_err(|e| StaticCheckErrorKind::Expects(format!("{e:?}")).into()); (cost_tracker, result) } Err(e) => { let result = db .roll_back() - .map_err(|e| CheckErrorKind::Expects(format!("{e:?}")).into()); + .map_err(|e| StaticCheckErrorKind::Expects(format!("{e:?}")).into()); if result.is_err() { (cost_tracker, result) } else { diff --git a/clarity/src/vm/errors.rs b/clarity/src/vm/errors.rs index bc3d9c1e469..11341ea05b5 100644 --- a/clarity/src/vm/errors.rs +++ b/clarity/src/vm/errors.rs @@ -21,7 +21,7 @@ pub use clarity_types::errors::{ pub use crate::vm::analysis::errors::{ check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, - SyntaxBindingError, SyntaxBindingErrorType, + StaticCheckError, StaticCheckErrorKind, SyntaxBindingError, SyntaxBindingErrorType, }; #[cfg(test)] diff --git a/clarity/src/vm/functions/define.rs b/clarity/src/vm/functions/define.rs index 30094737998..80ac4f6988e 100644 --- a/clarity/src/vm/functions/define.rs +++ b/clarity/src/vm/functions/define.rs @@ -16,6 +16,9 @@ use std::collections::BTreeMap; +use clarity_types::errors::analysis::CommonCheckErrorKind; +use clarity_types::VmExecutionError; + use crate::vm::callables::{DefineType, DefinedFunction}; use crate::vm::contexts::{ContractContext, Environment, LocalContext}; use crate::vm::errors::{ @@ -288,7 +291,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>, CheckErrorKind> { + ) -> std::result::Result>, CommonCheckErrorKind> { let (define_type, args) = match DefineFunctions::try_parse(expression) { Some(x) => x, None => return Ok(None), @@ -296,7 +299,9 @@ impl<'a> DefineFunctionsParsed<'a> { let result = match define_type { DefineFunctions::Constant => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; + let name = args[0] + .match_atom() + .ok_or(CommonCheckErrorKind::ExpectedName)?; DefineFunctionsParsed::Constant { name, value: &args[1], @@ -306,7 +311,7 @@ impl<'a> DefineFunctionsParsed<'a> { check_argument_count(2, args)?; let signature = args[0] .match_list() - .ok_or(CheckErrorKind::DefineFunctionBadSignature)?; + .ok_or(CommonCheckErrorKind::DefineFunctionBadSignature)?; DefineFunctionsParsed::PrivateFunction { signature, body: &args[1], @@ -316,7 +321,7 @@ impl<'a> DefineFunctionsParsed<'a> { check_argument_count(2, args)?; let signature = args[0] .match_list() - .ok_or(CheckErrorKind::DefineFunctionBadSignature)?; + .ok_or(CommonCheckErrorKind::DefineFunctionBadSignature)?; DefineFunctionsParsed::ReadOnlyFunction { signature, body: &args[1], @@ -326,7 +331,7 @@ impl<'a> DefineFunctionsParsed<'a> { check_argument_count(2, args)?; let signature = args[0] .match_list() - .ok_or(CheckErrorKind::DefineFunctionBadSignature)?; + .ok_or(CommonCheckErrorKind::DefineFunctionBadSignature)?; DefineFunctionsParsed::PublicFunction { signature, body: &args[1], @@ -334,7 +339,9 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::NonFungibleToken => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; + let name = args[0] + .match_atom() + .ok_or(CommonCheckErrorKind::ExpectedName)?; DefineFunctionsParsed::NonFungibleToken { name, nft_type: &args[1], @@ -342,7 +349,9 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::FungibleToken => { check_arguments_at_least(1, args)?; - let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; + let name = args[0] + .match_atom() + .ok_or(CommonCheckErrorKind::ExpectedName)?; if args.len() == 1 { DefineFunctionsParsed::UnboundedFungibleToken { name } } else if args.len() == 2 { @@ -351,12 +360,14 @@ impl<'a> DefineFunctionsParsed<'a> { max_supply: &args[1], } } else { - return Err(CheckErrorKind::IncorrectArgumentCount(1, args.len())); + return Err(CommonCheckErrorKind::IncorrectArgumentCount(1, args.len())); } } DefineFunctions::Map => { check_argument_count(3, args)?; - let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; + let name = args[0] + .match_atom() + .ok_or(CommonCheckErrorKind::ExpectedName)?; DefineFunctionsParsed::Map { name, key_type: &args[1], @@ -365,7 +376,9 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::PersistedVariable => { check_argument_count(3, args)?; - let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; + let name = args[0] + .match_atom() + .ok_or(CommonCheckErrorKind::ExpectedName)?; DefineFunctionsParsed::PersistedVariable { name, data_type: &args[1], @@ -374,7 +387,9 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::Trait => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; + let name = args[0] + .match_atom() + .ok_or(CommonCheckErrorKind::ExpectedName)?; DefineFunctionsParsed::Trait { name, functions: &args[1..], @@ -382,13 +397,15 @@ impl<'a> DefineFunctionsParsed<'a> { } DefineFunctions::UseTrait => { check_argument_count(2, args)?; - let name = args[0].match_atom().ok_or(CheckErrorKind::ExpectedName)?; + let name = args[0] + .match_atom() + .ok_or(CommonCheckErrorKind::ExpectedName)?; match &args[1].expr { Field(ref field) => DefineFunctionsParsed::UseTrait { name, trait_identifier: field, }, - _ => return Err(CheckErrorKind::ExpectedTraitIdentifier), + _ => return Err(CommonCheckErrorKind::ExpectedTraitIdentifier), } } DefineFunctions::ImplTrait => { @@ -397,7 +414,7 @@ impl<'a> DefineFunctionsParsed<'a> { Field(ref field) => DefineFunctionsParsed::ImplTrait { trait_identifier: field, }, - _ => return Err(CheckErrorKind::ExpectedTraitIdentifier), + _ => return Err(CommonCheckErrorKind::ExpectedTraitIdentifier), } } }; @@ -409,7 +426,9 @@ pub fn evaluate_define( expression: &SymbolicExpression, env: &mut Environment, ) -> Result { - if let Some(define_type) = DefineFunctionsParsed::try_parse(expression)? { + if let Some(define_type) = DefineFunctionsParsed::try_parse(expression) + .map_err(|e| VmExecutionError::Unchecked(e.into()))? + { match define_type { DefineFunctionsParsed::Constant { name, value } => { handle_define_variable(name, value, env) diff --git a/clarity/src/vm/functions/mod.rs b/clarity/src/vm/functions/mod.rs index b82a028aeb3..a81641bdc89 100644 --- a/clarity/src/vm/functions/mod.rs +++ b/clarity/src/vm/functions/mod.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use clarity_types::errors::analysis::CommonCheckErrorKind; use stacks_common::types::StacksEpochId; use crate::vm::callables::{cost_input_sized_vararg, CallableType, NativeHandle}; @@ -685,7 +686,7 @@ pub fn handle_binding_list( ) -> std::result::Result<(), E> where F: FnMut(&ClarityName, &SymbolicExpression) -> std::result::Result<(), E>, - E: for<'a> From<(CheckErrorKind, &'a SymbolicExpression)>, + E: for<'a> From<(CommonCheckErrorKind, &'a SymbolicExpression)>, { for (i, binding) in bindings.iter().enumerate() { let binding_expression = binding.match_list().ok_or_else(|| { diff --git a/clarity/src/vm/tests/variables.rs b/clarity/src/vm/tests/variables.rs index af65c3e24c9..cbace07f7c0 100644 --- a/clarity/src/vm/tests/variables.rs +++ b/clarity/src/vm/tests/variables.rs @@ -13,7 +13,6 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see . - #[cfg(any(test, feature = "testing"))] use rstest::rstest; #[cfg(test)] @@ -25,7 +24,7 @@ use crate::vm::{ analysis::type_checker::v2_1::tests::contracts::type_check_version, ast::parse, database::MemoryBackingStore, - errors::{CheckErrorKind, VmExecutionError}, + errors::{CheckErrorKind, StaticCheckErrorKind, VmExecutionError}, tests::{tl_env_factory, TopLevelMemoryEnvironmentGenerator}, types::{PrincipalData, QualifiedContractIdentifier, Value}, ClarityVersion, ContractContext, @@ -54,7 +53,7 @@ fn test_block_height( if version >= ClarityVersion::Clarity3 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrorKind::UndefinedVariable("block-height".to_string()), + StaticCheckErrorKind::UndefinedVariable("block-height".to_string()), *err.err ); } else { @@ -113,7 +112,7 @@ fn test_stacks_block_height( if version < ClarityVersion::Clarity3 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrorKind::UndefinedVariable("stacks-block-height".to_string()), + StaticCheckErrorKind::UndefinedVariable("stacks-block-height".to_string()), *err.err ); } else { @@ -172,7 +171,7 @@ fn test_tenure_height( if version < ClarityVersion::Clarity3 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrorKind::UndefinedVariable("tenure-height".to_string()), + StaticCheckErrorKind::UndefinedVariable("tenure-height".to_string()), *err.err ); } else { @@ -208,12 +207,12 @@ fn test_tenure_height( } } +#[cfg(test)] #[derive(Debug, PartialEq)] -enum WhenError { - Analysis, - Initialization, - Runtime, - Never, +enum ExpectedContractError { + Analysis(StaticCheckErrorKind), + Initialization(CheckErrorKind), + Runtime(CheckErrorKind), } #[cfg(test)] @@ -225,9 +224,8 @@ fn expect_contract_error( name: &str, contract: &str, expected_errors: &[( - WhenError, fn(ClarityVersion, StacksEpochId) -> bool, - CheckErrorKind, + ExpectedContractError, )], expected_success: Value, ) { @@ -244,13 +242,15 @@ fn expect_contract_error( type_check_version(&contract_identifier, &mut exprs, db, true, epoch, version) }); - for (when, err_condition, expected_error) in expected_errors { - if *when == WhenError::Analysis && err_condition(version, epoch) { - let err = analysis.unwrap_err(); - assert_eq!(*expected_error, *err.err); + for (err_condition, expected_error) in expected_errors { + if let ExpectedContractError::Analysis(expected_error) = expected_error { + if err_condition(version, epoch) { + let err = analysis.unwrap_err(); + assert_eq!(expected_error, &*err.err); - // Do not continue with the test if the analysis failed. - return; + // Do not continue with the test if the analysis failed. + return; + } } } @@ -270,17 +270,18 @@ fn expect_contract_error( None, ); - 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 VmExecutionError::Unchecked(inner_err) = &err { - assert_eq!(expected_error, inner_err); - } else { - panic!("Expected an Unchecked error, but got a different error"); + for (err_condition, expected_error) in expected_errors { + if let ExpectedContractError::Initialization(expected_error) = expected_error { + if err_condition(version, epoch) { + let err = init_result.unwrap_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"); + } + // Do not continue with the test if the initialization failed. + return; } - - // Do not continue with the test if the initialization failed. - return; } } @@ -289,17 +290,19 @@ fn expect_contract_error( // Call the function let eval_result = env.eval_read_only(&contract_identifier, "(test-func)"); - 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 VmExecutionError::Unchecked(inner_err) = &err { - assert_eq!(expected_error, inner_err); - } else { - panic!("Expected an Unchecked error, but got a different error"); + for (err_condition, expected_error) in expected_errors { + if let ExpectedContractError::Runtime(expected_error) = expected_error { + if err_condition(version, epoch) { + let err = eval_result.unwrap_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"); + } + + // Do not continue with the test if the evaluation failed. + return; } - - // Do not continue with the test if the evaluation failed. - return; } } @@ -326,14 +329,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::UInt(1234), @@ -353,14 +358,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Bool(true), @@ -381,14 +388,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Runtime, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Runtime(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Int(32), @@ -412,14 +421,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Runtime, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Runtime(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Int(3), @@ -437,14 +448,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Bool(true), @@ -462,14 +475,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::UInt(1234), @@ -487,14 +502,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Bool(false), @@ -527,14 +544,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Bool(false), @@ -552,14 +571,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Bool(false), @@ -577,14 +598,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Bool(true), @@ -602,14 +625,16 @@ fn reuse_block_height( "#, &[ ( - WhenError::Initialization, |version, _| version < ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "block-height".to_string(), + )), ), ( - WhenError::Analysis, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::ReservedWord("block-height".to_string()), + ExpectedContractError::Analysis(StaticCheckErrorKind::ReservedWord( + "block-height".to_string(), + )), ), ], Value::Bool(true), @@ -635,9 +660,10 @@ fn reuse_stacks_block_height( ) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::UInt(1234), ); @@ -655,9 +681,10 @@ fn reuse_stacks_block_height( ) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Bool(true), ); @@ -676,9 +703,10 @@ fn reuse_stacks_block_height( ) "#, &[( - WhenError::Runtime, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Runtime(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Int(32), ); @@ -700,9 +728,10 @@ fn reuse_stacks_block_height( ) "#, &[( - WhenError::Runtime, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Runtime(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Int(3), ); @@ -718,9 +747,10 @@ fn reuse_stacks_block_height( (define-private (test-func) (stacks-block-height)) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Bool(true), ); @@ -736,9 +766,10 @@ fn reuse_stacks_block_height( (define-read-only (test-func) stacks-block-height) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::UInt(1234), ); @@ -754,9 +785,10 @@ fn reuse_stacks_block_height( (define-read-only (test-func) false) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Bool(false), ); @@ -787,9 +819,10 @@ fn reuse_stacks_block_height( (define-read-only (test-func) false) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Bool(false), ); @@ -805,9 +838,10 @@ fn reuse_stacks_block_height( (define-read-only (test-func) false) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Bool(false), ); @@ -823,9 +857,10 @@ fn reuse_stacks_block_height( (define-private (test-func) (unwrap-panic (stacks-block-height))) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Bool(true), ); @@ -841,9 +876,10 @@ fn reuse_stacks_block_height( (define-private (test-func) (stacks-block-height)) "#, &[( - WhenError::Initialization, |version, _| version >= ClarityVersion::Clarity3, - CheckErrorKind::NameAlreadyUsed("stacks-block-height".to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + "stacks-block-height".to_string(), + )), )], Value::Bool(true), ); @@ -872,9 +908,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::UInt(1234), ); @@ -894,9 +931,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::Bool(true), ); @@ -917,9 +955,8 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Runtime, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Runtime(CheckErrorKind::NameAlreadyUsed(name.to_string())), )], Value::Int(32), ); @@ -943,9 +980,8 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Runtime, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Runtime(CheckErrorKind::NameAlreadyUsed(name.to_string())), )], Value::Int(3), ); @@ -963,9 +999,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::Bool(true), ); @@ -983,9 +1020,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::UInt(1234), ); @@ -1003,9 +1041,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::Bool(false), ); @@ -1040,9 +1079,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::Bool(false), ); @@ -1060,9 +1100,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::Bool(false), ); @@ -1080,9 +1121,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::Bool(true), ); @@ -1100,9 +1142,10 @@ fn reuse_builtin_name( "# ), &[( - WhenError::Initialization, version_check, - CheckErrorKind::NameAlreadyUsed(name.to_string()), + ExpectedContractError::Initialization(CheckErrorKind::NameAlreadyUsed( + name.to_string(), + )), )], Value::Bool(true), ); @@ -1133,7 +1176,7 @@ fn test_block_time( if version < ClarityVersion::Clarity4 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrorKind::UndefinedVariable("stacks-block-time".to_string()), + StaticCheckErrorKind::UndefinedVariable("stacks-block-time".to_string()), *err.err ); } else { @@ -1260,7 +1303,7 @@ fn test_current_contract( if version < ClarityVersion::Clarity4 { let err = analysis.unwrap_err(); assert_eq!( - CheckErrorKind::UndefinedVariable("current-contract".to_string()), + StaticCheckErrorKind::UndefinedVariable("current-contract".to_string()), *err.err ); } else { diff --git a/clarity/src/vm/types/signatures.rs b/clarity/src/vm/types/signatures.rs index aadf25f846d..f5f49bc796e 100644 --- a/clarity/src/vm/types/signatures.rs +++ b/clarity/src/vm/types/signatures.rs @@ -17,6 +17,7 @@ use std::collections::BTreeMap; use std::fmt; +use clarity_types::errors::analysis::CommonCheckErrorKind; pub use clarity_types::types::signatures::{ AssetIdentifier, BufferLength, CallableSubtype, ListTypeData, SequenceSubtype, StringSubtype, StringUTF8Length, TupleTypeSignature, TypeSignature, @@ -26,7 +27,7 @@ use stacks_common::types::StacksEpochId; use self::TypeSignature::SequenceType; use crate::vm::costs::{runtime_cost, CostOverflowingMath}; -use crate::vm::errors::{CheckErrorKind, SyntaxBindingError, SyntaxBindingErrorType}; +use crate::vm::errors::{SyntaxBindingError, SyntaxBindingErrorType}; use crate::vm::representations::{ ClarityName, SymbolicExpression, SymbolicExpressionType, TraitDefinition, }; @@ -162,59 +163,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; + ) -> Result; fn parse_buff_type_repr( type_args: &[SymbolicExpression], - ) -> Result; + ) -> 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, CheckErrorKind>; + ) -> Result, CommonCheckErrorKind>; #[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(CheckErrorKind::UnknownTypeName(typename.into())), + _ => Err(CommonCheckErrorKind::UnknownTypeName(typename.into())), } } @@ -224,18 +225,19 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { + ) -> Result { if type_args.len() != 2 { - return Err(CheckErrorKind::InvalidTypeDescription); + return Err(CommonCheckErrorKind::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(|_| CheckErrorKind::ValueTooLarge)?; + let max_len = + u32::try_from(*max_len).map_err(|_| CommonCheckErrorKind::ValueTooLarge)?; ListTypeData::new_list(entry_type, max_len).map(|x| x.into()) } else { - Err(CheckErrorKind::InvalidTypeDescription) + Err(CommonCheckErrorKind::InvalidTypeDescription) } } @@ -245,8 +247,8 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { - let mapped_key_types = parse_name_type_pairs::<_, CheckErrorKind>( + ) -> Result { + let mapped_key_types = parse_name_type_pairs::<_, CommonCheckErrorKind>( epoch, type_args, SyntaxBindingErrorType::TupleCons, @@ -260,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(CheckErrorKind::InvalidTypeDescription); + return Err(CommonCheckErrorKind::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(CheckErrorKind::InvalidTypeDescription) + Err(CommonCheckErrorKind::InvalidTypeDescription) } } @@ -276,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(CheckErrorKind::InvalidTypeDescription); + return Err(CommonCheckErrorKind::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(CheckErrorKind::InvalidTypeDescription) + Err(CommonCheckErrorKind::InvalidTypeDescription) } } @@ -293,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(CheckErrorKind::InvalidTypeDescription); + return Err(CommonCheckErrorKind::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(CheckErrorKind::InvalidTypeDescription) + Err(CommonCheckErrorKind::InvalidTypeDescription) } } @@ -310,9 +312,9 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { + ) -> Result { if type_args.len() != 1 { - return Err(CheckErrorKind::InvalidTypeDescription); + return Err(CommonCheckErrorKind::InvalidTypeDescription); } let inner_type = TypeSignature::parse_type_repr(epoch, &type_args[0], accounting)?; @@ -323,20 +325,21 @@ impl TypeSignatureExt for TypeSignature { epoch: StacksEpochId, type_args: &[SymbolicExpression], accounting: &mut A, - ) -> Result { + ) -> Result { if type_args.len() != 2 { - return Err(CheckErrorKind::InvalidTypeDescription); + return Err(CommonCheckErrorKind::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)?; - TypeSignature::new_response(ok_type, err_type) + let response_type = TypeSignature::new_response(ok_type, err_type)?; + Ok(response_type) } fn parse_type_repr( epoch: StacksEpochId, x: &SymbolicExpression, accounting: &mut A, - ) -> Result { + ) -> Result { runtime_cost(ClarityCostFunction::TypeParseStep, accounting, 0)?; match x.expr { @@ -347,7 +350,7 @@ impl TypeSignatureExt for TypeSignature { SymbolicExpressionType::List(ref list_contents) => { let (compound_type, rest) = list_contents .split_first() - .ok_or(CheckErrorKind::InvalidTypeDescription)?; + .ok_or(CommonCheckErrorKind::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), @@ -361,10 +364,10 @@ impl TypeSignatureExt for TypeSignature { "response" => { TypeSignature::parse_response_type_repr(epoch, rest, accounting) } - _ => Err(CheckErrorKind::InvalidTypeDescription), + _ => Err(CommonCheckErrorKind::InvalidTypeDescription), } } else { - Err(CheckErrorKind::InvalidTypeDescription) + Err(CommonCheckErrorKind::InvalidTypeDescription) } } SymbolicExpressionType::TraitReference(_, ref trait_definition) @@ -389,7 +392,7 @@ impl TypeSignatureExt for TypeSignature { )), } } - _ => Err(CheckErrorKind::InvalidTypeDescription), + _ => Err(CommonCheckErrorKind::InvalidTypeDescription), } } @@ -398,43 +401,43 @@ impl TypeSignatureExt for TypeSignature { accounting: &mut A, epoch: StacksEpochId, clarity_version: ClarityVersion, - ) -> Result, CheckErrorKind> { + ) -> Result, CommonCheckErrorKind> { let mut trait_signature: BTreeMap = BTreeMap::new(); let functions_types = type_args .first() - .ok_or_else(|| CheckErrorKind::InvalidTypeDescription)? + .ok_or_else(|| CommonCheckErrorKind::InvalidTypeDescription)? .match_list() - .ok_or(CheckErrorKind::DefineTraitBadSignature)?; + .ok_or(CommonCheckErrorKind::DefineTraitBadSignature)?; for function_type in functions_types.iter() { let args = function_type .match_list() - .ok_or(CheckErrorKind::DefineTraitBadSignature)?; + .ok_or(CommonCheckErrorKind::DefineTraitBadSignature)?; if args.len() != 3 { - return Err(CheckErrorKind::InvalidTypeDescription); + return Err(CommonCheckErrorKind::InvalidTypeDescription); } // Extract function's name let fn_name = args[0] .match_atom() - .ok_or(CheckErrorKind::DefineTraitBadSignature)?; + .ok_or(CommonCheckErrorKind::DefineTraitBadSignature)?; // Extract function's arguments let fn_args_exprs = args[1] .match_list() - .ok_or(CheckErrorKind::DefineTraitBadSignature)?; + .ok_or(CommonCheckErrorKind::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(CheckErrorKind::DefineTraitBadSignature), + _ => Err(CommonCheckErrorKind::DefineTraitBadSignature), }, - _ => Err(CheckErrorKind::DefineTraitBadSignature), + _ => Err(CommonCheckErrorKind::DefineTraitBadSignature), }?; if trait_signature @@ -448,7 +451,7 @@ impl TypeSignatureExt for TypeSignature { .is_some() && clarity_version >= ClarityVersion::Clarity2 { - return Err(CheckErrorKind::DefineTraitDuplicateMethod( + return Err(CommonCheckErrorKind::DefineTraitDuplicateMethod( fn_name.to_string(), )); } @@ -473,7 +476,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 = @@ -484,11 +487,12 @@ 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 = - function_type_size.cost_overflow_add(u64::from(arg.type_size()?))?; + function_type_size = function_type_size + .cost_overflow_add(u64::from(arg.type_size()?)) + .map_err(|_| CommonCheckErrorKind::CostOverflow)?; } Ok(function_type_size) } @@ -497,7 +501,7 @@ impl FunctionSignature { &self, epoch: &StacksEpochId, args: Vec, - ) -> Result { + ) -> Result { if args.len() != self.args.len() { return Ok(false); } @@ -546,7 +550,7 @@ pub fn parse_name_type_pairs( accounting: &mut A, ) -> Result, E> where - E: for<'a> From<(CheckErrorKind, &'a SymbolicExpression)>, + E: for<'a> From<(CommonCheckErrorKind, &'a SymbolicExpression)>, { // this is a pretty deep nesting here, but what we're trying to do is pick out the values of // the form: @@ -555,14 +559,14 @@ where use crate::vm::representations::SymbolicExpressionType::List; // step 1: parse it into a vec of symbolicexpression pairs. - let as_pairs: Result, (CheckErrorKind, &SymbolicExpression)> = name_type_pairs + let as_pairs: Result, (CommonCheckErrorKind, &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(( - CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::InvalidLength( + CommonCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::InvalidLength( binding_error_type, i, )), @@ -581,7 +585,7 @@ where .collect(); // step 2: turn into a vec of (name, typesignature) pairs. - let key_types: Result, (CheckErrorKind, &SymbolicExpression)> = (as_pairs?) + let key_types: Result, (CommonCheckErrorKind, &SymbolicExpression)> = (as_pairs?) .iter() .enumerate() .map(|(i, (name_symbol, type_symbol))| { @@ -589,7 +593,7 @@ where .match_atom() .ok_or_else(|| { ( - CheckErrorKind::BadSyntaxBinding(SyntaxBindingError::NotAtom( + CommonCheckErrorKind::BadSyntaxBinding(SyntaxBindingError::NotAtom( binding_error_type, i, )), @@ -614,13 +618,14 @@ impl fmt::Display for FunctionArg { #[cfg(test)] mod test { + use clarity_types::errors::CheckErrorKind; + use clarity_types::errors::CheckErrorKind::*; #[cfg(test)] use rstest::rstest; #[cfg(test)] use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; - use super::CheckErrorKind::*; use super::*; use crate::vm::tests::test_clarity_versions; use crate::vm::types::QualifiedContractIdentifier; @@ -635,7 +640,9 @@ mod test { epoch, ) .unwrap()[0]; - TypeSignature::parse_type_repr(epoch, expr, &mut ()).unwrap_err() + TypeSignature::parse_type_repr(epoch, expr, &mut ()) + .unwrap_err() + .into() } #[apply(test_clarity_versions)] @@ -663,7 +670,7 @@ mod test { assert_eq!( TupleTypeSignature::try_from(keys).unwrap_err(), - ValueTooLarge + CommonCheckErrorKind::ValueTooLarge ); } diff --git a/stackslib/src/chainstate/stacks/boot/contract_tests.rs b/stackslib/src/chainstate/stacks/boot/contract_tests.rs index 7aae0821e5b..cb362755274 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::{CheckErrorKind, VmExecutionError}; +use clarity::vm::errors::{CheckErrorKind, StaticCheckErrorKind, 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, @@ -1713,7 +1713,7 @@ fn simple_epoch21_test() { ClarityError::StaticCheck(e) => { assert_eq!( *e.err, - CheckErrorKind::UnknownFunction("stx-account".into()) + StaticCheckErrorKind::UnknownFunction("stx-account".into()) ); } e => panic!("Should have caused an analysis error: {:#?}", e), diff --git a/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__consensus__append_block_with_contract_call_success.snap.new b/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__consensus__append_block_with_contract_call_success.snap.new deleted file mode 100644 index e63bca6f961..00000000000 --- a/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__consensus__append_block_with_contract_call_success.snap.new +++ /dev/null @@ -1,160 +0,0 @@ ---- -source: stackslib/src/chainstate/tests/consensus.rs -assertion_line: 893 -expression: result -snapshot_kind: text ---- -[ - Success(ExpectedBlockOutput( - marf_hash: "186c8e49bcfc59bb67ed22f031f009a44681f296392e0f92bed520918ba463ae", - transactions: [ - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: Bool(true), - )), - cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 1, - read_count: 1, - runtime: 11968, - ), - ), - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: UInt(1), - )), - cost: ExecutionCost( - write_length: 0, - write_count: 0, - read_length: 103, - read_count: 3, - runtime: 499, - ), - ), - ], - total_block_cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 104, - read_count: 4, - runtime: 12467, - ), - )), - Success(ExpectedBlockOutput( - marf_hash: "ad23713f072473cad6a32125ed5fa822bb62bbfae8ed2302209c12d2f1958128", - transactions: [ - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: Bool(true), - )), - cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 1, - read_count: 1, - runtime: 11968, - ), - ), - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: UInt(1), - )), - cost: ExecutionCost( - write_length: 0, - write_count: 0, - read_length: 103, - read_count: 3, - runtime: 499, - ), - ), - ], - total_block_cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 104, - read_count: 4, - runtime: 12467, - ), - )), - Success(ExpectedBlockOutput( - marf_hash: "021bd30b09b5ac6ff34abd11f05244a966af937b584b1752f272cd717bb25f1d", - transactions: [ - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: Bool(true), - )), - cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 1, - read_count: 1, - runtime: 11968, - ), - ), - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: UInt(1), - )), - cost: ExecutionCost( - write_length: 0, - write_count: 0, - read_length: 103, - read_count: 3, - runtime: 499, - ), - ), - ], - total_block_cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 104, - read_count: 4, - runtime: 12467, - ), - )), - Success(ExpectedBlockOutput( - marf_hash: "0e2829cdc4ea57ab95e61b1c17c604c51b501ab684b75c90286623253aceac31", - transactions: [ - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: Bool(true), - )), - cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 1, - read_count: 1, - runtime: 11968, - ), - ), - ExpectedTransactionOutput( - return_type: Response(ResponseData( - committed: true, - data: UInt(1), - )), - cost: ExecutionCost( - write_length: 0, - write_count: 0, - read_length: 103, - read_count: 3, - runtime: 499, - ), - ), - ], - total_block_cost: ExecutionCost( - write_length: 121, - write_count: 2, - read_length: 104, - read_count: 4, - runtime: 12467, - ), - )), -] diff --git a/stackslib/src/clarity_cli.rs b/stackslib/src/clarity_cli.rs index 3c3bd361de5..e15060ebeab 100644 --- a/stackslib/src/clarity_cli.rs +++ b/stackslib/src/clarity_cli.rs @@ -43,7 +43,6 @@ 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::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 +50,9 @@ 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::{InterpreterResult, RuntimeError, VmExecutionError}; +use crate::clarity::vm::errors::{ + InterpreterResult, RuntimeError, StaticCheckError, VmExecutionError, +}; use crate::clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use crate::clarity::vm::{ analysis, ast, eval_all, ClarityVersion, ContractContext, ContractName, SymbolicExpression, diff --git a/stackslib/src/clarity_vm/tests/analysis_costs.rs b/stackslib/src/clarity_vm/tests/analysis_costs.rs index 5d60bd86c92..ecb9c5827ba 100644 --- a/stackslib/src/clarity_vm/tests/analysis_costs.rs +++ b/stackslib/src/clarity_vm/tests/analysis_costs.rs @@ -16,7 +16,7 @@ use clarity::vm::clarity::{ClarityError, TransactionConnection}; use clarity::vm::costs::ExecutionCost; -use clarity::vm::errors::CheckErrorKind; +use clarity::vm::errors::StaticCheckErrorKind; use clarity::vm::functions::NativeFunctions; use clarity::vm::test_util::TEST_HEADER_DB; use clarity::vm::tests::{test_only_mainnet_to_chain_id, UnitTestBurnStateDB}; @@ -317,7 +317,7 @@ fn undefined_top_variable_error(#[case] use_mainnet: bool, #[case] epoch: Stacks let Err(ClarityError::StaticCheck(check_error)) = analysis_result else { panic!("Bad analysis result: {analysis_result:?}"); }; - let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err else { + let StaticCheckErrorKind::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 bc8a2c96dd5..ce90e4a8ecb 100644 --- a/stackslib/src/clarity_vm/tests/contracts.rs +++ b/stackslib/src/clarity_vm/tests/contracts.rs @@ -16,7 +16,7 @@ use clarity::types::StacksEpochId; use clarity::vm::clarity::ClarityError; -use clarity::vm::errors::{CheckErrorKind, VmExecutionError}; +use clarity::vm::errors::{CheckErrorKind, StaticCheckErrorKind, VmExecutionError}; use clarity::vm::types::SequenceData::Buffer; use clarity::vm::types::{ BuffData, OptionalData, PrincipalData, QualifiedContractIdentifier, TupleData, TypeSignature, @@ -49,7 +49,7 @@ fn test_get_burn_block_info_eval() { let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); if let Err(ClarityError::StaticCheck(check_error)) = res { - if let CheckErrorKind::UnknownFunction(func_name) = *check_error.err { + if let StaticCheckErrorKind::UnknownFunction(func_name) = *check_error.err { assert_eq!(func_name, "get-burn-block-info?"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -70,7 +70,7 @@ fn test_get_burn_block_info_eval() { let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); if let Err(ClarityError::StaticCheck(check_error)) = res { - if let CheckErrorKind::UnknownFunction(func_name) = *check_error.err { + if let StaticCheckErrorKind::UnknownFunction(func_name) = *check_error.err { assert_eq!(func_name, "get-burn-block-info?"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -162,7 +162,7 @@ fn test_get_block_info_eval_v210() { let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); if let Err(ClarityError::StaticCheck(check_error)) = res { - if let CheckErrorKind::NoSuchBlockInfoProperty(name) = *check_error.err { + if let StaticCheckErrorKind::NoSuchBlockInfoProperty(name) = *check_error.err { assert_eq!(name, "block-reward"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -183,7 +183,7 @@ fn test_get_block_info_eval_v210() { let res = clarity_db.analyze_smart_contract(&contract_identifier, clarity_version, contract); if let Err(ClarityError::StaticCheck(check_error)) = res { - if let CheckErrorKind::NoSuchBlockInfoProperty(name) = *check_error.err { + if let StaticCheckErrorKind::NoSuchBlockInfoProperty(name) = *check_error.err { assert_eq!(name, "block-reward"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -345,7 +345,7 @@ fn trait_invocation_205_with_stored_principal() { .unwrap_err(); match error { ClarityError::StaticCheck(ref e) => match *e.err { - CheckErrorKind::TypeError(..) => (), + StaticCheckErrorKind::TypeError(..) => (), _ => panic!("Unexpected error: {:?}", error), }, _ => panic!("Unexpected error: {:?}", error), @@ -876,7 +876,7 @@ fn test_block_heights() { contract_clarity3, ); if let Err(ClarityError::StaticCheck(check_error)) = res { - if let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err { + if let StaticCheckErrorKind::UndefinedVariable(var_name) = *check_error.err { assert_eq!(var_name, "stacks-block-height"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -910,7 +910,7 @@ fn test_block_heights() { contract_clarity3, ); if let Err(ClarityError::StaticCheck(check_error)) = res { - if let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err { + if let StaticCheckErrorKind::UndefinedVariable(var_name) = *check_error.err { assert_eq!(var_name, "stacks-block-height"); } else { panic!("Bad analysis error: {:?}", &check_error); @@ -926,7 +926,7 @@ fn test_block_heights() { contract_clarity1, ); if let Err(ClarityError::StaticCheck(check_error)) = res { - if let CheckErrorKind::UndefinedVariable(var_name) = *check_error.err { + if let StaticCheckErrorKind::UndefinedVariable(var_name) = *check_error.err { assert_eq!(var_name, "block-height"); } else { panic!("Bad analysis error: {:?}", &check_error); From a043b86c50bb68d9c550702b1d94e541f9af2ea9 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 3 Nov 2025 16:40:16 +0000 Subject: [PATCH 02/13] remove unnecessary From conversions. total_type_size return StaticCheckErrorKind> --- clarity-types/src/errors/analysis.rs | 14 ++++++-------- clarity-types/src/errors/mod.rs | 16 ++++++++-------- clarity-types/src/types/serialization.rs | 20 +++++++------------- clarity-types/src/types/signatures.rs | 13 ++++++------- clarity/src/vm/types/signatures.rs | 8 ++++---- 5 files changed, 31 insertions(+), 40 deletions(-) diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index 43269e5c6e7..fb61e5af0e2 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -871,17 +871,15 @@ impl StaticCheckError { } } -impl From<(SyntaxBindingError, &SymbolicExpression)> for StaticCheckError { - fn from(e: (SyntaxBindingError, &SymbolicExpression)) -> Self { - Self::with_expression(StaticCheckErrorKind::BadSyntaxBinding(e.0), e.1) +impl From<(CommonCheckErrorKind, &SymbolicExpression)> for StaticCheckError { + fn from(e: (CommonCheckErrorKind, &SymbolicExpression)) -> Self { + Self::with_expression(e.0.into(), e.1) } } -impl From<(CommonCheckErrorKind, &SymbolicExpression)> for StaticCheckError { - fn from(e: (CommonCheckErrorKind, &SymbolicExpression)) -> Self { - let mut ce = Self::new(e.0.into()); - ce.set_expression(e.1); - ce +impl From<(SyntaxBindingError, &SymbolicExpression)> for StaticCheckError { + fn from(e: (SyntaxBindingError, &SymbolicExpression)) -> Self { + Self::with_expression(StaticCheckErrorKind::BadSyntaxBinding(e.0), e.1) } } diff --git a/clarity-types/src/errors/mod.rs b/clarity-types/src/errors/mod.rs index 4e9948dccf3..4dae0f9ebe8 100644 --- a/clarity-types/src/errors/mod.rs +++ b/clarity-types/src/errors/mod.rs @@ -275,14 +275,6 @@ impl From for VmExecutionError { } } -// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. -// So there shouldn't be any need to convert it to a VmExecutionError. -impl From for VmExecutionError { - fn from(err: CommonCheckErrorKind) -> Self { - VmExecutionError::Unchecked(err.into()) - } -} - impl From for VmExecutionError { fn from(err: CostErrors) -> Self { match err { @@ -303,6 +295,14 @@ impl From for VmExecutionError { } } +// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. +// So there shouldn't be any need to convert it to a VmExecutionError. +impl From for VmExecutionError { + fn from(err: CommonCheckErrorKind) -> Self { + VmExecutionError::Unchecked(err.into()) + } +} + impl From for VmExecutionError { fn from(err: CheckErrorKind) -> Self { VmExecutionError::Unchecked(err) diff --git a/clarity-types/src/types/serialization.rs b/clarity-types/src/types/serialization.rs index 019beb38f49..9747aca13de 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::analysis::{CommonCheckErrorKind, StaticCheckErrorKind}; +use crate::errors::analysis::StaticCheckErrorKind; use crate::errors::{CheckErrorKind, IncomparableError, VmInternalError}; use crate::representations::{ClarityName, ContractName, MAX_STRING_LEN}; use crate::types::{ @@ -129,14 +129,6 @@ impl From for SerializationError { } } -// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. -// So there shouldn't be any need to convert it to a SerializationError. -impl From for SerializationError { - fn from(e: CommonCheckErrorKind) -> Self { - SerializationError::BadTypeError(CheckErrorKind::from(e)) - } -} - define_u8_enum!(TypePrefix { Int = 0, UInt = 1, @@ -621,8 +613,8 @@ impl Value { TypePrefix::Buffer => { let mut buffer_len = [0; 4]; r.read_exact(&mut buffer_len)?; - let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len))?; - + let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len)) + .map_err(CheckErrorKind::from)?; if let Some(x) = &expected_type { let passed_test = match x { TypeSignature::SequenceType(SequenceSubtype::BufferType( @@ -853,7 +845,8 @@ impl Value { TypePrefix::StringASCII => { let mut buffer_len = [0; 4]; r.read_exact(&mut buffer_len)?; - let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len))?; + let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len)) + .map_err(CheckErrorKind::from)?; if let Some(x) = &expected_type { let passed_test = match x { @@ -878,7 +871,8 @@ impl Value { TypePrefix::StringUTF8 => { let mut total_len = [0; 4]; r.read_exact(&mut total_len)?; - let total_len = BufferLength::try_from(u32::from_be_bytes(total_len))?; + let total_len = BufferLength::try_from(u32::from_be_bytes(total_len)) + .map_err(CheckErrorKind::from)?; let mut data: Vec = vec![0; u32::from(total_len) as usize]; diff --git a/clarity-types/src/types/signatures.rs b/clarity-types/src/types/signatures.rs index 7a716fae88e..5db9fe936d7 100644 --- a/clarity-types/src/types/signatures.rs +++ b/clarity-types/src/types/signatures.rs @@ -920,7 +920,7 @@ impl TypeSignature { } /// If one of the types is a NoType, return Ok(the other type), otherwise return least_supertype(a, b) - pub fn factor_out_no_type( + pub(crate) fn factor_out_no_type( epoch: &StacksEpochId, a: &TypeSignature, b: &TypeSignature, @@ -993,7 +993,7 @@ impl TypeSignature { } } - pub fn least_supertype_v2_0( + fn least_supertype_v2_0( a: &TypeSignature, b: &TypeSignature, ) -> Result { @@ -1102,7 +1102,7 @@ impl TypeSignature { } } - pub fn least_supertype_v2_1( + pub(crate) fn least_supertype_v2_1( a: &TypeSignature, b: &TypeSignature, ) -> Result { @@ -1289,19 +1289,18 @@ 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()), )), - _ => Self::type_of(x), + _ => Self::type_of(x).map_err(StaticCheckErrorKind::from), } } // Checks if resulting type signature is of valid size. pub fn construct_parent_list_type(args: &[Value]) -> Result { - let children_types: Result, CommonCheckErrorKind> = - args.iter().map(TypeSignature::type_of).collect(); + let children_types: Result, _> = args.iter().map(TypeSignature::type_of).collect(); Ok(TypeSignature::parent_list_type(&children_types?)?) } diff --git a/clarity/src/vm/types/signatures.rs b/clarity/src/vm/types/signatures.rs index f5f49bc796e..f68f9586a00 100644 --- a/clarity/src/vm/types/signatures.rs +++ b/clarity/src/vm/types/signatures.rs @@ -17,7 +17,7 @@ use std::collections::BTreeMap; use std::fmt; -use clarity_types::errors::analysis::CommonCheckErrorKind; +use clarity_types::errors::analysis::{CommonCheckErrorKind, StaticCheckErrorKind}; pub use clarity_types::types::signatures::{ AssetIdentifier, BufferLength, CallableSubtype, ListTypeData, SequenceSubtype, StringSubtype, StringUTF8Length, TupleTypeSignature, TypeSignature, @@ -476,7 +476,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 = @@ -487,12 +487,12 @@ 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 = function_type_size .cost_overflow_add(u64::from(arg.type_size()?)) - .map_err(|_| CommonCheckErrorKind::CostOverflow)?; + .map_err(|_| StaticCheckErrorKind::CostOverflow)?; } Ok(function_type_size) } From a3a496ff7048bec908e77ddc200422c2b5d28749 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Wed, 5 Nov 2025 12:41:47 +0000 Subject: [PATCH 03/13] cargo fmt --- clarity/src/vm/analysis/type_checker/v2_05/natives/assets.rs | 4 +--- clarity/src/vm/analysis/type_checker/v2_1/mod.rs | 4 ++-- clarity/src/vm/analysis/type_checker/v2_1/natives/assets.rs | 4 +--- clarity/src/vm/analysis/type_checker/v2_1/natives/maps.rs | 3 +-- 4 files changed, 5 insertions(+), 10 deletions(-) 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 3bc0a6af6d1..d5a492d09a9 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,9 +15,7 @@ // along with this program. If not, see . use super::{TypeChecker, TypingContext}; -use crate::vm::analysis::errors::{ - check_argument_count, StaticCheckError, StaticCheckErrorKind, -}; +use crate::vm::analysis::errors::{check_argument_count, StaticCheckError, StaticCheckErrorKind}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::representations::SymbolicExpression; 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 32672a3f7d9..448cd41cb2f 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, - StaticCheckError, StaticCheckErrorKind, SyntaxBindingErrorType, + check_argument_count, check_arguments_at_least, check_arguments_at_most, StaticCheckError, + StaticCheckErrorKind, SyntaxBindingErrorType, }; use crate::vm::analysis::AnalysisDatabase; use crate::vm::costs::cost_functions::ClarityCostFunction; 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 b6461217d75..c00c7aaeeaf 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,9 +17,7 @@ use stacks_common::consts::TOKEN_TRANSFER_MEMO_LENGTH; use super::{TypeChecker, TypingContext}; -use crate::vm::analysis::errors::{ - check_argument_count, StaticCheckError, StaticCheckErrorKind, -}; +use crate::vm::analysis::errors::{check_argument_count, StaticCheckError, StaticCheckErrorKind}; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::runtime_cost; use crate::vm::representations::SymbolicExpression; 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 ca520bced38..26e44b9aea5 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,8 +17,7 @@ use stacks_common::types::StacksEpochId; use crate::vm::analysis::type_checker::v2_1::{ - check_arguments_at_least, StaticCheckError, StaticCheckErrorKind, TypeChecker, - TypingContext, + check_arguments_at_least, StaticCheckError, StaticCheckErrorKind, TypeChecker, TypingContext, }; use crate::vm::costs::cost_functions::ClarityCostFunction; use crate::vm::costs::{analysis_typecheck_cost, runtime_cost}; From b6f048c3664f9c80cd4ee0982f34e6d44921520b Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Thu, 6 Nov 2025 15:10:59 +0000 Subject: [PATCH 04/13] removed unused CommonCheckErrorKind::CouldNotDetermineSerializationType --- clarity-types/src/errors/analysis.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index a5d2a11362c..35925f02d39 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -219,9 +219,6 @@ pub enum CommonCheckErrorKind { /// The `String` wraps the non-existent type name. UnknownTypeName(String), - /// Could not determine the serialization type for a value during analysis. - CouldNotDetermineSerializationType, - /// Could not determine the type of an expression during analysis. CouldNotDetermineType, @@ -651,8 +648,6 @@ pub enum CheckErrorKind { /// Expected an optional or response value but found a different value. /// The `Box` wraps the actual value provided. ExpectedOptionalOrResponseValue(Box), - /// Could not determine the serialization type for a value during analysis. - CouldNotDetermineSerializationType, /// Expected a contract principal value but found a different value. /// The `Box` wraps the actual value provided. ExpectedContractPrincipalValue(Box), @@ -1117,9 +1112,6 @@ impl From for CheckErrorKind { CommonCheckErrorKind::TypeError(a, b) => CheckErrorKind::TypeError(a, b), CommonCheckErrorKind::BadSyntaxBinding(e) => CheckErrorKind::BadSyntaxBinding(e), CommonCheckErrorKind::ValueOutOfBounds => CheckErrorKind::ValueOutOfBounds, - CommonCheckErrorKind::CouldNotDetermineSerializationType => { - CheckErrorKind::CouldNotDetermineSerializationType - } CommonCheckErrorKind::EmptyTuplesNotAllowed => CheckErrorKind::EmptyTuplesNotAllowed, CommonCheckErrorKind::NameAlreadyUsed(name) => CheckErrorKind::NameAlreadyUsed(name), CommonCheckErrorKind::UnknownTypeName(name) => CheckErrorKind::UnknownTypeName(name), @@ -1180,9 +1172,6 @@ impl From for StaticCheckErrorKind { CommonCheckErrorKind::TypeError(a, b) => StaticCheckErrorKind::TypeError(a, b), CommonCheckErrorKind::BadSyntaxBinding(e) => StaticCheckErrorKind::BadSyntaxBinding(e), CommonCheckErrorKind::ValueOutOfBounds => StaticCheckErrorKind::ValueOutOfBounds, - CommonCheckErrorKind::CouldNotDetermineSerializationType => { - StaticCheckErrorKind::CouldNotDetermineSerializationType - } CommonCheckErrorKind::EmptyTuplesNotAllowed => { StaticCheckErrorKind::EmptyTuplesNotAllowed } @@ -1468,7 +1457,6 @@ impl DiagnosableError for CheckErrorKind { CheckErrorKind::InvalidCharactersDetected => "invalid characters detected".into(), CheckErrorKind::InvalidUTF8Encoding => "invalid UTF8 encoding".into(), CheckErrorKind::InvalidSecp65k1Signature => "invalid seckp256k1 signature".into(), - CheckErrorKind::CouldNotDetermineSerializationType => "could not determine the input type for the serialization function".into(), CheckErrorKind::ExpectedListOfAllowances(fn_name, arg_num) => format!("{fn_name} expects a list of asset allowances as argument {arg_num}"), CheckErrorKind::AllowanceExprNotAllowed => "allowance expressions are only allowed in the context of a `restrict-assets?` or `as-contract?`".into(), CheckErrorKind::ExpectedAllowanceExpr(got_name) => format!("expected an allowance expression, got: {got_name}"), From 2fedc147f30f796206a7897e2f9b5d173e27929c Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Wed, 12 Nov 2025 08:39:23 +0000 Subject: [PATCH 05/13] fix cost error conversion during contract analysis. Thanks ConsensusTest! --- clarity/src/vm/clarity.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clarity/src/vm/clarity.rs b/clarity/src/vm/clarity.rs index bd06b628c46..418ad8a745a 100644 --- a/clarity/src/vm/clarity.rs +++ b/clarity/src/vm/clarity.rs @@ -78,7 +78,6 @@ impl std::error::Error for ClarityError { } } -#[cfg(any(test, feature = "testing"))] impl From for ClarityError { fn from(e: StaticCheckError) -> Self { match *e.err { @@ -258,7 +257,7 @@ pub trait TransactionConnection: ClarityConnection { let cost_track = contract_analysis.take_contract_cost_tracker(); (cost_track, Ok((contract_ast, contract_analysis))) } - Err(e) => (e.1, Err(ClarityError::StaticCheck(e.0))), + Err(e) => (e.1, Err(e.0.into())), } }) } From 614220272290c41fa541b8bdb0bdaa8bb1d1871e Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Wed, 12 Nov 2025 09:46:37 +0000 Subject: [PATCH 06/13] update CommonCheckErrorKind comments --- clarity-types/src/errors/analysis.rs | 28 +++++++++++----------------- clarity-types/src/errors/mod.rs | 4 ---- clarity/src/vm/analysis/errors.rs | 3 ++- clarity/src/vm/analysis/mod.rs | 4 +++- clarity/src/vm/errors.rs | 3 ++- 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index 35925f02d39..d5de5c3ac2f 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -154,25 +154,19 @@ impl From for CommonCheckErrorKind { } } -/// Internal set of error variants that are shared exclusively between static analysis (deployment) -// and runtime checking (execution), specifically for validation logic that is implemented in common -// code paths used by both. +/// Shared set of error variants that are between static analysis (during contract deployment) +/// and runtime checking (during contract execution), specifically for validation logic that +/// is implemented in common code paths used by both. /// -/// **This enum is strictly for internal use and is not a part of the public API.** +/// All these variants represent errors that can arise only from code executed in both analysis and +/// execution contexts—such as argument count checks, type size limits, or shared cost tracking logic. +/// If an error may be triggered by either context via common logic, it lives here. /// -/// All these variants represent errors that can arise *only* from code executed in both analysis and execution -/// contexts—such as argument count checks, type size limits, or shared cost tracking logic. If an error -/// may be triggered by either context via common logic, it lives here. -/// -/// Importantly, this enum does *not* cover all errors common to both analysis and execution. +/// Importantly, this enum does not cover all errors common to both analysis and execution. /// There are other error shared error variants, but those are generated specifically by logic /// that is unique to static analysis or unique to execution. These errors are defined separately -/// and do not pass through this enum. Only error cases that can possibly arise from a shared validation -/// flow will appear here. -/// -/// When a `CommonCheckErrorKind` is produced, it is always converted immediately into either a -/// [`StaticCheckErrorKind`] (when encountered during deployment analysis) *or* a -/// [`CheckErrorKind`] (when encountered at runtime). +/// and do not pass through this enum. Only error cases that can possibly arise from a shared +/// validation flow will appear here. #[derive(Debug, PartialEq)] pub enum CommonCheckErrorKind { // Cost checker errors @@ -862,8 +856,7 @@ pub struct StaticCheckError { } impl CheckErrorKind { - /// Does this check error indicate that the transaction should be - /// rejected? + /// This check indicates that the transaction should be rejected. pub fn rejectable(&self) -> bool { matches!( self, @@ -873,6 +866,7 @@ impl CheckErrorKind { } impl StaticCheckErrorKind { + /// This check indicates that the transaction should be rejected. pub fn rejectable(&self) -> bool { matches!( self, diff --git a/clarity-types/src/errors/mod.rs b/clarity-types/src/errors/mod.rs index a4586953245..957fef5ef25 100644 --- a/clarity-types/src/errors/mod.rs +++ b/clarity-types/src/errors/mod.rs @@ -295,8 +295,6 @@ impl From for VmExecutionError { } } -// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. -// So there shouldn't be any need to convert it to a VmExecutionError. impl From for VmExecutionError { fn from(err: CommonCheckErrorKind) -> Self { VmExecutionError::Unchecked(err.into()) @@ -309,8 +307,6 @@ impl From for VmExecutionError { } } -// TODO: remove. CommonCheckErrorKind shouldn't be used in the public API. -// So there shouldn't be any need to convert it to a VmExecutionError. impl From<(CommonCheckErrorKind, &SymbolicExpression)> for VmExecutionError { fn from(err: (CommonCheckErrorKind, &SymbolicExpression)) -> Self { VmExecutionError::Unchecked(err.0.into()) diff --git a/clarity/src/vm/analysis/errors.rs b/clarity/src/vm/analysis/errors.rs index c7e326e6a6e..15002f5a15d 100644 --- a/clarity/src/vm/analysis/errors.rs +++ b/clarity/src/vm/analysis/errors.rs @@ -16,5 +16,6 @@ pub use clarity_types::errors::analysis::{ check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, - StaticCheckError, StaticCheckErrorKind, SyntaxBindingError, SyntaxBindingErrorType, + CommonCheckErrorKind, StaticCheckError, StaticCheckErrorKind, SyntaxBindingError, + SyntaxBindingErrorType, }; diff --git a/clarity/src/vm/analysis/mod.rs b/clarity/src/vm/analysis/mod.rs index 9da98099d2e..4bc15d41944 100644 --- a/clarity/src/vm/analysis/mod.rs +++ b/clarity/src/vm/analysis/mod.rs @@ -28,7 +28,9 @@ 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::{CheckErrorKind, StaticCheckError, StaticCheckErrorKind}; +pub use self::errors::{ + CheckErrorKind, CommonCheckErrorKind, StaticCheckError, StaticCheckErrorKind, +}; use self::read_only_checker::ReadOnlyChecker; use self::trait_checker::TraitChecker; use self::type_checker::v2_05::TypeChecker as TypeChecker2_05; diff --git a/clarity/src/vm/errors.rs b/clarity/src/vm/errors.rs index 11341ea05b5..04d712a60dd 100644 --- a/clarity/src/vm/errors.rs +++ b/clarity/src/vm/errors.rs @@ -21,7 +21,8 @@ pub use clarity_types::errors::{ pub use crate::vm::analysis::errors::{ check_argument_count, check_arguments_at_least, check_arguments_at_most, CheckErrorKind, - StaticCheckError, StaticCheckErrorKind, SyntaxBindingError, SyntaxBindingErrorType, + CommonCheckErrorKind, StaticCheckError, StaticCheckErrorKind, SyntaxBindingError, + SyntaxBindingErrorType, }; #[cfg(test)] From 1554bac596bf3501e7283a70aea7d5ee58c94375 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Wed, 12 Nov 2025 09:47:37 +0000 Subject: [PATCH 07/13] replace fuzz error CheckErrorKind::TraitReferenceNotAllowed with TraitReferenceUnknown --- clarity/fuzz/fuzz_targets/fuzz_sanitize.rs | 144 +++++++++--------- .../fuzz/fuzz_targets/fuzz_value_sanitize.rs | 4 +- 2 files changed, 79 insertions(+), 69 deletions(-) diff --git a/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs b/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs index 7b509750abe..298151e096f 100644 --- a/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs +++ b/clarity/fuzz/fuzz_targets/fuzz_sanitize.rs @@ -16,24 +16,17 @@ #![no_main] use arbitrary::Arbitrary; -use clarity::vm::types::TypeSignature; -use clarity::vm::types::signatures::SequenceSubtype; -use clarity::vm::Value as ClarityValue; -use clarity::vm::types::SequenceData; -use clarity::vm::types::PrincipalData; -use clarity::vm::types::StandardPrincipalData; -use clarity::vm::types::QualifiedContractIdentifier; -use clarity::vm::types::TupleData; -use clarity::vm::types::CharType; -use clarity::vm::ClarityName; +use clarity::vm::analysis::CheckErrorKind; use clarity::vm::representations::ContractName; use clarity::vm::types::serialization::SerializationError; +use clarity::vm::types::signatures::SequenceSubtype; +use clarity::vm::types::{ + CharType, PrincipalData, QualifiedContractIdentifier, SequenceData, StandardPrincipalData, + StringSubtype, TupleData, TypeSignature, +}; +use clarity::vm::{ClarityName, Value as ClarityValue}; +use libfuzzer_sys::{arbitrary, fuzz_target}; use stacks_common::types::StacksEpochId; -use clarity::vm::analysis::CheckErrorKind; -use clarity::vm::types::StringSubtype; - -use libfuzzer_sys::arbitrary; -use libfuzzer_sys::fuzz_target; #[derive(Debug)] struct FuzzClarityValue(ClarityValue); @@ -92,11 +85,15 @@ impl arbitrary::Arbitrary<'_> for FuzzClarityValue { .map_err(|_| arbitrary::Error::IncorrectFormat)?, 6 => ClarityValue::error(FuzzClarityValue::arbitrary(u)?.0) .map_err(|_| arbitrary::Error::IncorrectFormat)?, - 7 => ClarityValue::Principal(PrincipalData::Standard(FuzzStandardPrincipal::arbitrary(u)?.0)), - 8 => ClarityValue::Principal(PrincipalData::Contract(QualifiedContractIdentifier::new( + 7 => ClarityValue::Principal(PrincipalData::Standard( FuzzStandardPrincipal::arbitrary(u)?.0, - FuzzContractName::arbitrary(u)?.0, - ))), + )), + 8 => { + ClarityValue::Principal(PrincipalData::Contract(QualifiedContractIdentifier::new( + FuzzStandardPrincipal::arbitrary(u)?.0, + FuzzContractName::arbitrary(u)?.0, + ))) + } // utf8 9 => ClarityValue::string_utf8_from_bytes(Arbitrary::arbitrary(u)?) .map_err(|_| arbitrary::Error::IncorrectFormat)?, @@ -111,7 +108,7 @@ impl arbitrary::Arbitrary<'_> for FuzzClarityValue { let value_vec: Vec = Arbitrary::arbitrary(u)?; ClarityValue::cons_list_unsanitized(value_vec.into_iter().map(|x| x.0).collect()) .map_err(|_| arbitrary::Error::IncorrectFormat)? - }, + } // tuple 13 => { let tuple_data: Vec<(FuzzClarityName, FuzzClarityValue)> = Arbitrary::arbitrary(u)?; @@ -119,11 +116,11 @@ impl arbitrary::Arbitrary<'_> for FuzzClarityValue { tuple_data .into_iter() .map(|(key, value)| (key.0, value.0)) - .collect() - ) - .map_err(|_| arbitrary::Error::IncorrectFormat)? - .into() - }, + .collect(), + ) + .map_err(|_| arbitrary::Error::IncorrectFormat)? + .into() + } _ => return Err(arbitrary::Error::IncorrectFormat), }; @@ -161,7 +158,7 @@ pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result { let buff_data = match x { ClarityValue::Sequence(SequenceData::Buffer(ref buff_data)) => buff_data, @@ -171,37 +168,46 @@ pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result { + } + TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::ASCII( + ref my_max_len, + ))) => { let ascii_data = match x { - ClarityValue::Sequence(SequenceData::String(CharType::ASCII(ref ascii_data))) => ascii_data, + ClarityValue::Sequence(SequenceData::String(CharType::ASCII(ref ascii_data))) => { + ascii_data + } _ => return Ok(false), }; if ascii_data.len().map_or(false, |n| &n > my_max_len) { return Ok(false); } return Ok(true); - }, - TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::UTF8(ref my_max_len))) => { + } + TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::UTF8( + ref my_max_len, + ))) => { let utf8_data = match x { - ClarityValue::Sequence(SequenceData::String(CharType::UTF8(ref utf8_data))) => utf8_data, + ClarityValue::Sequence(SequenceData::String(CharType::UTF8(ref utf8_data))) => { + utf8_data + } _ => return Ok(false), }; - if utf8_data.len().map_or(false, |n| u32::from(n) > u32::from(my_max_len.clone())) { + if utf8_data + .len() + .map_or(false, |n| u32::from(n) > u32::from(my_max_len.clone())) + { return Ok(false); } return Ok(true); - }, + } TypeSignature::PrincipalType => match x { ClarityValue::Principal(_) => Ok(true), _ => Ok(false), }, TypeSignature::OptionalType(ref ot) => match x { - ClarityValue::Optional(inner_value) => { - match &inner_value.data { - Some(some_value) => strict_admits(ot, some_value), - None => Ok(true), - } + ClarityValue::Optional(inner_value) => match &inner_value.data { + Some(some_value) => strict_admits(ot, some_value), + None => Ok(true), }, _ => Ok(false), }, @@ -216,29 +222,31 @@ pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result { let tuple_data = match x { ClarityValue::Tuple(td) => td, _ => return Ok(false), }; if tt.len() != tuple_data.len() { - return Ok(false) + return Ok(false); } for (field, field_type) in tt.get_type_map().iter() { let field_value = match tuple_data.get(&field) { Ok(x) => x, - Err(_) => return Ok(false) + Err(_) => return Ok(false), }; if !strict_admits(field_type, field_value)? { return Ok(false); } } return Ok(true); - }, - TypeSignature::CallableType(_) | - TypeSignature::ListUnionType(_) | - TypeSignature::TraitReferenceType(_) => Err(CheckErrorKind::TraitReferenceNotAllowed), + } + TypeSignature::CallableType(_) + | TypeSignature::ListUnionType(_) + | TypeSignature::TraitReferenceType(_) => Err(CheckErrorKind::TraitReferenceUnknown( + "Unknown trait reference".into(), + )), } } @@ -250,11 +258,9 @@ fn fuzz_sanitize(input: ClarityValue) { let computed_type = TypeSignature::type_of(&input).unwrap(); let did_strict_admit = strict_admits(&computed_type, &input).unwrap(); - let (sanitized_value, did_sanitize) = ClarityValue::sanitize_value( - &StacksEpochId::Epoch24, - &computed_type, - input.clone() - ).unwrap(); + let (sanitized_value, did_sanitize) = + ClarityValue::sanitize_value(&StacksEpochId::Epoch24, &computed_type, input.clone()) + .unwrap(); if did_strict_admit { assert_eq!(input, sanitized_value); @@ -265,11 +271,8 @@ fn fuzz_sanitize(input: ClarityValue) { } let serialized = input.serialize_to_vec().expect("serialize input"); - let deserialize_unsanitized = ClarityValue::deserialize_read( - &mut serialized.as_slice(), - Some(&computed_type), - false - ); + let deserialize_unsanitized = + ClarityValue::deserialize_read(&mut serialized.as_slice(), Some(&computed_type), false); if !did_strict_admit { deserialize_unsanitized.unwrap_err(); } else { @@ -280,9 +283,10 @@ fn fuzz_sanitize(input: ClarityValue) { ClarityValue::deserialize_read( &mut serialized.as_slice(), Some(&computed_type), - true - ).unwrap() - }, + true, + ) + .unwrap() + } deser_result => deser_result.unwrap(), }; assert_eq!(deser_value, input); @@ -291,17 +295,19 @@ fn fuzz_sanitize(input: ClarityValue) { let deserialize_sanitized = match ClarityValue::deserialize_read( &mut serialized.as_slice(), Some(&computed_type), - true + true, ) { Ok(x) => x, 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"); + let serialized = sanitized_value + .serialize_to_vec() + .expect("serialize sanitized"); let deserialize_unsanitized = match ClarityValue::deserialize_read( &mut serialized.as_slice(), Some(&computed_type), - false + false, ) { Err(SerializationError::BadTypeError(CheckErrorKind::TypeSignatureTooDeep)) => { // pre-2.4, deserializer could error on legal types deeper than a deserialization limit of 16. @@ -309,9 +315,10 @@ fn fuzz_sanitize(input: ClarityValue) { ClarityValue::deserialize_read( &mut serialized.as_slice(), Some(&computed_type), - true - ).unwrap() - }, + true, + ) + .unwrap() + } deser_result => deser_result.unwrap(), }; assert_eq!(deserialize_unsanitized, sanitized_value); @@ -319,13 +326,14 @@ fn fuzz_sanitize(input: ClarityValue) { let deserialize_sanitized = ClarityValue::deserialize_read( &mut serialized.as_slice(), Some(&computed_type), - true - ).unwrap(); + true, + ) + .unwrap(); assert_eq!(deserialize_sanitized, sanitized_value); assert!(strict_admits(&computed_type, &deserialize_sanitized).unwrap()); return; } - Err(e) => panic!("Unexpected error from deserialization: {}", e) + Err(e) => panic!("Unexpected error from deserialization: {}", e), }; assert!(strict_admits(&computed_type, &deserialize_sanitized).unwrap()); diff --git a/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs b/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs index 52c983daecb..79bad892823 100644 --- a/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs +++ b/clarity/fuzz/fuzz_targets/fuzz_value_sanitize.rs @@ -251,7 +251,9 @@ pub fn strict_admits(me: &TypeSignature, x: &ClarityValue) -> Result Err(CheckErrorKind::TraitReferenceNotAllowed), + | TypeSignature::TraitReferenceType(_) => Err(CheckErrorKind::TraitReferenceUnknown( + "Unknown trait reference".into(), + )), } } From 6eb5496822e730df878457dcfae9738f704efaab Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Tue, 2 Dec 2025 12:38:25 +0000 Subject: [PATCH 08/13] remove CheckErrorKind variants for static analysis only --- clarity-types/src/errors/analysis.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index 732b159c52b..40f397302e2 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -831,8 +831,6 @@ pub enum CheckErrorKind { /// Attempt to write to contract state in a read-only function. WriteAttemptedInReadOnly, - /// `at-block` closure must be read-only but contains write operations. - AtBlockClosureMustBeReadOnly, // contract post-conditions /// Post-condition expects a list of asset allowances but received invalid input. @@ -843,15 +841,6 @@ pub enum CheckErrorKind { /// Expected an allowance expression but found invalid input. /// The `String` wraps the unexpected input. ExpectedAllowanceExpr(String), - /// `with-all-assets-unsafe` is not allowed in this context. - WithAllAllowanceNotAllowed, - /// `with-all-assets-unsafe` cannot be used alongside other allowances. - WithAllAllowanceNotAlone, - /// `with-nft` allowance requires a list of asset identifiers. - WithNftExpectedListOfIdentifiers, - /// `with-nft` allowance identifiers list exceeds the maximum allowed length. - /// The first `u32` represents the maximum length, and the second represents the actual length. - MaxIdentifierLengthExceeded(u32, u32), /// Too many allowances specified in post-condition. /// The first `usize` represents the maximum allowed, and the second represents the actual count. TooManyAllowances(usize, usize), @@ -1470,7 +1459,6 @@ impl DiagnosableError for CheckErrorKind { CheckErrorKind::TooManyFunctionParameters(found, allowed) => format!("too many function parameters specified: found {found}, the maximum is {allowed}"), 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::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}')"), @@ -1488,10 +1476,6 @@ impl DiagnosableError for CheckErrorKind { CheckErrorKind::ExpectedListOfAllowances(fn_name, arg_num) => format!("{fn_name} expects a list of asset allowances as argument {arg_num}"), CheckErrorKind::AllowanceExprNotAllowed => "allowance expressions are only allowed in the context of a `restrict-assets?` or `as-contract?`".into(), CheckErrorKind::ExpectedAllowanceExpr(got_name) => format!("expected an allowance expression, got: {got_name}"), - CheckErrorKind::WithAllAllowanceNotAllowed => "with-all-assets-unsafe is not allowed here, only in the allowance list for `as-contract?`".into(), - CheckErrorKind::WithAllAllowanceNotAlone => "with-all-assets-unsafe must not be used along with other allowances".into(), - CheckErrorKind::WithNftExpectedListOfIdentifiers => "with-nft allowance must include a list of asset identifiers".into(), - CheckErrorKind::MaxIdentifierLengthExceeded(max_len, len) => format!("with-nft allowance identifiers list must not exceed {max_len} elements, got {len}"), CheckErrorKind::TooManyAllowances(max_allowed, found) => format!("too many allowances specified, the maximum is {max_allowed}, found {found}"), } } From a6ee03cb59735ceaebf9127966d89c5eb541ed9d Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Tue, 2 Dec 2025 13:21:00 +0000 Subject: [PATCH 09/13] add docstring for impl From for String --- clarity-types/src/errors/analysis.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index 40f397302e2..e9d19fa65f7 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -1198,6 +1198,8 @@ impl From for StaticCheckErrorKind { } } +/// This conversion is provided to support tests in +/// `clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs`. #[cfg(any(test, feature = "testing"))] impl From for String { fn from(o: StaticCheckErrorKind) -> Self { From ebd47f53f3593f28ed06bb50c2c07e1ab524f0b4 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Tue, 2 Dec 2025 13:21:32 +0000 Subject: [PATCH 10/13] remove impl DiagnosableError for CheckErrorKind --- clarity-types/src/errors/analysis.rs | 108 --------------------------- 1 file changed, 108 deletions(-) diff --git a/clarity-types/src/errors/analysis.rs b/clarity-types/src/errors/analysis.rs index e9d19fa65f7..14f34b0ba73 100644 --- a/clarity-types/src/errors/analysis.rs +++ b/clarity-types/src/errors/analysis.rs @@ -1387,111 +1387,3 @@ impl DiagnosableError for StaticCheckErrorKind { } } } - -impl DiagnosableError for CheckErrorKind { - fn message(&self) -> String { - match &self { - 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()), - 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()), - CheckErrorKind::BadMatchInput(t) => - format!("match requires an input of either a response or optional, found input: '{t}'"), - 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::CostComputationFailed(s) => format!("contract cost computation failed: {s}"), - CheckErrorKind::ExecutionTimeExpired => "execution time expired".into(), - 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::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::ExpectedOptionalOrResponseValue(found_value) => format!("expecting expression of type 'optional' or 'response', found '{found_value}'"), - 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::CouldNotDetermineType => "type of expression cannot be determined".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::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::NoSuchMap(map_name) => format!("use of unresolved map '{map_name}'"), - CheckErrorKind::DefineFunctionBadSignature => "invalid function definition".into(), - CheckErrorKind::BadFunctionName => "invalid function name".into(), - CheckErrorKind::PublicFunctionMustReturnResponse(found_type) => format!("public functions must return an expression of type 'response', found '{found_type}'"), - 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::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::GetBlockInfoExpectPropertyName => "missing property name for 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::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::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::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::TooManyFunctionParameters(found, allowed) => format!("too many function parameters specified: found {found}, the maximum is {allowed}"), - 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::BadTokenName => "expecting an token name as an argument".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::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::DefineTraitBadSignature => "invalid trait definition".into(), - CheckErrorKind::DefineTraitDuplicateMethod(method_name) => format!("duplicate method name '{method_name}' in trait definition"), - CheckErrorKind::ContractOfExpectsTrait => "trait reference expected".into(), - CheckErrorKind::TraitTooManyMethods(found, allowed) => format!("too many trait methods specified: found {found}, the maximum is {allowed}"), - CheckErrorKind::InvalidCharactersDetected => "invalid characters detected".into(), - CheckErrorKind::InvalidUTF8Encoding => "invalid UTF8 encoding".into(), - CheckErrorKind::InvalidSecp65k1Signature => "invalid seckp256k1 signature".into(), - CheckErrorKind::ExpectedListOfAllowances(fn_name, arg_num) => format!("{fn_name} expects a list of asset allowances as argument {arg_num}"), - CheckErrorKind::AllowanceExprNotAllowed => "allowance expressions are only allowed in the context of a `restrict-assets?` or `as-contract?`".into(), - CheckErrorKind::ExpectedAllowanceExpr(got_name) => format!("expected an allowance expression, got: {got_name}"), - CheckErrorKind::TooManyAllowances(max_allowed, found) => format!("too many allowances specified, the maximum is {max_allowed}, found {found}"), - } - } - - fn suggestion(&self) -> Option { - match &self { - CheckErrorKind::BadLetSyntax => Some( - "'let' syntax example: (let ((supply 1000) (ttl 60)) )".into(), - ), - CheckErrorKind::TraitReferenceUnknown(_) => Some( - "traits should be either defined, with define-trait, or imported, with use-trait." - .into(), - ), - _ => None, - } - } -} From 9831c3418f1e9c45e434b868ecaab714c9825b3a Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 5 Dec 2025 08:30:53 +0000 Subject: [PATCH 11/13] document unreachable CheckErrorKind variants --- .../tests/runtime_analysis_tests.rs | 128 ++++++++++++++---- 1 file changed, 99 insertions(+), 29 deletions(-) diff --git a/stackslib/src/chainstate/tests/runtime_analysis_tests.rs b/stackslib/src/chainstate/tests/runtime_analysis_tests.rs index ad37eee3bf8..e06833223b0 100644 --- a/stackslib/src/chainstate/tests/runtime_analysis_tests.rs +++ b/stackslib/src/chainstate/tests/runtime_analysis_tests.rs @@ -57,14 +57,17 @@ fn variant_coverage_report(variant: CheckErrorKind) { use VariantCoverage::*; _ = match variant { - CostOverflow => todo!(), + CostOverflow => Unreachable_ExpectLike, // Should exceed u64 CostBalanceExceeded(_, _) => Tested(vec![ check_error_cost_balance_exceeded_cdeploy, check_error_cost_balance_exceeded_ccall ]), - MemoryBalanceExceeded(_, _) - | CostComputationFailed(_) - | ExecutionTimeExpired => todo!(), + MemoryBalanceExceeded(_, _) => Tested(vec![ + check_error_memory_balance_exceeded_cdeploy, + check_error_memory_balance_exceeded_ccall + ]), + CostComputationFailed(_) => Unreachable_ExpectLike, + ExecutionTimeExpired => todo!(), ValueTooLarge => Tested(vec![ check_error_kind_value_too_large_cdeploy, check_error_kind_value_too_large_ccall @@ -74,47 +77,114 @@ fn variant_coverage_report(variant: CheckErrorKind) { check_error_kind_type_signature_too_deep_cdeploy, check_error_kind_type_signature_too_deep_ccall ]), - | ExpectedName - | SupertypeTooLarge - | Expects(_) - | BadMatchOptionSyntax(_) - | BadMatchResponseSyntax(_) - | BadMatchInput(_) => todo!(), + ExpectedName => Unreachable_Functionally( + "Every place in the runtime where ExpectedName is raised comes from a direct + call to SymbolicExpression::match_atom() on the original AST node and the type + checker runs the same structure check during analysis."), + SupertypeTooLarge => Unreachable_Functionally( + "least_supertype checks already run in analysis, and runtime values are + sanitized to their declared signatures, so the VM never sees a pair of + values whose unified type wasn't accepted earlier."), + Expects(_) => Unreachable_ExpectLike, + BadMatchOptionSyntax(_) => Unreachable_Functionally( + "Both the analyzer and the runtime examine the exact same match AST slice. + The static pass invokes check_special_match_opt, which enforces the 3 + argument structure and the some binding name before any code is accepted"), + BadMatchResponseSyntax(_) => Unreachable_Functionally( + "Both the analyzer and the runtime examine the exact same match AST slice. + The static pass invokes check_special_match_resp, which enforces the 4 + argument structure and the ok and err binding names before any code is accepted."), + BadMatchInput(_) => Unreachable_Functionally( + "Both the analyzer and the runtime examine the exact same match AST slice. + The static pass invokes check_special_match, which enforces the 2 argument + structure and the input type before any code is accepted."), ListTypesMustMatch => Tested(vec![check_error_kind_list_types_must_match_cdeploy]), TypeError(_, _) => todo!(), TypeValueError(_, _) => Tested(vec![ check_error_kind_type_value_error_cdeploy, check_error_kind_type_value_error_ccall ]), - InvalidTypeDescription - | UnknownTypeName(_) - | UnionTypeError(_, _) => todo!(), + InvalidTypeDescription => Unreachable_Functionally( + "Every invalid type literal is parsed both by the analyzer and by the runtime. + Both paths invoke the same TypeSignature::parse_* helpers, so analysis + always fails before initialization can trigger it."), + UnknownTypeName(_) => Unreachable_Functionally( + "Static analysis catches invalid types via `TypeSignature::parse_atom_type`."), + UnionTypeError(_, _) => Unreachable_Functionally( + "The analyzer enforces that every call to `bit-shift-left` / `bit-shift-right` + supplies an argument whose type is exactly `int` or `uint` (see + `NativeFunctions::BitwiseLShift|BitwiseRShift` using + `FunctionArgSignature::Union(IntType, UIntType)` and the + `TypeSignature::admits_type` checks in `type_checker::check_function_arg_signature`)"), UnionTypeValueError(_, _) => Tested(vec![ check_error_kind_union_type_value_error_cdeploy, check_error_kind_union_type_value_error_ccall ]), - | ExpectedOptionalValue(_) - | ExpectedResponseValue(_) - | ExpectedOptionalOrResponseValue(_)=> todo!(), + ExpectedOptionalValue(_) => Unreachable_Functionally( + "Every optional primitive (`is-some`, `default-to`, `unwrap!`, etc.) + has a dedicated analysis hook (`check_special_is_optional`, + `check_special_default_to`, `inner_unwrap`, …) that enforces the optional + type before a contract can be published, so the runtime never sees a plain + `Value` arrive at `native_default_to` / `is_some`."), + ExpectedResponseValue(_) => Unreachable_Functionally( + "Response helpers are validated by `check_special_is_response` and `inner_unwrap_err` + during static analysis, preventing a non-response from reaching the runtime handlers"), + ExpectedOptionalOrResponseValue(_) => Unreachable_Functionally( + "The mixed helpers (`match`, `try!`, `unwrap!`, `unwrap-err!`) ultimately + delegate to `check_special_match` and `inner_unwrap` in the analyzer, which enforces + that the argument is either an optional or a response before the code is accepted. + There is no runtime path where a plain value reaches `native_try_ret` or the + option/response matchers"), ExpectedContractPrincipalValue(_) => Tested(vec![ check_error_kind_expected_contract_principal_value_cdeploy, check_error_kind_expected_contract_principal_value_ccall ]), CouldNotDetermineType => Tested(vec![check_error_kind_could_not_determine_type_ccall]), - BadTokenName - | NoSuchNFT(_) - | NoSuchFT(_) - | BadTransferSTXArguments - | BadTransferFTArguments - | BadTransferNFTArguments - | BadMintFTArguments - | BadBurnFTArguments - | ExpectedTuple(_) => todo!(), - NoSuchTupleField(_, _) | DefineFunctionBadSignature | BadFunctionName | PublicFunctionMustReturnResponse(_) => Unreachable_Functionally("On contract deploy checked during static analysis."), - EmptyTuplesNotAllowed | NoSuchMap(_) => Unreachable_Functionally("On contract deploy checked during static analysis. (At runtime, just used for loading cost functions on block begin)"), - NoSuchDataVariable(_) => Unreachable_Functionally("On contract deploy checked during static analysis. (At runtime, just used for loading cost functions on block begin and for handle prepare phase)"), + BadTokenName => Unreachable_Functionally( + "Asset natives call `match_atom()` on their token arg during analysis."), + NoSuchNFT(_) => Unreachable_Functionally( + "Analysis uses contract_context.get_nft_type during every nft-* checker, + so a reference to an undefined NFT aborts before initialization"), + NoSuchFT(_) => Unreachable_Functionally( + "ft-* analyzers call contract_context.ft_exists, preventing undefined + fungible tokens from ever reaching the runtime handlers."), + BadTransferSTXArguments => Unreachable_Functionally( + "The analyzer routes all `stx-transfer?`, `stx-transfer-memo?`, and `stx-burn?` + calls through `check_special_stx_transfer` / `check_special_stx_burn` + which demand a `(uint, principal, principal)` signature before a contract + can be published. Because the runtime caches only sanitized values, + `special_stx_transfer` never receives a malformed value at runtime."), + BadTransferFTArguments => Unreachable_Functionally( + "`check_special_transfer_token` enforces the `(uint, principal, principal)` + argument contract for every FT transfer during analysis, so `special_transfer_token` + never sees a mismatched set of values at runtime."), + BadTransferNFTArguments => Unreachable_Functionally( + "`check_special_transfer_asset` ensures that the NFT + identifier plus `(principal, principal)` pair have the right types, + preventing `special_transfer_asset` from failing at runtime."), + BadMintFTArguments => Unreachable_Functionally( + "`check_special_mint_token` requires a `(uint, principal)` + argument tuple for fungible minting before deployment, so the runtime + never raises `BadMintFTArguments`"), + BadBurnFTArguments => Unreachable_Functionally( + "`check_special_burn_token` enforces `(uint, principal)` + during static analysis, making the runtime variant unobservable."), + ExpectedTuple(_) => Unreachable_Functionally( + "`check_special_get`/`check_special_merge` ensure every + `(get …)`/`(merge …)` argument is statically typed as a tuple (or + option wrapping a tuple), so `tuple_get` / `tuple_merge` never see + a non-tuple at runtime"), + NoSuchTupleField(_, _) => Unreachable_Functionally( + "`check_special_get` verifies tuple field existence for every `(get …)` + during static analysis, so `tuple_get` never receives a missing field"), + DefineFunctionBadSignature | BadFunctionName | PublicFunctionMustReturnResponse(_) => Unreachable_Functionally( + "On contract deploy checked during static analysis."), + EmptyTuplesNotAllowed | NoSuchMap(_) => Unreachable_Functionally( + "On contract deploy checked during static analysis. (At runtime, just used for loading cost functions on block begin)"), + NoSuchDataVariable(_) => Unreachable_Functionally( + "On contract deploy checked during static analysis. (At runtime, just used for loading cost functions on block begin and for handle prepare phase)"), ReturnTypesMustMatch(_, _) => Tested(vec![check_error_kind_return_types_must_match_ccall]), - CircularReference(_) => Tested(vec![check_error_kind_circular_reference_ccall]), + CircularReference(_) => Tested(vec![check_error_kind_circular_reference_ccall]), // Possible only during contract call. On contract deploy checked during parsing. NoSuchContract(_) => Tested(vec![check_error_kind_no_such_contract_ccall]), NoSuchPublicFunction(_, _) => Tested(vec![check_error_kind_no_such_public_function_ccall]), PublicFunctionNotReadOnly(_, _) => Unreachable_Functionally("Environment::inner_execute_contract is invoked with read_only = false on the relevant code path, causing PublicFunctionNotReadOnly check to be skipped."), From 34298ca09f994c859c5717f278a214d139e6a8c1 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 5 Dec 2025 22:22:52 +0800 Subject: [PATCH 12/13] add TypeError consensus tests. plus minor fixes --- .../tests/runtime_analysis_tests.rs | 133 +- ...ts__check_error_kind_type_error_ccall.snap | 1456 +++++++++++++++++ ...__check_error_kind_type_error_cdeploy.snap | 126 ++ 3 files changed, 1709 insertions(+), 6 deletions(-) create mode 100644 stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_ccall.snap create mode 100644 stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_cdeploy.snap diff --git a/stackslib/src/chainstate/tests/runtime_analysis_tests.rs b/stackslib/src/chainstate/tests/runtime_analysis_tests.rs index e06833223b0..cbc40f9337f 100644 --- a/stackslib/src/chainstate/tests/runtime_analysis_tests.rs +++ b/stackslib/src/chainstate/tests/runtime_analysis_tests.rs @@ -67,7 +67,13 @@ fn variant_coverage_report(variant: CheckErrorKind) { check_error_memory_balance_exceeded_ccall ]), CostComputationFailed(_) => Unreachable_ExpectLike, - ExecutionTimeExpired => todo!(), + ExecutionTimeExpired => Unreachable_Functionally( + "All consensus-critical code paths (block validation and transaction processing) + pass `None` for max_execution_time to StacksChainState::process_transaction, + causing GlobalContext::execution_time_tracker to remain ExecutionTimeTracker::NoTracking. + The check_max_execution_time_expired function always returns Ok(()) when tracker + is NoTracking. Execution time limits are only enforced in RPC API calls + and miner-local transaction filtering."), ValueTooLarge => Tested(vec![ check_error_kind_value_too_large_cdeploy, check_error_kind_value_too_large_ccall @@ -99,7 +105,10 @@ fn variant_coverage_report(variant: CheckErrorKind) { The static pass invokes check_special_match, which enforces the 2 argument structure and the input type before any code is accepted."), ListTypesMustMatch => Tested(vec![check_error_kind_list_types_must_match_cdeploy]), - TypeError(_, _) => todo!(), + TypeError(_, _) => Tested(vec![ + check_error_kind_type_error_cdeploy, + check_error_kind_type_error_ccall + ]), TypeValueError(_, _) => Tested(vec![ check_error_kind_type_value_error_cdeploy, check_error_kind_type_value_error_ccall @@ -404,7 +413,7 @@ fn check_error_memory_balance_exceeded_ccall() { // we only test epochs 2.4 and later because the call takes ~200 milion runtime cost, // if we test all epochs, the tenure limit will be exceeded and the last 2 calls in // epoch 3.3 will cause a block rejection. - deploy_epochs: &StacksEpochId::ALL[6..], // Epochs 2.4 and later + deploy_epochs: &StacksEpochId::since(StacksEpochId::Epoch24), ); } @@ -660,6 +669,118 @@ fn check_error_kind_type_signature_too_deep_ccall() { ); } +/// CheckErrorKind: [`CheckErrorKind::TypeError`] +/// Caused by: `at-block` evaluates an expression at a historical block where the contract's +/// state doesn't exist yet (block 0). The result is `none` with no type info (`OptionalType(NoType)`), +/// which then fails when compared with `uint` via `is-eq`. +/// Outcome: block accepted. +#[test] +fn check_error_kind_type_error_cdeploy() { + let contract_1 = SetupContract::new( + "pool-trait", + " + (define-trait pool-trait + ((get-shares-at (uint) (response uint uint))))", + ); + + let contract_2 = SetupContract::new( + "pool", + " + ;; Pool - uses at-block with map access + (impl-trait .pool-trait.pool-trait) + + (define-data-var zero uint u0) + + (define-read-only (get-shares-at (block uint)) + (let ( + (hash (unwrap-panic (get-block-info? id-header-hash block))) + (total-amt (unwrap-panic (at-block hash (ok (var-get zero))))) + (is-zero (is-eq total-amt u0))) ;; this is triggering the TypeError + (ok u0)))", + ) + .with_clarity_version(ClarityVersion::Clarity2); // Only works with clarity 1 or 2 + + contract_deploy_consensus_test!( + contract_name: "value-too-large", + contract_code: " + ;; Rewards - calls pool via trait + (use-trait pool-trait .pool-trait.pool-trait) + + (define-map reward-info { id: uint } { share-block: uint }) + + (define-read-only (get-reward-info (id uint)) + (default-to { share-block: u0 } (map-get? reward-info { id: id }))) + + (define-public (get-shares (id uint) (pool )) + (let ( + (info (get-reward-info id)) + (block (get share-block info)) + ;; the following line triggers the TypeError + (shares (unwrap-panic (contract-call? pool get-shares-at block)))) + (ok shares))) + + (define-constant result (get-shares u999 .pool))", + setup_contracts: &[contract_1, contract_2], + ); +} + +/// CheckErrorKind: [`CheckErrorKind::TypeError`] +/// Caused by: `at-block` evaluates an expression at a historical block where the contract's +/// state doesn't exist yet (block 0). The result is `none` with no type info (`OptionalType(NoType)`), +/// which then fails when compared with `uint` via `is-eq`. +/// Outcome: block accepted. +#[test] +fn check_error_kind_type_error_ccall() { + let contract_1 = SetupContract::new( + "pool-trait", + " + (define-trait pool-trait + ((get-shares-at (uint) (response uint uint))))", + ); + + let contract_2 = SetupContract::new( + "pool", + " + ;; Pool - uses at-block with map access + (impl-trait .pool-trait.pool-trait) + + (define-data-var zero uint u0) + + (define-read-only (get-shares-at (block uint)) + (let ( + (hash (unwrap-panic (get-block-info? id-header-hash block))) + (total-amt (unwrap-panic (at-block hash (ok (var-get zero))))) + (is-zero (is-eq total-amt u0))) ;; this is triggering the TypeError + (ok u0)))", + ) + .with_clarity_version(ClarityVersion::Clarity1); // Only works with clarity 1 or 2 + + contract_call_consensus_test!( + contract_name: "value-too-large", + contract_code: " + (use-trait pool-trait .pool-trait.pool-trait) + + (define-map reward-info { id: uint } { share-block: uint }) + + (define-read-only (get-reward-info (id uint)) + (default-to { share-block: u0 } (map-get? reward-info { id: id }))) + + (define-public (get-shares (id uint) (pool )) + (let ( + (info (get-reward-info id)) + (block (get share-block info)) + ;; the following line triggers the TypeError + (shares (unwrap-panic (contract-call? pool get-shares-at block)))) + (ok shares))) + + (define-public (trigger-error) + (get-shares u999 .pool))", + function_name: "trigger-error", + function_args: &[], + setup_contracts: &[contract_1, contract_2], + ); +} + /// CheckErrorKind: [`CheckErrorKind::TypeValueError`] /// Caused by: passing a value of the wrong type to a function. /// Outcome: block accepted. @@ -824,7 +945,7 @@ fn check_error_kind_union_type_value_error_ccall() { (foo .contract-1))", function_name: "trigger-runtime-error", function_args: &[], - deploy_epochs: &StacksEpochId::ALL[11..], // Epochs 3.3 and later + deploy_epochs: &StacksEpochId::since(StacksEpochId::Epoch33), exclude_clarity_versions: &[ClarityVersion::Clarity1, ClarityVersion::Clarity2, ClarityVersion::Clarity3], setup_contracts: &[contract_1], ); @@ -961,7 +1082,7 @@ fn check_error_kind_expected_contract_principal_value_ccall() { true))"#, function_name: "trigger-error", function_args: &[], - deploy_epochs: &StacksEpochId::ALL[11..], // Epochs 3.3 and later + deploy_epochs: &StacksEpochId::since(StacksEpochId::Epoch33), exclude_clarity_versions: &[ClarityVersion::Clarity1, ClarityVersion::Clarity2, ClarityVersion::Clarity3], ); } @@ -1061,7 +1182,7 @@ fn check_error_kind_could_not_determine_type_ccall() { function_name: "trigger-error", function_args: &[], deploy_epochs: &[StacksEpochId::Epoch23], - call_epochs: &StacksEpochId::ALL[6..], // Epochs 2.4 and later + call_epochs: &StacksEpochId::since(StacksEpochId::Epoch24), exclude_clarity_versions: &[ClarityVersion::Clarity1, ClarityVersion::Clarity3, ClarityVersion::Clarity4], setup_contracts: &[trait_contract, trait_impl], ); diff --git a/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_ccall.snap b/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_ccall.snap new file mode 100644 index 00000000000..298e27a7f04 --- /dev/null +++ b/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_ccall.snap @@ -0,0 +1,1456 @@ +--- +source: stackslib/src/chainstate/tests/runtime_analysis_tests.rs +expression: result +--- +[ + Success(ExpectedBlockOutput( + marf_hash: "40150865647d615aa0f8eeab66c92161ec508b98ea61c6aa06a594fa65425ba8", + evaluated_epoch: Epoch20, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_0-Clarity1, code_body: [..], clarity_version: None)", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 7392000, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 7392000, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "b9099134fac7fe339c301d92ece8dd66d6d9e30cbf5c9d03b71e5704e2b99cd1", + evaluated_epoch: Epoch2_05, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_05-Clarity1, code_body: [..], clarity_version: None)", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 421039, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 421039, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "e384351d497d008a323ee31f7330dad1c53e8d97256dbb4847d7081b2bd8ed1f", + evaluated_epoch: Epoch21, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_1-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "4fb1a80a5dcc6241427e096815b3c392f609dabfc304da1d2d2523e6a6c539b5", + evaluated_epoch: Epoch21, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_1-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "8815e8b5a750faba45950912d27d4399d8dea78be84dde56b339b14c139148e3", + evaluated_epoch: Epoch22, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_2-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "ebaf0cfc9bb8f3c02ee4c9af5bc93debe3ff70f7940dbd82516ec63e04709779", + evaluated_epoch: Epoch22, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_2-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "b779de76128da56deedf61b8228a116eae22de782573cd14bcbb53c516dc6211", + evaluated_epoch: Epoch23, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_3-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "70b836f3ef80545f4929a77becbfc5ca17aed146970b3bc27de5d0af613916ba", + evaluated_epoch: Epoch23, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_3-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "13d45d4fe25c6da0cc9de308850ee4d8f07542d4cc5b27d66e4f47e38c3d6fe4", + evaluated_epoch: Epoch24, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_4-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "f63a1a46ee0e513a13f26bdbf3ecf1707a85941c51bcdc375944912367262677", + evaluated_epoch: Epoch24, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_4-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "087a9ab93882ef7bfe8e4603db8e724c9fff91ed1fe8bf7a3fff2e68a913ad30", + evaluated_epoch: Epoch25, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_5-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "2e24bd4ae40b271c638e68d91f1f7300bc0df64b0259a673f2db95931cdc7c26", + evaluated_epoch: Epoch25, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch2_5-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "9c16a2b9d79d3caf68cd90a0696cee3291edf9bb1e370912f0a6f6b5edd60dec", + evaluated_epoch: Epoch30, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_0-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "9c260e621ad20c5afd254b05f4b7b986ba45a3c263a2fb30887976da3ffba58d", + evaluated_epoch: Epoch30, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_0-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "10f5900707ec40faa9cd8d9d47e13c058743dc4fdc5bbcd8306b2f63a48368c1", + evaluated_epoch: Epoch30, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_0-Clarity3, code_body: [..], clarity_version: Some(Clarity3))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "f94dc0555e25227cf8ed2f6d05f81aff3940445dc66fbe68b871ad3dab8a15ff", + evaluated_epoch: Epoch31, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_1-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "7fe37ec11ea9f08cf1fc243b549be39fcf68663accb67d86bfbe74f47036a110", + evaluated_epoch: Epoch31, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_1-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "a0c5b8c27b5c2447ae2397b91590902ba031272ba1a4a7ab3790204f514b00d5", + evaluated_epoch: Epoch31, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_1-Clarity3, code_body: [..], clarity_version: Some(Clarity3))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "9f10c8554a327f128bc76c93fda0cdb24dc772e24befd5d6dea5bc150a3790f4", + evaluated_epoch: Epoch32, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_2-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "0ebf8b8eafb39afb9a9537ddafb4114dbcd2ca3be6c9c7301c65f7e8841a1633", + evaluated_epoch: Epoch32, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_2-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "7200b1d6cb50e438bda77fcffedb15f2c3e446840db3f02ca2cffbbe79920e8c", + evaluated_epoch: Epoch32, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_2-Clarity3, code_body: [..], clarity_version: Some(Clarity3))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "805ead69e557e37be939512a5aa6d2c18b0f9b84b7879661a261b25d6aa6c525", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 6, + read_count: 2, + runtime: 38847, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "e7e8b6d20ca98019b591da13237d528dee8f3b468f84559736d5f578375f1ea3", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "eb62c87a91b18e4ac78107a2400ad71facce085e46e1bc021880c0e0b14bd4d0", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity3, code_body: [..], clarity_version: Some(Clarity3))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "2f9cdbaaa30e8a3a4083fb4fbb704b13a370f177b6e10ae627b40cf0d2fbe280", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity4, code_body: [..], clarity_version: Some(Clarity4))", + vm_error: "None [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: true, + data: Bool(true), + )), + cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 789, + write_count: 3, + read_length: 8, + read_count: 3, + runtime: 40485, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "c90efa3fad68239653e442cda095e172c2c2cbc8574bf2f4aeda13d19be92531", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_0-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "f7db254b641b43c52178fae451587b5c7827cfef7d26be6e30ea5110b5f50afc", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_05-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "b036864c807cd62fa6546a1095cdccf3902e088b5cccfe81de43b0868f49950a", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_1-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "bb27d0339502ad660d0b6ebbee3c12490a35fb0230f17696a08227ff9d461f25", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_1-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "c4769034bd6222555c18f65515f5d5887409d6c2ec627a0b73ad990292c97a25", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_2-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "250a4337d2f65fc0a079caee4e3b500e863612ba854dae00e65178b805a56b71", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_2-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "d25fc356a92a2be4aed455b98b65893e49e3626649bef8f2d772d5a58e6252c4", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_3-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "385cdde553233d8da223bedea07064119cc1e153d1724d2231edb9a41d7505c6", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_3-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "838b7c351ac1d393af6c4515b9265675f734103543edc655d6c04db560f3809a", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_4-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "b9757dbbe44c99b62749698ad27054d489672e7203061d3baf4c2adc238e719d", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_4-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "9575074bdf6221689941aa212fc9fd63b371369edef65f27e8500a3469c84194", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_5-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "0001f67447a0be19ad6ab2303b67806390f7225fdeaa51c29539a9bf8ad43bd4", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch2_5-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "ff1516f5fd4807919cb371ec2b97a952196f0fdee7f0ce52169cbb5e4b97153a", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_0-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "73a99e57c087895406a758234e2174f186566c04332f9d2f6ab5243b488bf953", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_0-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "d02ffbc826c95ec3c082d7a6bba9474ecb97c6dce223bf2d0f4b8e38e60fa8cb", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_0-Clarity3, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "3f66b369f8a442b1b88b9a763db5d3b84c8254c61b6bbee9beb79b26eedb8514", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_1-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "20b2083f5cf4af725f1d685fef85e681d1b8933cd7a29eb2b967742e7f981a76", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_1-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "19ebeaf8080b39cd7188317b2c9d2adf6ca390eded4f4b0a4da5b02c40376e54", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_1-Clarity3, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "f128fe18384297b3b3487c3c9cb78e0557b88f0aa71cdeaa8820d43ddd6fb22b", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_2-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "89f508bc9223d1097a55c17f76033944201fffb6a00de2054e76323cbc1a368b", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_2-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "db56784f2bc08034d753ff7dd84dc79188c489789e9cb516ecba8577ae5a5ea9", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_2-Clarity3, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "e839cae025f35684237c14803ee6c5307598fd057de1edee77842aab040c176b", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_3-Clarity1, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "d979c3d437f977f1b465a21e76f392d18d6b8f7e360508f4976613c302b50144", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_3-Clarity2, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "12e95ed282ec81fce5878cab3dc12902ae5c163bdcb18381cc45c371a39a99e4", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_3-Clarity3, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "980d8da97b1126eee286fb011f49112f2bf36319754fe25a7270628eb649ea7c", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "ContractCall(address: ST1AW6EKPGT61SQ9FNVDS17RKNWT8ZP582VF9HSCP, contract_name: value-too-large-Epoch3_3-Clarity4, function_name: trigger-error, function_args: [[]])", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 0, + write_count: 0, + read_length: 1095, + read_count: 10, + runtime: 19452, + ), + )), +] diff --git a/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_cdeploy.snap b/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_cdeploy.snap new file mode 100644 index 00000000000..c5b9483d6f1 --- /dev/null +++ b/stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__runtime_analysis_tests__check_error_kind_type_error_cdeploy.snap @@ -0,0 +1,126 @@ +--- +source: stackslib/src/chainstate/tests/runtime_analysis_tests.rs +expression: result +--- +[ + Success(ExpectedBlockOutput( + marf_hash: "8c2161ba760559dd0a19790ab560252ad1f369b1f2aa2d868868d50967d1e6b3", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity1, code_body: [..], clarity_version: Some(Clarity1))", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 470, + read_count: 9, + runtime: 58240, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 470, + read_count: 9, + runtime: 58240, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "3dce5528fed1676402aeeeb23005cd535a482fb8d930526c7e09f1ad55e5e7eb", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity2, code_body: [..], clarity_version: Some(Clarity2))", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 472, + read_count: 10, + runtime: 59878, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 472, + read_count: 10, + runtime: 59878, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "312bbd18f60e722c1dcf90fbeb7a6962c54d1b3aff1a18e67dcdbd08cf95fc5c", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity3, code_body: [..], clarity_version: Some(Clarity3))", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 472, + read_count: 10, + runtime: 59878, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 472, + read_count: 10, + runtime: 59878, + ), + )), + Success(ExpectedBlockOutput( + marf_hash: "b17737c76f4b5fe4ac96075989298957d6543f8b4ef2c5225a19e973d9d3f82c", + evaluated_epoch: Epoch33, + transactions: [ + ExpectedTransactionOutput( + tx: "SmartContract(name: value-too-large-Epoch3_3-Clarity4, code_body: [..], clarity_version: Some(Clarity4))", + vm_error: "Some(TypeError(UIntType, OptionalType(NoType))) [NON-CONSENSUS BREAKING]", + return_type: Response(ResponseData( + committed: false, + data: Optional(OptionalData( + data: None, + )), + )), + cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 472, + read_count: 10, + runtime: 59878, + ), + ), + ], + total_block_cost: ExecutionCost( + write_length: 811, + write_count: 3, + read_length: 472, + read_count: 10, + runtime: 59878, + ), + )), +] From be60d08ac22658015848da37fe80fa7285be7c60 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 5 Dec 2025 22:29:28 +0800 Subject: [PATCH 13/13] improved docstring --- .../src/chainstate/tests/runtime_analysis_tests.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/stackslib/src/chainstate/tests/runtime_analysis_tests.rs b/stackslib/src/chainstate/tests/runtime_analysis_tests.rs index cbc40f9337f..22a688127ca 100644 --- a/stackslib/src/chainstate/tests/runtime_analysis_tests.rs +++ b/stackslib/src/chainstate/tests/runtime_analysis_tests.rs @@ -670,9 +670,10 @@ fn check_error_kind_type_signature_too_deep_ccall() { } /// CheckErrorKind: [`CheckErrorKind::TypeError`] -/// Caused by: `at-block` evaluates an expression at a historical block where the contract's -/// state doesn't exist yet (block 0). The result is `none` with no type info (`OptionalType(NoType)`), -/// which then fails when compared with `uint` via `is-eq`. +/// Caused by: `(at-block … (ok (var-get zero)))` returns `none` when evaluated at +/// a block where the contract state doesn't exist yet. The code immediately feeds +/// that `OptionalType(NoType)` value into `is-eq` against `u0`, triggering the +/// runtime `TypeError(UIntType, OptionalType(NoType))`. /// Outcome: block accepted. #[test] fn check_error_kind_type_error_cdeploy() { @@ -725,9 +726,10 @@ fn check_error_kind_type_error_cdeploy() { } /// CheckErrorKind: [`CheckErrorKind::TypeError`] -/// Caused by: `at-block` evaluates an expression at a historical block where the contract's -/// state doesn't exist yet (block 0). The result is `none` with no type info (`OptionalType(NoType)`), -/// which then fails when compared with `uint` via `is-eq`. +/// Caused by: `(at-block … (ok (var-get zero)))` returns `none` when evaluated at +/// a block where the contract state doesn't exist yet. The code immediately feeds +/// that `OptionalType(NoType)` value into `is-eq` against `u0`, triggering the +/// runtime `TypeError(UIntType, OptionalType(NoType))`. /// Outcome: block accepted. #[test] fn check_error_kind_type_error_ccall() {