From e92dc67760062013b8b4eaee214413910c32d61c Mon Sep 17 00:00:00 2001 From: Todd Nowacki Date: Tue, 22 Nov 2022 10:36:23 -0800 Subject: [PATCH] [move][adapter] Improve type argument errors (#6286) * [move][adapter] Improve type argument errors - A missing type in a module currently throws an invariant violation from the Move VM, this catches that error and produces a better error --- .../tests/entry_points/ascii.exp | 2 +- .../tests/entry_points/missing_module.exp | 0 .../tests/entry_points/missing_type.exp | 28 ++++++++ .../tests/entry_points/missing_type.move | 25 +++++++ .../tests/entry_points/obj_vector.exp | 6 +- .../tests/entry_points/obj_vector_generic.exp | 6 +- .../tests/shared/by_value_shared_object.exp | 4 +- .../tests/shared/example.exp | 0 .../tests/sui/freeze.exp | 4 +- .../sui/move_call_args_type_mismatch.exp | 2 +- crates/sui-adapter/src/adapter.rs | 26 ++++++- crates/sui-core/src/generate_format.rs | 5 +- crates/sui-core/tests/staged/sui.yaml | 45 ++++++++---- crates/sui-types/src/messages.rs | 68 +++++++++++++++++-- 14 files changed, 188 insertions(+), 33 deletions(-) create mode 100644 crates/sui-adapter-transactional-tests/tests/entry_points/missing_module.exp create mode 100644 crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.exp create mode 100644 crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.move create mode 100644 crates/sui-adapter-transactional-tests/tests/shared/example.exp diff --git a/crates/sui-adapter-transactional-tests/tests/entry_points/ascii.exp b/crates/sui-adapter-transactional-tests/tests/entry_points/ascii.exp index bc3c95a6c7e87..5c75dc6a031e1 100644 --- a/crates/sui-adapter-transactional-tests/tests/entry_points/ascii.exp +++ b/crates/sui-adapter-transactional-tests/tests/entry_points/ascii.exp @@ -17,5 +17,5 @@ task 4 'run'. lines 39-47: written: object(107) task 5 'run'. lines 49-49: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Type mismatch. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Type mismatch. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: TypeMismatch }), source: Some("Unexpected non-ASCII value (outside of ASCII character range) in argument 0") } } diff --git a/crates/sui-adapter-transactional-tests/tests/entry_points/missing_module.exp b/crates/sui-adapter-transactional-tests/tests/entry_points/missing_module.exp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.exp b/crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.exp new file mode 100644 index 0000000000000..41171fdc9e5a8 --- /dev/null +++ b/crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.exp @@ -0,0 +1,28 @@ +processed 7 tasks + +init: +A: object(100) + +task 1 'publish'. lines 8-15: +created: object(104) +written: object(103) + +task 2 'run'. lines 17-17: +Error: Transaction Effects Status: Entry Type Argument Error. Error for type argument at index 0: A package (or module) in the type argument was not found +Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryTypeArgumentError(EntryTypeArgumentError { argument_idx: 0, kind: ModuleNotFound }), source: None } } + +task 3 'run'. lines 19-19: +Error: Transaction Effects Status: Entry Type Argument Error. Error for type argument at index 0: A type was not found in the module specified +Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryTypeArgumentError(EntryTypeArgumentError { argument_idx: 0, kind: TypeNotFound }), source: None } } + +task 4 'run'. lines 21-21: +Error: Transaction Effects Status: Entry Type Argument Error. Error for type argument at index 0: Mismatch between the number of actual versus expected type arguments. +Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryTypeArgumentError(EntryTypeArgumentError { argument_idx: 0, kind: ArityMismatch }), source: None } } + +task 5 'run'. lines 23-23: +Error: Transaction Effects Status: Entry Type Argument Error. Error for type argument at index 0: Mismatch between the number of actual versus expected type arguments. +Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryTypeArgumentError(EntryTypeArgumentError { argument_idx: 0, kind: ArityMismatch }), source: None } } + +task 6 'run'. lines 25-25: +Error: Transaction Effects Status: Entry Type Argument Error. Error for type argument at index 0: A type provided did not match the specified constraints. +Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryTypeArgumentError(EntryTypeArgumentError { argument_idx: 0, kind: ConstraintNotSatisfied }), source: None } } diff --git a/crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.move b/crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.move new file mode 100644 index 0000000000000..bcde46d975ec5 --- /dev/null +++ b/crates/sui-adapter-transactional-tests/tests/entry_points/missing_type.move @@ -0,0 +1,25 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +// tests invalid type args + +//# init --addresses test=0x0 --accounts A + +//# publish +module test::m { + +struct S {} + +entry fun foo() {} + +} + +//# run test::m::foo --type-args test::x::x + +//# run test::m::foo --type-args test::m::SUI + +//# run test::m::foo --type-args test::m::S + +//# run test::m::foo --type-args test::m::S + +//# run test::m::foo --type-args test::m::S diff --git a/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector.exp b/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector.exp index 8bcb39e8b4e98..68a1bbca9b192 100644 --- a/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector.exp +++ b/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector.exp @@ -35,7 +35,7 @@ created: object(116) written: object(115) task 9 'run'. lines 140-143: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Type mismatch. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Type mismatch. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: TypeMismatch }), source: Some("Expected argument of type Test::M::Obj, but found type Test::M::AnotherObj") } } task 10 'run'. lines 145-145: @@ -47,7 +47,7 @@ created: object(121) written: object(120) task 12 'run'. lines 149-152: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Type mismatch. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Type mismatch. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: TypeMismatch }), source: Some("Expected argument of type Test::M::Obj, but found type Test::M::AnotherObj") } } task 13 'run'. lines 154-154: @@ -55,7 +55,7 @@ created: object(124) written: object(123) task 14 'run'. lines 156-159: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByValue }), source: Some("Immutable and shared objects cannot be passed by-value, violation found in argument 0") } } task 15 'run'. lines 161-161: diff --git a/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector_generic.exp b/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector_generic.exp index fa4d4fae732ed..680b87647e8a4 100644 --- a/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector_generic.exp +++ b/crates/sui-adapter-transactional-tests/tests/entry_points/obj_vector_generic.exp @@ -32,7 +32,7 @@ created: object(115) written: object(114) task 8 'run'. lines 137-140: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Type mismatch. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Type mismatch. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: TypeMismatch }), source: Some("Expected argument of type Test::M::ObjAny, but found type Test::M::AnotherObjAny") } } task 9 'run'. lines 142-142: @@ -44,7 +44,7 @@ created: object(120) written: object(119) task 11 'run'. lines 146-149: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Type mismatch. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Type mismatch. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: TypeMismatch }), source: Some("Expected argument of type Test::M::ObjAny, but found type Test::M::AnotherObjAny") } } task 12 'run'. lines 151-151: @@ -52,7 +52,7 @@ created: object(123) written: object(122) task 13 'run'. lines 153-156: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByValue }), source: Some("Immutable and shared objects cannot be passed by-value, violation found in argument 0") } } task 14 'run'. lines 158-158: diff --git a/crates/sui-adapter-transactional-tests/tests/shared/by_value_shared_object.exp b/crates/sui-adapter-transactional-tests/tests/shared/by_value_shared_object.exp index 7f914ceed5292..ac6a3630269bb 100644 --- a/crates/sui-adapter-transactional-tests/tests/shared/by_value_shared_object.exp +++ b/crates/sui-adapter-transactional-tests/tests/shared/by_value_shared_object.exp @@ -18,9 +18,9 @@ Version: 1 Contents: t2::o2::Obj2 {id: sui::object::UID {id: sui::object::ID {bytes: fake(107)}}} task 5 'run'. lines 45-45: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByValue }), source: Some("Immutable and shared objects cannot be passed by-value, violation found in argument 0") } } task 6 'run'. lines 47-47: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByValue }), source: Some("Immutable and shared objects cannot be passed by-value, violation found in argument 0") } } diff --git a/crates/sui-adapter-transactional-tests/tests/shared/example.exp b/crates/sui-adapter-transactional-tests/tests/shared/example.exp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp b/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp index 75f5b7c7b615c..e141d2454001e 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp +++ b/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp @@ -15,9 +15,9 @@ task 3 'run'. lines 74-74: written: object(106), object(107) task 4 'run'. lines 76-76: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByValue }), source: Some("Immutable and shared objects cannot be passed by-value, violation found in argument 0") } } task 5 'run'. lines 78-78: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable objects cannot be passed by mutable reference, &mut. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 0: Immutable objects cannot be passed by mutable reference, &mut. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByMuteRef }), source: Some("Argument 0 is expected to be mutable, immutable object found") } } diff --git a/crates/sui-adapter-transactional-tests/tests/sui/move_call_args_type_mismatch.exp b/crates/sui-adapter-transactional-tests/tests/sui/move_call_args_type_mismatch.exp index 3807b259893d0..0c6be3951c954 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/move_call_args_type_mismatch.exp +++ b/crates/sui-adapter-transactional-tests/tests/sui/move_call_args_type_mismatch.exp @@ -5,7 +5,7 @@ created: object(103) written: object(102) task 2 'run'. lines 14-16: -Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 1: Mismatch between the number of actual versus expected argument. +Error: Transaction Effects Status: Entry Argument Error. Error for argument at index 1: Mismatch between the number of actual versus expected arguments. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 1, kind: ArityMismatch }), source: Some("Expected 2 arguments calling function 'create', but found 1") } } task 3 'run'. lines 17-17: diff --git a/crates/sui-adapter/src/adapter.rs b/crates/sui-adapter/src/adapter.rs index c6e345b944b61..f2f2824d1d90c 100644 --- a/crates/sui-adapter/src/adapter.rs +++ b/crates/sui-adapter/src/adapter.rs @@ -13,8 +13,11 @@ use linked_hash_map::LinkedHashMap; use move_binary_format::{ access::ModuleAccess, binary_views::BinaryIndexedView, - errors::VMResult, - file_format::{AbilitySet, CompiledModule, LocalIndex, SignatureToken, StructHandleIndex}, + errors::{VMError, VMResult}, + file_format::{ + AbilitySet, CompiledModule, LocalIndex, SignatureToken, StructHandleIndex, + TypeParameterIndex, + }, }; use move_bytecode_verifier::VerifierConfig; use move_core_types::{ @@ -205,6 +208,12 @@ fn execute_internal< .map(|(id, (owner, _))| (*id, (by_value_objects.contains(id), *owner))) .collect(); let mut session = new_session(vm, state_view, input_objects); + // check type arguments separately for error conversion + for (idx, ty) in type_args.iter().enumerate() { + session + .load_type(ty) + .map_err(|e| convert_type_argument_error(idx, e))?; + } // script visibility checked manually for entry points let ( SerializedReturnValues { @@ -1372,3 +1381,16 @@ fn missing_unwrapped_msg(id: &ObjectID) -> String { id ) } + +fn convert_type_argument_error(idx: usize, error: VMError) -> ExecutionError { + use move_core_types::vm_status::StatusCode; + use sui_types::messages::EntryTypeArgumentErrorKind; + let kind = match error.major_status() { + StatusCode::LINKER_ERROR => EntryTypeArgumentErrorKind::ModuleNotFound, + StatusCode::TYPE_RESOLUTION_FAILURE => EntryTypeArgumentErrorKind::TypeNotFound, + StatusCode::NUMBER_OF_TYPE_ARGUMENTS_MISMATCH => EntryTypeArgumentErrorKind::ArityMismatch, + StatusCode::CONSTRAINT_NOT_SATISFIED => EntryTypeArgumentErrorKind::ConstraintNotSatisfied, + _ => return error.into(), + }; + ExecutionErrorKind::entry_type_argument_error(idx as TypeParameterIndex, kind).into() +} diff --git a/crates/sui-core/src/generate_format.rs b/crates/sui-core/src/generate_format.rs index 0cfcd8cf58aeb..cac73ae8ffb2e 100644 --- a/crates/sui-core/src/generate_format.rs +++ b/crates/sui-core/src/generate_format.rs @@ -19,8 +19,8 @@ use sui_types::{ AuthoritySignature, KeypairTraits, Signature, }, messages::{ - CallArg, EntryArgumentErrorKind, ExecutionFailureStatus, ExecutionStatus, ObjectArg, - ObjectInfoRequestKind, SingleTransactionKind, TransactionKind, + CallArg, EntryArgumentErrorKind, EntryTypeArgumentErrorKind, ExecutionFailureStatus, + ExecutionStatus, ObjectArg, ObjectInfoRequestKind, SingleTransactionKind, TransactionKind, }, object::{Data, Owner}, storage::DeleteKind, @@ -77,6 +77,7 @@ fn get_registry() -> Result { tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; + tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; diff --git a/crates/sui-core/tests/staged/sui.yaml b/crates/sui-core/tests/staged/sui.yaml index 179ab7065fd22..f99ec7dc6948c 100644 --- a/crates/sui-core/tests/staged/sui.yaml +++ b/crates/sui-core/tests/staged/sui.yaml @@ -114,6 +114,21 @@ EntryArgumentErrorKind: UnsupportedPureArg: UNIT 5: ArityMismatch: UNIT +EntryTypeArgumentError: + STRUCT: + - argument_idx: U16 + - kind: + TYPENAME: EntryTypeArgumentErrorKind +EntryTypeArgumentErrorKind: + ENUM: + 0: + ModuleNotFound: UNIT + 1: + TypeNotFound: UNIT + 2: + ArityMismatch: UNIT + 3: + ConstraintNotSatisfied: UNIT Envelope: STRUCT: - data: @@ -167,23 +182,27 @@ ExecutionFailureStatus: NEWTYPE: TYPENAME: EntryArgumentError 18: + EntryTypeArgumentError: + NEWTYPE: + TYPENAME: EntryTypeArgumentError + 19: CircularObjectOwnership: NEWTYPE: TYPENAME: CircularObjectOwnership - 19: + 20: InvalidChildObjectArgument: NEWTYPE: TYPENAME: InvalidChildObjectArgument - 20: + 21: InvalidSharedByValue: NEWTYPE: TYPENAME: InvalidSharedByValue - 21: + 22: TooManyChildObjects: STRUCT: - object: TYPENAME: ObjectID - 22: + 23: InvalidParentDeletion: STRUCT: - parent: @@ -191,29 +210,29 @@ ExecutionFailureStatus: - kind: OPTION: TYPENAME: DeleteKind - 23: + 24: InvalidParentFreezing: STRUCT: - parent: TYPENAME: ObjectID - 24: - PublishErrorEmptyPackage: UNIT 25: - PublishErrorNonZeroAddress: UNIT + PublishErrorEmptyPackage: UNIT 26: - PublishErrorDuplicateModule: UNIT + PublishErrorNonZeroAddress: UNIT 27: - SuiMoveVerificationError: UNIT + PublishErrorDuplicateModule: UNIT 28: - MovePrimitiveRuntimeError: UNIT + SuiMoveVerificationError: UNIT 29: + MovePrimitiveRuntimeError: UNIT + 30: MoveAbort: TUPLE: - TYPENAME: ModuleId - U64 - 30: - VMVerificationOrDeserializationError: UNIT 31: + VMVerificationOrDeserializationError: UNIT + 32: VMInvariantViolation: UNIT ExecutionStatus: ENUM: diff --git a/crates/sui-types/src/messages.rs b/crates/sui-types/src/messages.rs index cbb3c008f9f52..466ef3a4c84ab 100644 --- a/crates/sui-types/src/messages.rs +++ b/crates/sui-types/src/messages.rs @@ -21,7 +21,7 @@ use byteorder::{BigEndian, ReadBytesExt}; use fastcrypto::encoding::{Base64, Encoding, Hex}; use itertools::Either; use move_binary_format::access::ModuleAccess; -use move_binary_format::file_format::LocalIndex; +use move_binary_format::file_format::{LocalIndex, TypeParameterIndex}; use move_binary_format::CompiledModule; use move_core_types::language_storage::ModuleId; use move_core_types::{ @@ -1259,6 +1259,7 @@ pub enum ExecutionFailureStatus { NonEntryFunctionInvoked, EntryTypeArityMismatch, EntryArgumentError(EntryArgumentError), + EntryTypeArgumentError(EntryTypeArgumentError), CircularObjectOwnership(CircularObjectOwnership), InvalidChildObjectArgument(InvalidChildObjectArgument), InvalidSharedByValue(InvalidSharedByValue), @@ -1309,6 +1310,20 @@ pub enum EntryArgumentErrorKind { ArityMismatch, } +#[derive(Eq, PartialEq, Clone, Copy, Debug, Serialize, Deserialize, Hash)] +pub struct EntryTypeArgumentError { + pub argument_idx: TypeParameterIndex, + pub kind: EntryTypeArgumentErrorKind, +} + +#[derive(Eq, PartialEq, Clone, Copy, Debug, Serialize, Deserialize, Hash)] +pub enum EntryTypeArgumentErrorKind { + ModuleNotFound, + TypeNotFound, + ArityMismatch, + ConstraintNotSatisfied, +} + #[derive(Eq, PartialEq, Clone, Copy, Debug, Serialize, Deserialize, Hash)] pub struct CircularObjectOwnership { pub object: ObjectID, @@ -1330,6 +1345,13 @@ impl ExecutionFailureStatus { EntryArgumentError { argument_idx, kind }.into() } + pub fn entry_type_argument_error( + argument_idx: TypeParameterIndex, + kind: EntryTypeArgumentErrorKind, + ) -> Self { + EntryTypeArgumentError { argument_idx, kind }.into() + } + pub fn circular_object_ownership(object: ObjectID) -> Self { CircularObjectOwnership { object }.into() } @@ -1400,7 +1422,10 @@ impl Display for ExecutionFailureStatus { "Number of type arguments does not match the expected value", ), ExecutionFailureStatus::EntryArgumentError(data) => { - write!(f, "Entry Argument Type Error. {data}") + write!(f, "Entry Argument Error. {data}") + } + ExecutionFailureStatus::EntryTypeArgumentError(data) => { + write!(f, "Entry Type Argument Error. {data}") } ExecutionFailureStatus::CircularObjectOwnership(data) => { write!(f, "Circular Object Ownership. {data}") @@ -1501,7 +1526,7 @@ impl Display for EntryArgumentErrorKind { ) } EntryArgumentErrorKind::ObjectKindMismatch => { - write!(f, "Mismtach with object argument kind and its actual kind.") + write!(f, "Mismatch with object argument kind and its actual kind.") } EntryArgumentErrorKind::UnsupportedPureArg => write!( f, @@ -1511,13 +1536,42 @@ impl Display for EntryArgumentErrorKind { EntryArgumentErrorKind::ArityMismatch => { write!( f, - "Mismatch between the number of actual versus expected argument." + "Mismatch between the number of actual versus expected arguments." ) } } } } +impl Display for EntryTypeArgumentError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let EntryTypeArgumentError { argument_idx, kind } = self; + write!(f, "Error for type argument at index {argument_idx}: {kind}",) + } +} + +impl Display for EntryTypeArgumentErrorKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + EntryTypeArgumentErrorKind::ModuleNotFound => write!( + f, + "A package (or module) in the type argument was not found" + ), + EntryTypeArgumentErrorKind::TypeNotFound => { + write!(f, "A type was not found in the module specified",) + } + EntryTypeArgumentErrorKind::ArityMismatch => write!( + f, + "Mismatch between the number of actual versus expected type arguments." + ), + EntryTypeArgumentErrorKind::ConstraintNotSatisfied => write!( + f, + "A type provided did not match the specified constraints." + ), + } + } +} + impl Display for CircularObjectOwnership { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let CircularObjectOwnership { object } = self; @@ -1588,6 +1642,12 @@ impl From for ExecutionFailureStatus { } } +impl From for ExecutionFailureStatus { + fn from(error: EntryTypeArgumentError) -> Self { + Self::EntryTypeArgumentError(error) + } +} + impl From for ExecutionFailureStatus { fn from(error: CircularObjectOwnership) -> Self { Self::CircularObjectOwnership(error)