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
423impl From<Infallible> for RuntimeError {
424 #[inline]
425 fn from(error: Infallible) -> Self {
426 match error {}
427 }
428}
429
430from_new! {
431 RuntimeError {
432 alloc::Error,
433 alloc::alloc::AllocError,
434 AccessError,
435 AnySequenceTakeError,
436 AnyObjError,
437 StackError,
438 VmErrorKind,
439 ExpectedType,
440 }
441}
442
443#[derive(Debug)]
445#[cfg_attr(test, derive(PartialEq))]
446#[doc(hidden)]
447pub(crate) enum VmErrorKind {
448 AllocError {
449 error: alloc::Error,
450 },
451 AccessError {
452 error: AccessError,
453 },
454 StackError {
455 error: StackError,
456 },
457 SliceError {
458 error: SliceError,
459 },
460 BadInstruction {
461 error: BadInstruction,
462 },
463 BadJump {
464 error: BadJump,
465 },
466 DynArgsUsed {
467 error: DynArgsUsed,
468 },
469 Panic {
470 reason: Panic,
471 },
472 NoRunningVm,
473 Halted {
474 halt: VmHaltInfo,
475 },
476 Overflow,
477 Underflow,
478 DivideByZero,
479 MissingEntry {
480 item: ItemBuf,
481 hash: Hash,
482 },
483 MissingEntryHash {
484 hash: Hash,
485 },
486 MissingFunction {
487 hash: Hash,
488 },
489 MissingContextFunction {
490 hash: Hash,
491 },
492 NotOwned {
493 type_info: TypeInfo,
494 },
495 MissingProtocolFunction {
496 protocol: &'static Protocol,
497 instance: TypeInfo,
498 },
499 MissingInstanceFunction {
500 hash: Hash,
501 instance: TypeInfo,
502 },
503 IpOutOfBounds {
504 ip: usize,
505 length: usize,
506 },
507 UnsupportedBinaryOperation {
508 op: &'static str,
509 lhs: TypeInfo,
510 rhs: TypeInfo,
511 },
512 UnsupportedUnaryOperation {
513 op: &'static str,
514 operand: TypeInfo,
515 },
516 MissingStaticString {
517 slot: usize,
518 },
519 MissingStaticBytes {
520 slot: usize,
521 },
522 MissingStaticObjectKeys {
523 slot: usize,
524 },
525 MissingDropSet {
526 set: usize,
527 },
528 MissingGlobals {
529 slot: usize,
530 name: Option<ItemBuf>,
531 },
532 BadGlobalSlot {
533 slot: usize,
534 name: Option<ItemBuf>,
535 },
536 UninitializedGlobal {
537 slot: usize,
538 name: Option<ItemBuf>,
539 },
540 MissingRtti {
541 hash: Hash,
542 },
543 BadArgumentCount {
544 actual: usize,
545 expected: usize,
546 },
547 MaxValueDepth {
553 max: usize,
554 },
555 MaxConstDepth {
561 max: usize,
562 },
563 MaxConstSize {
565 max: usize,
566 },
567 MalformedConstValue,
574 MaxExecutionDepth {
580 max: usize,
581 },
582 BadEnvironmentCount {
583 actual: usize,
584 expected: usize,
585 },
586 BadArgument {
587 arg: usize,
588 },
589 UnsupportedIndexSet {
590 target: TypeInfo,
591 index: TypeInfo,
592 value: TypeInfo,
593 },
594 UnsupportedIndexGet {
595 target: TypeInfo,
596 index: TypeInfo,
597 },
598 UnsupportedTupleIndexGet {
599 target: TypeInfo,
600 index: usize,
601 },
602 UnsupportedTupleIndexSet {
603 target: TypeInfo,
604 },
605 UnsupportedObjectSlotIndexGet {
606 target: TypeInfo,
607 field: Arc<StaticString>,
608 },
609 UnsupportedObjectSlotIndexSet {
610 target: TypeInfo,
611 field: Arc<StaticString>,
612 },
613 UnsupportedIs {
614 value: TypeInfo,
615 test_type: TypeInfo,
616 },
617 UnsupportedAs {
618 value: TypeInfo,
619 },
620 UnsupportedAsTarget {
621 value: TypeInfo,
622 },
623 UnsupportedCallFn {
624 actual: TypeInfo,
625 },
626 ObjectIndexMissing {
627 slot: usize,
628 },
629 MissingIndex {
630 target: TypeInfo,
631 },
632 MissingIndexInteger {
633 target: TypeInfo,
634 index: VmIntegerRepr,
635 },
636 MissingIndexKey {
637 target: TypeInfo,
638 },
639 OutOfRange {
640 index: VmIntegerRepr,
641 length: VmIntegerRepr,
642 },
643 UnsupportedTryOperand {
644 actual: TypeInfo,
645 },
646 UnsupportedIterRangeInclusive {
647 start: TypeInfo,
648 end: TypeInfo,
649 },
650 UnsupportedIterRangeFrom {
651 start: TypeInfo,
652 },
653 UnsupportedIterRange {
654 start: TypeInfo,
655 end: TypeInfo,
656 },
657 UnsupportedIterNextOperand {
658 actual: TypeInfo,
659 },
660 ExpectedType {
661 expected: TypeInfo,
662 actual: TypeInfo,
663 },
664 ExpectedAny {
665 actual: TypeInfo,
666 },
667 ExpectedNumber {
668 actual: TypeInfo,
669 },
670 ExpectedEmpty {
671 actual: TypeInfo,
672 },
673 ExpectedTuple {
674 actual: TypeInfo,
675 },
676 ExpectedStruct {
677 actual: TypeInfo,
678 },
679 MissingConstantConstructor {
680 hash: Hash,
681 },
682 ValueToIntegerCoercionError {
683 from: VmIntegerRepr,
684 to: &'static str,
685 },
686 IntegerToValueCoercionError {
687 from: VmIntegerRepr,
688 to: &'static str,
689 },
690 ExpectedTupleLength {
691 actual: usize,
692 expected: usize,
693 },
694 ExpectedVecLength {
695 actual: usize,
696 expected: usize,
697 },
698 ConstNotSupported {
699 actual: TypeInfo,
700 },
701 MissingInterfaceEnvironment,
702 ExpectedExitedExecutionState {
703 actual: ExecutionState,
704 },
705 GeneratorComplete,
706 FutureCompleted,
707 MissingVariant {
709 name: String,
710 },
711 MissingField {
712 target: TypeInfo,
713 field: String,
714 },
715 MissingVariantName,
716 MissingStructField {
717 target: &'static str,
718 name: &'static str,
719 },
720 MissingTupleIndex {
721 target: &'static str,
722 index: usize,
723 },
724 ExpectedVariant {
725 actual: TypeInfo,
726 },
727 UnsupportedObjectFieldGet {
728 target: TypeInfo,
729 },
730 IllegalFloatComparison {
731 lhs: f64,
732 rhs: f64,
733 },
734 IllegalFloatOperation {
735 value: f64,
736 },
737 MissingCallFrame,
738 IllegalFormat,
739}
740
741impl fmt::Display for VmErrorKind {
742 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
743 match self {
744 VmErrorKind::AllocError { error } => error.fmt(f),
745 VmErrorKind::AccessError { error } => error.fmt(f),
746 VmErrorKind::StackError { error } => error.fmt(f),
747 VmErrorKind::SliceError { error } => error.fmt(f),
748 VmErrorKind::BadInstruction { error } => error.fmt(f),
749 VmErrorKind::BadJump { error } => error.fmt(f),
750 VmErrorKind::DynArgsUsed { error } => error.fmt(f),
751 VmErrorKind::Panic { reason } => write!(f, "Panicked: {reason}"),
752 VmErrorKind::NoRunningVm => write!(f, "No running virtual machines"),
753 VmErrorKind::Halted { halt } => match halt {
758 VmHaltInfo::Limited => write!(f, "Exhausted the budget it was given"),
759 VmHaltInfo::Yielded => write!(
760 f,
761 "Yielded, but was called as if it could not - a generator has to be \
762 driven through an execution"
763 ),
764 VmHaltInfo::Awaited => write!(
765 f,
766 "Awaited, but was called as if it could not - an asynchronous function \
767 has to be called asynchronously"
768 ),
769 },
770 VmErrorKind::Overflow => write!(f, "Numerical overflow"),
771 VmErrorKind::Underflow => write!(f, "Numerical underflow"),
772 VmErrorKind::DivideByZero => write!(f, "Division by zero"),
773 VmErrorKind::MissingEntry { item, hash } => {
774 write!(f, "Missing entry `{item}` with hash `{hash}`")
775 }
776 VmErrorKind::MissingEntryHash { hash } => {
777 write!(f, "Missing entry with hash `{hash}`")
778 }
779 VmErrorKind::MissingFunction { hash } => {
780 write!(f, "Missing function with hash `{hash}`")
781 }
782 VmErrorKind::MissingContextFunction { hash } => {
783 write!(f, "Missing context function with hash `{hash}`")
784 }
785 VmErrorKind::NotOwned { type_info } => {
786 write!(f, "Cannot use owned operations for {type_info}")
787 }
788 VmErrorKind::MissingProtocolFunction { protocol, instance } => {
789 write!(f, "Missing protocol function `{protocol}` for `{instance}`")
790 }
791 VmErrorKind::MissingInstanceFunction { hash, instance } => {
792 write!(f, "Missing instance function `{hash}` for `{instance}`")
793 }
794 VmErrorKind::IpOutOfBounds { ip, length } => write!(
795 f,
796 "Instruction pointer `{ip}` is out-of-bounds `0-{length}`",
797 ),
798 VmErrorKind::UnsupportedBinaryOperation { op, lhs, rhs } => {
799 write!(
800 f,
801 "Unsupported binary operation `{op}` on `{lhs}` and `{rhs}`",
802 )
803 }
804 VmErrorKind::UnsupportedUnaryOperation { op, operand } => {
805 write!(f, "Unsupported unary operation `{op}` on {operand}")
806 }
807 VmErrorKind::MissingStaticString { slot } => {
808 write!(f, "Static string slot {slot} does not exist")
809 }
810 VmErrorKind::MissingStaticBytes { slot } => {
811 write!(f, "Static bytes slot {slot} does not exist")
812 }
813 VmErrorKind::MissingStaticObjectKeys { slot } => {
814 write!(f, "Static object keys slot {slot} does not exist")
815 }
816 VmErrorKind::MissingDropSet { set } => {
817 write!(f, "Static drop set {set} does not exist")
818 }
819 VmErrorKind::MissingGlobals { slot, name } => {
820 write!(f, "No storage has been configured for the static ")?;
821 fmt_global(f, *slot, name.as_deref())
822 }
823 VmErrorKind::BadGlobalSlot { slot, name } => {
824 write!(f, "The configured storage has no slot for the static ")?;
825 fmt_global(f, *slot, name.as_deref())
826 }
827 VmErrorKind::UninitializedGlobal { slot, name } => {
828 write!(f, "Reading uninitialized static ")?;
829 fmt_global(f, *slot, name.as_deref())
830 }
831 VmErrorKind::MissingRtti { hash } => {
832 write!(f, "Missing runtime information for type with hash `{hash}`")
833 }
834 VmErrorKind::BadArgumentCount { actual, expected } => {
835 write!(f, "Wrong number of arguments {actual}, expected {expected}",)
836 }
837 VmErrorKind::MaxValueDepth { max } => {
838 write!(f, "Value is nested too deeply to walk, limit is {max}")
839 }
840 VmErrorKind::MaxConstSize { max } => {
841 write!(f, "Value is too large to be a constant, limit is {max}")
842 }
843 VmErrorKind::MalformedConstValue => {
844 write!(f, "Constant value is not a tree")
845 }
846 VmErrorKind::MaxConstDepth { max } => {
847 write!(
848 f,
849 "Value is nested too deeply to be a constant, limit is {max}"
850 )
851 }
852 VmErrorKind::MaxExecutionDepth { max } => {
853 write!(f, "Executions are nested too deeply, limit is {max}")
854 }
855 VmErrorKind::BadEnvironmentCount { actual, expected } => write!(
856 f,
857 "Wrong environment size `{actual}`, expected `{expected}`",
858 ),
859 VmErrorKind::BadArgument { arg } => write!(f, "Bad argument #{arg}"),
860 VmErrorKind::UnsupportedIndexSet {
861 target,
862 index,
863 value,
864 } => write!(
865 f,
866 "The index set operation `{target}[{index}] = {value}` is not supported",
867 ),
868 VmErrorKind::UnsupportedIndexGet { target, index } => write!(
869 f,
870 "The index get operation `{target}[{index}]` is not supported",
871 ),
872 VmErrorKind::UnsupportedTupleIndexGet { target, index } => write!(
873 f,
874 "The tuple index get {index} operation is not supported on `{target}`",
875 ),
876 VmErrorKind::UnsupportedTupleIndexSet { target } => write!(
877 f,
878 "The tuple index set operation is not supported on `{target}`",
879 ),
880 VmErrorKind::UnsupportedObjectSlotIndexGet { target, field } => {
881 write!(f, "Field `{field}` not available on `{target}`")
882 }
883 VmErrorKind::UnsupportedObjectSlotIndexSet { target, field } => {
884 write!(f, "Field `{field}` not available to set on `{target}`")
885 }
886 VmErrorKind::UnsupportedIs { value, test_type } => {
887 write!(f, "Operation `{value} is {test_type}` is not supported")
888 }
889 VmErrorKind::UnsupportedAs { value } => write!(
890 f,
891 "Type `{value}` cannot be converted with `as`, which only converts between `i64`, `u64` and `f64`"
892 ),
893 VmErrorKind::UnsupportedAsTarget { value } => write!(
898 f,
899 "Type `{value}` cannot be converted with `as` to that type, which only converts to `i64`, `u64` or `f64`"
900 ),
901 VmErrorKind::UnsupportedCallFn { actual } => write!(
902 f,
903 "Type `{actual}` cannot be called since it's not a function",
904 ),
905 VmErrorKind::ObjectIndexMissing { slot } => {
906 write!(f, "Missing index by static string slot `{slot}`")
907 }
908 VmErrorKind::MissingIndex { target } => {
909 write!(f, "Type `{target}` missing index")
910 }
911 VmErrorKind::MissingIndexInteger { target, index } => {
912 write!(f, "Type `{target}` missing integer index `{index}`")
913 }
914 VmErrorKind::MissingIndexKey { target } => {
915 write!(f, "Type `{target}` missing index")
916 }
917 VmErrorKind::OutOfRange { index, length } => write!(
918 f,
919 "Index out of bounds, the length is `{length}` but the index is `{index}`",
920 ),
921 VmErrorKind::UnsupportedTryOperand { actual } => {
922 write!(f, "Type `{actual}` is not supported as try operand")
923 }
924 VmErrorKind::UnsupportedIterRangeInclusive { start, end } => {
925 write!(f, "Cannot build an iterator out of {start}..={end}")
926 }
927 VmErrorKind::UnsupportedIterRangeFrom { start } => {
928 write!(f, "Cannot build an iterator out of {start}..")
929 }
930 VmErrorKind::UnsupportedIterRange { start, end } => {
931 write!(f, "Cannot build an iterator out of {start}..{end}")
932 }
933 VmErrorKind::UnsupportedIterNextOperand { actual } => {
934 write!(f, "Type `{actual}` is not supported as iter-next operand")
935 }
936 VmErrorKind::ExpectedType { expected, actual } => {
937 write!(f, "Expected type `{expected}` but found `{actual}`")
938 }
939 VmErrorKind::ExpectedAny { actual } => {
940 write!(f, "Expected `Any` type, but found `{actual}`")
941 }
942 VmErrorKind::ExpectedNumber { actual } => {
943 write!(f, "Expected number type, but found `{actual}`")
944 }
945 VmErrorKind::ExpectedEmpty { actual } => {
946 write!(f, "Expected empty, but found `{actual}`")
947 }
948 VmErrorKind::ExpectedTuple { actual } => {
949 write!(f, "Expected tuple, but found `{actual}`")
950 }
951 VmErrorKind::ExpectedStruct { actual } => {
952 write!(f, "Expected struct, but found `{actual}`")
953 }
954 VmErrorKind::MissingConstantConstructor { hash } => {
955 write!(f, "Missing constant constructor for type with hash {hash}")
956 }
957 VmErrorKind::ValueToIntegerCoercionError { from, to } => {
958 write!(f, "Failed to convert value `{from}` to integer `{to}`")
959 }
960 VmErrorKind::IntegerToValueCoercionError { from, to } => {
961 write!(f, "Failed to convert integer `{from}` to value `{to}`")
962 }
963 VmErrorKind::ExpectedTupleLength { actual, expected } => write!(
964 f,
965 "Expected a tuple of length `{expected}`, but found one with length `{actual}`",
966 ),
967 VmErrorKind::ExpectedVecLength { actual, expected } => write!(
968 f,
969 "Expected a vector of length `{expected}`, but found one with length `{actual}`",
970 ),
971 VmErrorKind::ConstNotSupported { actual } => {
972 write!(f, "Type `{actual}` can't be converted to a constant value")
973 }
974 VmErrorKind::MissingInterfaceEnvironment => {
975 write!(f, "Missing interface environment")
976 }
977 VmErrorKind::ExpectedExitedExecutionState { actual } => {
978 write!(f, "Expected exited execution state, but was {actual}")
979 }
980 VmErrorKind::GeneratorComplete => {
981 write!(f, "Cannot resume a generator that has completed")
982 }
983 VmErrorKind::FutureCompleted => write!(f, "Future already completed"),
984 VmErrorKind::MissingVariant { name } => write!(f, "No variant matching `{name}`"),
985 VmErrorKind::MissingField { target, field } => {
986 write!(f, "Missing field `{field}` on `{target}`")
987 }
988 VmErrorKind::MissingVariantName => {
989 write!(f, "missing variant name in runtime information")
990 }
991 VmErrorKind::MissingStructField { target, name } => write!(
992 f,
993 "missing dynamic field for struct field `{target}::{name}`",
994 ),
995 VmErrorKind::MissingTupleIndex { target, index } => write!(
996 f,
997 "missing dynamic index #{index} in tuple struct `{target}`",
998 ),
999 VmErrorKind::ExpectedVariant { actual } => {
1000 write!(f, "Expected an enum variant, but got `{actual}`")
1001 }
1002 VmErrorKind::UnsupportedObjectFieldGet { target } => write!(
1003 f,
1004 "The object field get operation is not supported on `{target}`",
1005 ),
1006 VmErrorKind::IllegalFloatComparison { lhs, rhs } => {
1007 write!(
1008 f,
1009 "Cannot perform a comparison of the floats {lhs} and {rhs}",
1010 )
1011 }
1012 VmErrorKind::IllegalFloatOperation { value } => {
1013 write!(f, "Cannot perform operation on float `{value}`")
1014 }
1015 VmErrorKind::MissingCallFrame => {
1016 write!(f, "Missing call frame for internal vm call")
1017 }
1018 VmErrorKind::IllegalFormat => {
1019 write!(f, "Value cannot be formatted")
1020 }
1021 }
1022 }
1023}
1024
1025impl From<Infallible> for VmErrorKind {
1026 #[inline]
1027 fn from(error: Infallible) -> Self {
1028 match error {}
1029 }
1030}
1031
1032impl<E> From<StoreError<E>> for VmErrorKind
1033where
1034 VmErrorKind: From<E>,
1035{
1036 #[inline]
1037 fn from(value: StoreError<E>) -> Self {
1038 match value.into_kind() {
1039 StoreErrorKind::Stack(error) => VmErrorKind::StackError { error },
1040 StoreErrorKind::Error(error) => VmErrorKind::from(error),
1041 StoreErrorKind::Alloc(error) => VmErrorKind::AllocError { error },
1042 }
1043 }
1044}
1045
1046impl From<RuntimeError> for VmErrorKind {
1047 #[inline]
1048 fn from(value: RuntimeError) -> Self {
1049 value.into_vm_error_kind()
1050 }
1051}
1052
1053impl From<AnySequenceTakeError> for VmErrorKind {
1054 #[inline]
1055 fn from(value: AnySequenceTakeError) -> Self {
1056 match value {
1057 AnySequenceTakeError::Access(error) => Self::from(error),
1058 AnySequenceTakeError::Alloc(error) => Self::from(error),
1059 }
1060 }
1061}
1062
1063impl From<AnyObjError> for VmErrorKind {
1064 #[inline]
1065 fn from(value: AnyObjError) -> Self {
1066 match value.into_kind() {
1067 AnyObjErrorKind::Alloc(error) => Self::from(error),
1068 AnyObjErrorKind::Cast(expected, actual) => VmErrorKind::ExpectedType {
1069 expected: TypeInfo::any_type_info(expected),
1070 actual,
1071 },
1072 AnyObjErrorKind::AccessError(error) => Self::from(error),
1073 AnyObjErrorKind::NotOwned(type_info) => VmErrorKind::NotOwned { type_info },
1074 }
1075 }
1076}
1077
1078impl From<AccessError> for VmErrorKind {
1079 #[inline]
1080 fn from(error: AccessError) -> Self {
1081 VmErrorKind::AccessError { error }
1082 }
1083}
1084
1085impl From<StackError> for VmErrorKind {
1086 #[inline]
1087 fn from(error: StackError) -> Self {
1088 VmErrorKind::StackError { error }
1089 }
1090}
1091
1092impl From<SliceError> for VmErrorKind {
1093 #[inline]
1094 fn from(error: SliceError) -> Self {
1095 VmErrorKind::SliceError { error }
1096 }
1097}
1098
1099impl From<BadInstruction> for VmErrorKind {
1100 #[inline]
1101 fn from(error: BadInstruction) -> Self {
1102 VmErrorKind::BadInstruction { error }
1103 }
1104}
1105
1106impl From<BadJump> for VmErrorKind {
1107 #[inline]
1108 fn from(error: BadJump) -> Self {
1109 VmErrorKind::BadJump { error }
1110 }
1111}
1112
1113impl From<DynArgsUsed> for VmErrorKind {
1114 #[inline]
1115 fn from(error: DynArgsUsed) -> Self {
1116 VmErrorKind::DynArgsUsed { error }
1117 }
1118}
1119
1120impl From<alloc::Error> for VmErrorKind {
1121 #[inline]
1122 fn from(error: alloc::Error) -> Self {
1123 VmErrorKind::AllocError { error }
1124 }
1125}
1126
1127impl From<alloc::alloc::AllocError> for VmErrorKind {
1128 #[inline]
1129 fn from(error: alloc::alloc::AllocError) -> Self {
1130 VmErrorKind::AllocError {
1131 error: error.into(),
1132 }
1133 }
1134}
1135
1136impl VmErrorKind {
1137 pub(crate) fn bad_argument(arg: usize) -> Self {
1139 Self::BadArgument { arg }
1140 }
1141
1142 pub(crate) fn expected<T>(actual: TypeInfo) -> Self
1144 where
1145 T: ?Sized + TypeOf,
1146 {
1147 Self::ExpectedType {
1148 expected: T::type_info(),
1149 actual,
1150 }
1151 }
1152}
1153
1154#[derive(Debug, Clone, Copy)]
1155#[cfg_attr(test, derive(PartialEq))]
1156enum VmIntegerReprKind {
1157 Signed(i128),
1158 Unsigned(u128),
1159 Isize(isize),
1160 Usize(usize),
1161}
1162
1163#[derive(Clone)]
1165#[cfg_attr(test, derive(PartialEq))]
1166pub(crate) struct VmIntegerRepr {
1167 kind: VmIntegerReprKind,
1168}
1169
1170impl VmIntegerRepr {
1171 #[inline]
1172 fn new(kind: VmIntegerReprKind) -> Self {
1173 Self { kind }
1174 }
1175}
1176
1177macro_rules! impl_from {
1178 ($($variant:ident => [$($ty:ty),* $(,)?]),* $(,)?) => {
1179 $($(
1180 impl From<$ty> for VmIntegerRepr {
1181 #[inline]
1182 fn from(value: $ty) -> Self {
1183 Self::new(VmIntegerReprKind::$variant(From::from(value)))
1184 }
1185 }
1186 )*)*
1187 };
1188}
1189
1190impl_from! {
1191 Signed => [i8, i16, i32, i64, i128],
1192 Unsigned => [u8, u16, u32, u64, u128],
1193 Isize => [isize],
1194 Usize => [usize],
1195}
1196
1197impl fmt::Display for VmIntegerRepr {
1198 #[inline]
1199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1200 match &self.kind {
1201 VmIntegerReprKind::Signed(value) => value.fmt(f),
1202 VmIntegerReprKind::Unsigned(value) => value.fmt(f),
1203 VmIntegerReprKind::Isize(value) => value.fmt(f),
1204 VmIntegerReprKind::Usize(value) => value.fmt(f),
1205 }
1206 }
1207}
1208
1209impl fmt::Debug for VmIntegerRepr {
1210 #[inline]
1211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1212 self.kind.fmt(f)
1213 }
1214}
1215
1216fn fmt_global(f: &mut fmt::Formatter<'_>, slot: usize, name: Option<&Item>) -> fmt::Result {
1219 match name {
1220 Some(name) => write!(f, "`{name}` (slot {slot})"),
1221 None => write!(f, "in slot {slot}"),
1222 }
1223}