1use core::convert::Infallible;
2use core::fmt;
3
4use rust_alloc::boxed::Box;
5
6use crate::alloc::error::CustomError;
7use crate::alloc::{self, String};
8use crate::runtime::unit::{BadInstruction, BadJump};
9use crate::sync::Arc;
10use crate::{vm_error, Any, Hash, Item, ItemBuf};
11
12use super::{
13 AccessError, AnyObjError, AnyObjErrorKind, AnySequenceTakeError, BoxedPanic, CallFrame,
14 DynArgsUsed, ExecutionState, Panic, Protocol, SliceError, StackError, StaticString, StoreError,
15 StoreErrorKind, TypeInfo, TypeOf, Unit, Vm, VmHaltInfo,
16};
17
18macro_rules! from_new {
19 (
20 $($ty:ty { $($from:ty),* $(,)? })*
21 ) => {
22 $($(
23 impl From<$from> for $ty {
24 #[inline]
25 fn from(error: $from) -> Self {
26 Self::new(error)
27 }
28 }
29 )*)*
30 }
31}
32
33vm_error!(VmError);
34
35pub struct VmError {
37 inner: Box<VmErrorInner>,
38}
39
40impl VmError {
41 #[inline]
42 pub(crate) fn new<E>(error: E) -> Self
43 where
44 VmErrorKind: From<E>,
45 {
46 Self {
47 inner: Box::new(VmErrorInner {
48 error: VmErrorAt {
49 #[cfg(feature = "emit")]
50 index: 0,
51 kind: VmErrorKind::from(error),
52 },
53 chain: rust_alloc::vec::Vec::new(),
54 stacktrace: rust_alloc::vec::Vec::new(),
55 }),
56 }
57 }
58
59 #[inline]
61 pub fn panic<D>(message: D) -> Self
62 where
63 D: 'static + BoxedPanic,
64 {
65 Self::from(Panic::custom(message))
66 }
67
68 #[inline]
71 pub fn expected<E>(actual: TypeInfo) -> Self
72 where
73 E: ?Sized + TypeOf,
74 {
75 Self::from(VmErrorKind::expected::<E>(actual))
76 }
77
78 #[inline]
80 pub fn at(&self) -> &VmErrorAt {
81 &self.inner.error
82 }
83
84 #[inline]
86 pub fn error(&self) -> &VmErrorAt {
87 &self.inner.error
88 }
89
90 #[inline]
92 pub fn chain(&self) -> &[VmErrorAt] {
93 &self.inner.chain
94 }
95
96 #[inline]
98 pub fn stacktrace(&self) -> &[VmErrorLocation] {
99 &self.inner.stacktrace
100 }
101
102 #[inline]
104 pub fn overflow() -> Self {
105 Self::from(VmErrorKind::Overflow)
106 }
107
108 #[inline]
110 pub fn first_location(&self) -> Option<&VmErrorLocation> {
111 self.inner.stacktrace.first()
112 }
113
114 #[inline]
115 pub(crate) fn into_kind(self) -> VmErrorKind {
116 self.inner.error.kind
117 }
118
119 pub(crate) fn with_vm<T>(result: Result<T, Self>, vm: &Vm) -> Result<T, Self> {
121 match result {
122 Ok(ok) => Ok(ok),
123 Err(mut err) => {
124 err.inner.stacktrace.push(VmErrorLocation {
125 unit: vm.unit().clone(),
126 ip: vm.last_ip(),
127 frames: vm.call_frames().to_vec(),
128 });
129
130 Err(err)
131 }
132 }
133 }
134
135 #[inline]
137 pub(crate) fn with_error<E>(mut self, error: E) -> Self
138 where
139 VmErrorKind: From<E>,
140 {
141 #[cfg(feature = "emit")]
142 let index = self.inner.stacktrace.len();
143
144 self.inner.chain.push(VmErrorAt {
145 #[cfg(feature = "emit")]
146 index,
147 kind: VmErrorKind::from(error),
148 });
149
150 self
151 }
152}
153
154impl fmt::Display for VmError {
155 #[inline]
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 self.inner.error.fmt(f)
158 }
159}
160
161impl fmt::Debug for VmError {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 f.debug_struct("VmError")
164 .field("error", &self.inner.error)
165 .field("chain", &self.inner.chain)
166 .field("stacktrace", &self.inner.stacktrace)
167 .finish()
168 }
169}
170
171impl core::error::Error for VmError {}
172
173#[derive(Debug)]
175#[non_exhaustive]
176pub struct VmErrorLocation {
177 pub unit: Arc<Unit>,
179 pub ip: usize,
181 pub frames: rust_alloc::vec::Vec<CallFrame>,
183}
184
185#[derive(Debug)]
186#[non_exhaustive]
187pub struct VmErrorAt {
188 #[cfg(feature = "emit")]
190 index: usize,
191 kind: VmErrorKind,
193}
194
195impl VmErrorAt {
196 #[cfg(feature = "emit")]
198 pub(crate) fn index(&self) -> usize {
199 self.index
200 }
201
202 #[cfg(feature = "emit")]
203 pub(crate) fn kind(&self) -> &VmErrorKind {
204 &self.kind
205 }
206}
207
208impl fmt::Display for VmErrorAt {
209 #[inline]
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 self.kind.fmt(f)
212 }
213}
214
215#[non_exhaustive]
216pub(crate) struct VmErrorInner {
217 pub(crate) error: VmErrorAt,
218 pub(crate) chain: rust_alloc::vec::Vec<VmErrorAt>,
219 pub(crate) stacktrace: rust_alloc::vec::Vec<VmErrorLocation>,
220}
221
222#[deprecated = "Use `Result<T, VmError>` directly instead."]
224pub type VmResult<T> = Result<T, VmError>;
225
226impl<E> From<E> for VmError
227where
228 VmErrorKind: From<E>,
229{
230 #[inline]
231 fn from(error: E) -> Self {
232 Self::new(error)
233 }
234}
235
236impl<E> From<CustomError<E>> for VmError
237where
238 VmError: From<E>,
239{
240 #[inline]
241 fn from(error: CustomError<E>) -> Self {
242 match error {
243 CustomError::Custom(error) => Self::from(error),
244 CustomError::Error(error) => VmError::new(error),
245 }
246 }
247}
248
249impl<const N: usize> From<[VmErrorKind; N]> for VmError {
250 fn from(kinds: [VmErrorKind; N]) -> Self {
251 let mut it = kinds.into_iter();
252
253 let Some(first) = it.next() else {
254 return VmError::panic("Cannot construct an empty collection of errors");
255 };
256
257 let mut chain = rust_alloc::vec::Vec::with_capacity(it.len());
258
259 for kind in it {
260 chain.push(VmErrorAt {
261 #[cfg(feature = "emit")]
262 index: 0,
263 kind,
264 });
265 }
266
267 Self {
268 inner: Box::new(VmErrorInner {
269 error: VmErrorAt {
270 #[cfg(feature = "emit")]
271 index: 0,
272 kind: first,
273 },
274 chain,
275 stacktrace: rust_alloc::vec::Vec::new(),
276 }),
277 }
278 }
279}
280
281impl From<Panic> for VmErrorKind {
282 #[inline]
283 fn from(reason: Panic) -> Self {
284 VmErrorKind::Panic { reason }
285 }
286}
287
288impl From<ExpectedType> for VmErrorKind {
289 #[inline]
290 fn from(expected: ExpectedType) -> Self {
291 VmErrorKind::ExpectedType {
292 expected: expected.expected,
293 actual: expected.actual,
294 }
295 }
296}
297
298pub struct ExpectedType {
300 pub(crate) expected: TypeInfo,
301 pub(crate) actual: TypeInfo,
302}
303
304impl ExpectedType {
305 pub(crate) fn new<T>(actual: TypeInfo) -> Self
307 where
308 T: ?Sized + TypeOf,
309 {
310 Self {
311 expected: T::type_info(),
312 actual,
313 }
314 }
315}
316
317vm_error!(RuntimeError);
318
319#[cfg_attr(test, derive(PartialEq))]
321pub struct RuntimeError {
322 error: Box<VmErrorKind>,
323}
324
325impl RuntimeError {
326 #[inline]
327 pub(crate) fn new<E>(error: E) -> Self
328 where
329 VmErrorKind: From<E>,
330 {
331 Self {
332 error: Box::new(VmErrorKind::from(error)),
333 }
334 }
335
336 #[inline]
337 pub(crate) fn into_vm_error_kind(self) -> VmErrorKind {
338 *self.error
339 }
340
341 #[inline]
343 pub fn panic<D>(message: D) -> Self
344 where
345 D: 'static + BoxedPanic,
346 {
347 Self::new(Panic::custom(message))
348 }
349
350 pub fn bad_argument_count(actual: usize, expected: usize) -> Self {
352 Self::new(VmErrorKind::BadArgumentCount { actual, expected })
353 }
354
355 pub fn expected<T>(actual: TypeInfo) -> Self
357 where
358 T: ?Sized + TypeOf,
359 {
360 Self::new(VmErrorKind::ExpectedType {
361 expected: T::type_info(),
362 actual,
363 })
364 }
365
366 pub(crate) fn expected_any<T>(actual: TypeInfo) -> Self
368 where
369 T: Any,
370 {
371 Self::new(VmErrorKind::ExpectedType {
372 expected: TypeInfo::any::<T>(),
373 actual,
374 })
375 }
376
377 pub(crate) fn expected_any_obj(actual: TypeInfo) -> Self {
379 Self::new(VmErrorKind::ExpectedAny { actual })
380 }
381
382 pub(crate) fn missing_constant_constructor(hash: Hash) -> Self {
384 Self::new(VmErrorKind::MissingConstantConstructor { hash })
385 }
386
387 pub(crate) fn expected_empty(actual: TypeInfo) -> Self {
388 Self::new(VmErrorKind::ExpectedEmpty { actual })
389 }
390
391 pub(crate) fn expected_tuple(actual: TypeInfo) -> Self {
392 Self::new(VmErrorKind::ExpectedTuple { actual })
393 }
394
395 pub(crate) fn expected_struct(actual: TypeInfo) -> Self {
396 Self::new(VmErrorKind::ExpectedStruct { actual })
397 }
398}
399
400impl core::error::Error for RuntimeError {}
401
402impl fmt::Display for RuntimeError {
403 #[inline]
404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405 self.error.fmt(f)
406 }
407}
408
409impl fmt::Debug for RuntimeError {
410 #[inline]
411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
412 self.error.fmt(f)
413 }
414}
415
416impl From<VmError> for RuntimeError {
417 #[inline]
418 fn from(error: VmError) -> Self {
419 Self::new(error.into_kind())
420 }
421}
422
423from_new! {
424 RuntimeError {
425 alloc::Error,
426 alloc::alloc::AllocError,
427 AccessError,
428 AnySequenceTakeError,
429 AnyObjError,
430 Infallible,
431 StackError,
432 VmErrorKind,
433 ExpectedType,
434 }
435}
436
437#[derive(Debug)]
439#[cfg_attr(test, derive(PartialEq))]
440#[doc(hidden)]
441pub(crate) enum VmErrorKind {
442 AllocError {
443 error: alloc::Error,
444 },
445 AccessError {
446 error: AccessError,
447 },
448 StackError {
449 error: StackError,
450 },
451 SliceError {
452 error: SliceError,
453 },
454 BadInstruction {
455 error: BadInstruction,
456 },
457 BadJump {
458 error: BadJump,
459 },
460 DynArgsUsed {
461 error: DynArgsUsed,
462 },
463 Panic {
464 reason: Panic,
465 },
466 NoRunningVm,
467 Halted {
468 halt: VmHaltInfo,
469 },
470 Overflow,
471 Underflow,
472 DivideByZero,
473 MissingEntry {
474 item: ItemBuf,
475 hash: Hash,
476 },
477 MissingEntryHash {
478 hash: Hash,
479 },
480 MissingFunction {
481 hash: Hash,
482 },
483 MissingContextFunction {
484 hash: Hash,
485 },
486 NotOwned {
487 type_info: TypeInfo,
488 },
489 MissingProtocolFunction {
490 protocol: &'static Protocol,
491 instance: TypeInfo,
492 },
493 MissingInstanceFunction {
494 hash: Hash,
495 instance: TypeInfo,
496 },
497 IpOutOfBounds {
498 ip: usize,
499 length: usize,
500 },
501 UnsupportedBinaryOperation {
502 op: &'static str,
503 lhs: TypeInfo,
504 rhs: TypeInfo,
505 },
506 UnsupportedUnaryOperation {
507 op: &'static str,
508 operand: TypeInfo,
509 },
510 MissingStaticString {
511 slot: usize,
512 },
513 MissingStaticBytes {
514 slot: usize,
515 },
516 MissingStaticObjectKeys {
517 slot: usize,
518 },
519 MissingDropSet {
520 set: usize,
521 },
522 MissingGlobals {
523 slot: usize,
524 name: Option<ItemBuf>,
525 },
526 BadGlobalSlot {
527 slot: usize,
528 name: Option<ItemBuf>,
529 },
530 UninitializedGlobal {
531 slot: usize,
532 name: Option<ItemBuf>,
533 },
534 MissingRtti {
535 hash: Hash,
536 },
537 BadArgumentCount {
538 actual: usize,
539 expected: usize,
540 },
541 MaxValueDepth {
547 max: usize,
548 },
549 MaxConstDepth {
555 max: usize,
556 },
557 MaxConstSize {
559 max: usize,
560 },
561 MalformedConstValue,
568 MaxExecutionDepth {
574 max: usize,
575 },
576 BadEnvironmentCount {
577 actual: usize,
578 expected: usize,
579 },
580 BadArgument {
581 arg: usize,
582 },
583 UnsupportedIndexSet {
584 target: TypeInfo,
585 index: TypeInfo,
586 value: TypeInfo,
587 },
588 UnsupportedIndexGet {
589 target: TypeInfo,
590 index: TypeInfo,
591 },
592 UnsupportedTupleIndexGet {
593 target: TypeInfo,
594 index: usize,
595 },
596 UnsupportedTupleIndexSet {
597 target: TypeInfo,
598 },
599 UnsupportedObjectSlotIndexGet {
600 target: TypeInfo,
601 field: Arc<StaticString>,
602 },
603 UnsupportedObjectSlotIndexSet {
604 target: TypeInfo,
605 field: Arc<StaticString>,
606 },
607 UnsupportedIs {
608 value: TypeInfo,
609 test_type: TypeInfo,
610 },
611 UnsupportedAs {
612 value: TypeInfo,
613 },
614 UnsupportedAsTarget {
615 value: TypeInfo,
616 },
617 UnsupportedCallFn {
618 actual: TypeInfo,
619 },
620 ObjectIndexMissing {
621 slot: usize,
622 },
623 MissingIndex {
624 target: TypeInfo,
625 },
626 MissingIndexInteger {
627 target: TypeInfo,
628 index: VmIntegerRepr,
629 },
630 MissingIndexKey {
631 target: TypeInfo,
632 },
633 OutOfRange {
634 index: VmIntegerRepr,
635 length: VmIntegerRepr,
636 },
637 UnsupportedTryOperand {
638 actual: TypeInfo,
639 },
640 UnsupportedIterRangeInclusive {
641 start: TypeInfo,
642 end: TypeInfo,
643 },
644 UnsupportedIterRangeFrom {
645 start: TypeInfo,
646 },
647 UnsupportedIterRange {
648 start: TypeInfo,
649 end: TypeInfo,
650 },
651 UnsupportedIterNextOperand {
652 actual: TypeInfo,
653 },
654 ExpectedType {
655 expected: TypeInfo,
656 actual: TypeInfo,
657 },
658 ExpectedAny {
659 actual: TypeInfo,
660 },
661 ExpectedNumber {
662 actual: TypeInfo,
663 },
664 ExpectedEmpty {
665 actual: TypeInfo,
666 },
667 ExpectedTuple {
668 actual: TypeInfo,
669 },
670 ExpectedStruct {
671 actual: TypeInfo,
672 },
673 MissingConstantConstructor {
674 hash: Hash,
675 },
676 ValueToIntegerCoercionError {
677 from: VmIntegerRepr,
678 to: &'static str,
679 },
680 IntegerToValueCoercionError {
681 from: VmIntegerRepr,
682 to: &'static str,
683 },
684 ExpectedTupleLength {
685 actual: usize,
686 expected: usize,
687 },
688 ExpectedVecLength {
689 actual: usize,
690 expected: usize,
691 },
692 ConstNotSupported {
693 actual: TypeInfo,
694 },
695 MissingInterfaceEnvironment,
696 ExpectedExitedExecutionState {
697 actual: ExecutionState,
698 },
699 GeneratorComplete,
700 FutureCompleted,
701 MissingVariant {
703 name: String,
704 },
705 MissingField {
706 target: TypeInfo,
707 field: String,
708 },
709 MissingVariantName,
710 MissingStructField {
711 target: &'static str,
712 name: &'static str,
713 },
714 MissingTupleIndex {
715 target: &'static str,
716 index: usize,
717 },
718 ExpectedVariant {
719 actual: TypeInfo,
720 },
721 UnsupportedObjectFieldGet {
722 target: TypeInfo,
723 },
724 IllegalFloatComparison {
725 lhs: f64,
726 rhs: f64,
727 },
728 IllegalFloatOperation {
729 value: f64,
730 },
731 MissingCallFrame,
732 IllegalFormat,
733}
734
735impl fmt::Display for VmErrorKind {
736 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
737 match self {
738 VmErrorKind::AllocError { error } => error.fmt(f),
739 VmErrorKind::AccessError { error } => error.fmt(f),
740 VmErrorKind::StackError { error } => error.fmt(f),
741 VmErrorKind::SliceError { error } => error.fmt(f),
742 VmErrorKind::BadInstruction { error } => error.fmt(f),
743 VmErrorKind::BadJump { error } => error.fmt(f),
744 VmErrorKind::DynArgsUsed { error } => error.fmt(f),
745 VmErrorKind::Panic { reason } => write!(f, "Panicked: {reason}"),
746 VmErrorKind::NoRunningVm => write!(f, "No running virtual machines"),
747 VmErrorKind::Halted { halt } => match halt {
752 VmHaltInfo::Limited => write!(f, "Exhausted the budget it was given"),
753 VmHaltInfo::Yielded => write!(
754 f,
755 "Yielded, but was called as if it could not - a generator has to be \
756 driven through an execution"
757 ),
758 VmHaltInfo::Awaited => write!(
759 f,
760 "Awaited, but was called as if it could not - an asynchronous function \
761 has to be called asynchronously"
762 ),
763 },
764 VmErrorKind::Overflow => write!(f, "Numerical overflow"),
765 VmErrorKind::Underflow => write!(f, "Numerical underflow"),
766 VmErrorKind::DivideByZero => write!(f, "Division by zero"),
767 VmErrorKind::MissingEntry { item, hash } => {
768 write!(f, "Missing entry `{item}` with hash `{hash}`")
769 }
770 VmErrorKind::MissingEntryHash { hash } => {
771 write!(f, "Missing entry with hash `{hash}`")
772 }
773 VmErrorKind::MissingFunction { hash } => {
774 write!(f, "Missing function with hash `{hash}`")
775 }
776 VmErrorKind::MissingContextFunction { hash } => {
777 write!(f, "Missing context function with hash `{hash}`")
778 }
779 VmErrorKind::NotOwned { type_info } => {
780 write!(f, "Cannot use owned operations for {type_info}")
781 }
782 VmErrorKind::MissingProtocolFunction { protocol, instance } => {
783 write!(f, "Missing protocol function `{protocol}` for `{instance}`")
784 }
785 VmErrorKind::MissingInstanceFunction { hash, instance } => {
786 write!(f, "Missing instance function `{hash}` for `{instance}`")
787 }
788 VmErrorKind::IpOutOfBounds { ip, length } => write!(
789 f,
790 "Instruction pointer `{ip}` is out-of-bounds `0-{length}`",
791 ),
792 VmErrorKind::UnsupportedBinaryOperation { op, lhs, rhs } => {
793 write!(
794 f,
795 "Unsupported binary operation `{op}` on `{lhs}` and `{rhs}`",
796 )
797 }
798 VmErrorKind::UnsupportedUnaryOperation { op, operand } => {
799 write!(f, "Unsupported unary operation `{op}` on {operand}")
800 }
801 VmErrorKind::MissingStaticString { slot } => {
802 write!(f, "Static string slot {slot} does not exist")
803 }
804 VmErrorKind::MissingStaticBytes { slot } => {
805 write!(f, "Static bytes slot {slot} does not exist")
806 }
807 VmErrorKind::MissingStaticObjectKeys { slot } => {
808 write!(f, "Static object keys slot {slot} does not exist")
809 }
810 VmErrorKind::MissingDropSet { set } => {
811 write!(f, "Static drop set {set} does not exist")
812 }
813 VmErrorKind::MissingGlobals { slot, name } => {
814 write!(f, "No storage has been configured for the static ")?;
815 fmt_global(f, *slot, name.as_deref())
816 }
817 VmErrorKind::BadGlobalSlot { slot, name } => {
818 write!(f, "The configured storage has no slot for the static ")?;
819 fmt_global(f, *slot, name.as_deref())
820 }
821 VmErrorKind::UninitializedGlobal { slot, name } => {
822 write!(f, "Reading uninitialized static ")?;
823 fmt_global(f, *slot, name.as_deref())
824 }
825 VmErrorKind::MissingRtti { hash } => {
826 write!(f, "Missing runtime information for type with hash `{hash}`")
827 }
828 VmErrorKind::BadArgumentCount { actual, expected } => {
829 write!(f, "Wrong number of arguments {actual}, expected {expected}",)
830 }
831 VmErrorKind::MaxValueDepth { max } => {
832 write!(f, "Value is nested too deeply to walk, limit is {max}")
833 }
834 VmErrorKind::MaxConstSize { max } => {
835 write!(f, "Value is too large to be a constant, limit is {max}")
836 }
837 VmErrorKind::MalformedConstValue => {
838 write!(f, "Constant value is not a tree")
839 }
840 VmErrorKind::MaxConstDepth { max } => {
841 write!(
842 f,
843 "Value is nested too deeply to be a constant, limit is {max}"
844 )
845 }
846 VmErrorKind::MaxExecutionDepth { max } => {
847 write!(f, "Executions are nested too deeply, limit is {max}")
848 }
849 VmErrorKind::BadEnvironmentCount { actual, expected } => write!(
850 f,
851 "Wrong environment size `{actual}`, expected `{expected}`",
852 ),
853 VmErrorKind::BadArgument { arg } => write!(f, "Bad argument #{arg}"),
854 VmErrorKind::UnsupportedIndexSet {
855 target,
856 index,
857 value,
858 } => write!(
859 f,
860 "The index set operation `{target}[{index}] = {value}` is not supported",
861 ),
862 VmErrorKind::UnsupportedIndexGet { target, index } => write!(
863 f,
864 "The index get operation `{target}[{index}]` is not supported",
865 ),
866 VmErrorKind::UnsupportedTupleIndexGet { target, index } => write!(
867 f,
868 "The tuple index get {index} operation is not supported on `{target}`",
869 ),
870 VmErrorKind::UnsupportedTupleIndexSet { target } => write!(
871 f,
872 "The tuple index set operation is not supported on `{target}`",
873 ),
874 VmErrorKind::UnsupportedObjectSlotIndexGet { target, field } => {
875 write!(f, "Field `{field}` not available on `{target}`")
876 }
877 VmErrorKind::UnsupportedObjectSlotIndexSet { target, field } => {
878 write!(f, "Field `{field}` not available to set on `{target}`")
879 }
880 VmErrorKind::UnsupportedIs { value, test_type } => {
881 write!(f, "Operation `{value} is {test_type}` is not supported")
882 }
883 VmErrorKind::UnsupportedAs { value } => write!(
884 f,
885 "Type `{value}` cannot be converted with `as`, which only converts between `i64`, `u64` and `f64`"
886 ),
887 VmErrorKind::UnsupportedAsTarget { value } => write!(
892 f,
893 "Type `{value}` cannot be converted with `as` to that type, which only converts to `i64`, `u64` or `f64`"
894 ),
895 VmErrorKind::UnsupportedCallFn { actual } => write!(
896 f,
897 "Type `{actual}` cannot be called since it's not a function",
898 ),
899 VmErrorKind::ObjectIndexMissing { slot } => {
900 write!(f, "Missing index by static string slot `{slot}`")
901 }
902 VmErrorKind::MissingIndex { target } => {
903 write!(f, "Type `{target}` missing index")
904 }
905 VmErrorKind::MissingIndexInteger { target, index } => {
906 write!(f, "Type `{target}` missing integer index `{index}`")
907 }
908 VmErrorKind::MissingIndexKey { target } => {
909 write!(f, "Type `{target}` missing index")
910 }
911 VmErrorKind::OutOfRange { index, length } => write!(
912 f,
913 "Index out of bounds, the length is `{length}` but the index is `{index}`",
914 ),
915 VmErrorKind::UnsupportedTryOperand { actual } => {
916 write!(f, "Type `{actual}` is not supported as try operand")
917 }
918 VmErrorKind::UnsupportedIterRangeInclusive { start, end } => {
919 write!(f, "Cannot build an iterator out of {start}..={end}")
920 }
921 VmErrorKind::UnsupportedIterRangeFrom { start } => {
922 write!(f, "Cannot build an iterator out of {start}..")
923 }
924 VmErrorKind::UnsupportedIterRange { start, end } => {
925 write!(f, "Cannot build an iterator out of {start}..{end}")
926 }
927 VmErrorKind::UnsupportedIterNextOperand { actual } => {
928 write!(f, "Type `{actual}` is not supported as iter-next operand")
929 }
930 VmErrorKind::ExpectedType { expected, actual } => {
931 write!(f, "Expected type `{expected}` but found `{actual}`")
932 }
933 VmErrorKind::ExpectedAny { actual } => {
934 write!(f, "Expected `Any` type, but found `{actual}`")
935 }
936 VmErrorKind::ExpectedNumber { actual } => {
937 write!(f, "Expected number type, but found `{actual}`")
938 }
939 VmErrorKind::ExpectedEmpty { actual } => {
940 write!(f, "Expected empty, but found `{actual}`")
941 }
942 VmErrorKind::ExpectedTuple { actual } => {
943 write!(f, "Expected tuple, but found `{actual}`")
944 }
945 VmErrorKind::ExpectedStruct { actual } => {
946 write!(f, "Expected struct, but found `{actual}`")
947 }
948 VmErrorKind::MissingConstantConstructor { hash } => {
949 write!(f, "Missing constant constructor for type with hash {hash}")
950 }
951 VmErrorKind::ValueToIntegerCoercionError { from, to } => {
952 write!(f, "Failed to convert value `{from}` to integer `{to}`")
953 }
954 VmErrorKind::IntegerToValueCoercionError { from, to } => {
955 write!(f, "Failed to convert integer `{from}` to value `{to}`")
956 }
957 VmErrorKind::ExpectedTupleLength { actual, expected } => write!(
958 f,
959 "Expected a tuple of length `{expected}`, but found one with length `{actual}`",
960 ),
961 VmErrorKind::ExpectedVecLength { actual, expected } => write!(
962 f,
963 "Expected a vector of length `{expected}`, but found one with length `{actual}`",
964 ),
965 VmErrorKind::ConstNotSupported { actual } => {
966 write!(f, "Type `{actual}` can't be converted to a constant value")
967 }
968 VmErrorKind::MissingInterfaceEnvironment => {
969 write!(f, "Missing interface environment")
970 }
971 VmErrorKind::ExpectedExitedExecutionState { actual } => {
972 write!(f, "Expected exited execution state, but was {actual}")
973 }
974 VmErrorKind::GeneratorComplete => {
975 write!(f, "Cannot resume a generator that has completed")
976 }
977 VmErrorKind::FutureCompleted => write!(f, "Future already completed"),
978 VmErrorKind::MissingVariant { name } => write!(f, "No variant matching `{name}`"),
979 VmErrorKind::MissingField { target, field } => {
980 write!(f, "Missing field `{field}` on `{target}`")
981 }
982 VmErrorKind::MissingVariantName => {
983 write!(f, "missing variant name in runtime information")
984 }
985 VmErrorKind::MissingStructField { target, name } => write!(
986 f,
987 "missing dynamic field for struct field `{target}::{name}`",
988 ),
989 VmErrorKind::MissingTupleIndex { target, index } => write!(
990 f,
991 "missing dynamic index #{index} in tuple struct `{target}`",
992 ),
993 VmErrorKind::ExpectedVariant { actual } => {
994 write!(f, "Expected an enum variant, but got `{actual}`")
995 }
996 VmErrorKind::UnsupportedObjectFieldGet { target } => write!(
997 f,
998 "The object field get operation is not supported on `{target}`",
999 ),
1000 VmErrorKind::IllegalFloatComparison { lhs, rhs } => {
1001 write!(
1002 f,
1003 "Cannot perform a comparison of the floats {lhs} and {rhs}",
1004 )
1005 }
1006 VmErrorKind::IllegalFloatOperation { value } => {
1007 write!(f, "Cannot perform operation on float `{value}`")
1008 }
1009 VmErrorKind::MissingCallFrame => {
1010 write!(f, "Missing call frame for internal vm call")
1011 }
1012 VmErrorKind::IllegalFormat => {
1013 write!(f, "Value cannot be formatted")
1014 }
1015 }
1016 }
1017}
1018
1019impl From<Infallible> for VmErrorKind {
1020 #[inline]
1021 fn from(error: Infallible) -> Self {
1022 match error {}
1023 }
1024}
1025
1026impl<E> From<StoreError<E>> for VmErrorKind
1027where
1028 VmErrorKind: From<E>,
1029{
1030 #[inline]
1031 fn from(value: StoreError<E>) -> Self {
1032 match value.into_kind() {
1033 StoreErrorKind::Stack(error) => VmErrorKind::StackError { error },
1034 StoreErrorKind::Error(error) => VmErrorKind::from(error),
1035 StoreErrorKind::Alloc(error) => VmErrorKind::AllocError { error },
1036 }
1037 }
1038}
1039
1040impl From<RuntimeError> for VmErrorKind {
1041 #[inline]
1042 fn from(value: RuntimeError) -> Self {
1043 value.into_vm_error_kind()
1044 }
1045}
1046
1047impl From<AnySequenceTakeError> for VmErrorKind {
1048 #[inline]
1049 fn from(value: AnySequenceTakeError) -> Self {
1050 match value {
1051 AnySequenceTakeError::Access(error) => Self::from(error),
1052 AnySequenceTakeError::Alloc(error) => Self::from(error),
1053 }
1054 }
1055}
1056
1057impl From<AnyObjError> for VmErrorKind {
1058 #[inline]
1059 fn from(value: AnyObjError) -> Self {
1060 match value.into_kind() {
1061 AnyObjErrorKind::Alloc(error) => Self::from(error),
1062 AnyObjErrorKind::Cast(expected, actual) => VmErrorKind::ExpectedType {
1063 expected: TypeInfo::any_type_info(expected),
1064 actual,
1065 },
1066 AnyObjErrorKind::AccessError(error) => Self::from(error),
1067 AnyObjErrorKind::NotOwned(type_info) => VmErrorKind::NotOwned { type_info },
1068 }
1069 }
1070}
1071
1072impl From<AccessError> for VmErrorKind {
1073 #[inline]
1074 fn from(error: AccessError) -> Self {
1075 VmErrorKind::AccessError { error }
1076 }
1077}
1078
1079impl From<StackError> for VmErrorKind {
1080 #[inline]
1081 fn from(error: StackError) -> Self {
1082 VmErrorKind::StackError { error }
1083 }
1084}
1085
1086impl From<SliceError> for VmErrorKind {
1087 #[inline]
1088 fn from(error: SliceError) -> Self {
1089 VmErrorKind::SliceError { error }
1090 }
1091}
1092
1093impl From<BadInstruction> for VmErrorKind {
1094 #[inline]
1095 fn from(error: BadInstruction) -> Self {
1096 VmErrorKind::BadInstruction { error }
1097 }
1098}
1099
1100impl From<BadJump> for VmErrorKind {
1101 #[inline]
1102 fn from(error: BadJump) -> Self {
1103 VmErrorKind::BadJump { error }
1104 }
1105}
1106
1107impl From<DynArgsUsed> for VmErrorKind {
1108 #[inline]
1109 fn from(error: DynArgsUsed) -> Self {
1110 VmErrorKind::DynArgsUsed { error }
1111 }
1112}
1113
1114impl From<alloc::Error> for VmErrorKind {
1115 #[inline]
1116 fn from(error: alloc::Error) -> Self {
1117 VmErrorKind::AllocError { error }
1118 }
1119}
1120
1121impl From<alloc::alloc::AllocError> for VmErrorKind {
1122 #[inline]
1123 fn from(error: alloc::alloc::AllocError) -> Self {
1124 VmErrorKind::AllocError {
1125 error: error.into(),
1126 }
1127 }
1128}
1129
1130impl VmErrorKind {
1131 pub(crate) fn bad_argument(arg: usize) -> Self {
1133 Self::BadArgument { arg }
1134 }
1135
1136 pub(crate) fn expected<T>(actual: TypeInfo) -> Self
1138 where
1139 T: ?Sized + TypeOf,
1140 {
1141 Self::ExpectedType {
1142 expected: T::type_info(),
1143 actual,
1144 }
1145 }
1146}
1147
1148#[derive(Debug, Clone, Copy)]
1149#[cfg_attr(test, derive(PartialEq))]
1150enum VmIntegerReprKind {
1151 Signed(i128),
1152 Unsigned(u128),
1153 Isize(isize),
1154 Usize(usize),
1155}
1156
1157#[derive(Clone)]
1159#[cfg_attr(test, derive(PartialEq))]
1160pub(crate) struct VmIntegerRepr {
1161 kind: VmIntegerReprKind,
1162}
1163
1164impl VmIntegerRepr {
1165 #[inline]
1166 fn new(kind: VmIntegerReprKind) -> Self {
1167 Self { kind }
1168 }
1169}
1170
1171macro_rules! impl_from {
1172 ($($variant:ident => [$($ty:ty),* $(,)?]),* $(,)?) => {
1173 $($(
1174 impl From<$ty> for VmIntegerRepr {
1175 #[inline]
1176 fn from(value: $ty) -> Self {
1177 Self::new(VmIntegerReprKind::$variant(From::from(value)))
1178 }
1179 }
1180 )*)*
1181 };
1182}
1183
1184impl_from! {
1185 Signed => [i8, i16, i32, i64, i128],
1186 Unsigned => [u8, u16, u32, u64, u128],
1187 Isize => [isize],
1188 Usize => [usize],
1189}
1190
1191impl fmt::Display for VmIntegerRepr {
1192 #[inline]
1193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1194 match &self.kind {
1195 VmIntegerReprKind::Signed(value) => value.fmt(f),
1196 VmIntegerReprKind::Unsigned(value) => value.fmt(f),
1197 VmIntegerReprKind::Isize(value) => value.fmt(f),
1198 VmIntegerReprKind::Usize(value) => value.fmt(f),
1199 }
1200 }
1201}
1202
1203impl fmt::Debug for VmIntegerRepr {
1204 #[inline]
1205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1206 self.kind.fmt(f)
1207 }
1208}
1209
1210fn fmt_global(f: &mut fmt::Formatter<'_>, slot: usize, name: Option<&Item>) -> fmt::Result {
1213 match name {
1214 Some(name) => write!(f, "`{name}` (slot {slot})"),
1215 None => write!(f, "in slot {slot}"),
1216 }
1217}