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 BadEnvironmentCount {
542 actual: usize,
543 expected: usize,
544 },
545 BadArgument {
546 arg: usize,
547 },
548 UnsupportedIndexSet {
549 target: TypeInfo,
550 index: TypeInfo,
551 value: TypeInfo,
552 },
553 UnsupportedIndexGet {
554 target: TypeInfo,
555 index: TypeInfo,
556 },
557 UnsupportedTupleIndexGet {
558 target: TypeInfo,
559 index: usize,
560 },
561 UnsupportedTupleIndexSet {
562 target: TypeInfo,
563 },
564 UnsupportedObjectSlotIndexGet {
565 target: TypeInfo,
566 field: Arc<StaticString>,
567 },
568 UnsupportedObjectSlotIndexSet {
569 target: TypeInfo,
570 field: Arc<StaticString>,
571 },
572 UnsupportedIs {
573 value: TypeInfo,
574 test_type: TypeInfo,
575 },
576 UnsupportedAs {
577 value: TypeInfo,
578 type_hash: Hash,
579 },
580 UnsupportedCallFn {
581 actual: TypeInfo,
582 },
583 ObjectIndexMissing {
584 slot: usize,
585 },
586 MissingIndex {
587 target: TypeInfo,
588 },
589 MissingIndexInteger {
590 target: TypeInfo,
591 index: VmIntegerRepr,
592 },
593 MissingIndexKey {
594 target: TypeInfo,
595 },
596 OutOfRange {
597 index: VmIntegerRepr,
598 length: VmIntegerRepr,
599 },
600 UnsupportedTryOperand {
601 actual: TypeInfo,
602 },
603 UnsupportedIterRangeInclusive {
604 start: TypeInfo,
605 end: TypeInfo,
606 },
607 UnsupportedIterRangeFrom {
608 start: TypeInfo,
609 },
610 UnsupportedIterRange {
611 start: TypeInfo,
612 end: TypeInfo,
613 },
614 UnsupportedIterNextOperand {
615 actual: TypeInfo,
616 },
617 ExpectedType {
618 expected: TypeInfo,
619 actual: TypeInfo,
620 },
621 ExpectedAny {
622 actual: TypeInfo,
623 },
624 ExpectedNumber {
625 actual: TypeInfo,
626 },
627 ExpectedEmpty {
628 actual: TypeInfo,
629 },
630 ExpectedTuple {
631 actual: TypeInfo,
632 },
633 ExpectedStruct {
634 actual: TypeInfo,
635 },
636 MissingConstantConstructor {
637 hash: Hash,
638 },
639 ValueToIntegerCoercionError {
640 from: VmIntegerRepr,
641 to: &'static str,
642 },
643 IntegerToValueCoercionError {
644 from: VmIntegerRepr,
645 to: &'static str,
646 },
647 ExpectedTupleLength {
648 actual: usize,
649 expected: usize,
650 },
651 ExpectedVecLength {
652 actual: usize,
653 expected: usize,
654 },
655 ConstNotSupported {
656 actual: TypeInfo,
657 },
658 MissingInterfaceEnvironment,
659 ExpectedExitedExecutionState {
660 actual: ExecutionState,
661 },
662 GeneratorComplete,
663 FutureCompleted,
664 MissingVariant {
666 name: String,
667 },
668 MissingField {
669 target: TypeInfo,
670 field: String,
671 },
672 MissingVariantName,
673 MissingStructField {
674 target: &'static str,
675 name: &'static str,
676 },
677 MissingTupleIndex {
678 target: &'static str,
679 index: usize,
680 },
681 ExpectedVariant {
682 actual: TypeInfo,
683 },
684 UnsupportedObjectFieldGet {
685 target: TypeInfo,
686 },
687 IllegalFloatComparison {
688 lhs: f64,
689 rhs: f64,
690 },
691 IllegalFloatOperation {
692 value: f64,
693 },
694 MissingCallFrame,
695 IllegalFormat,
696}
697
698impl fmt::Display for VmErrorKind {
699 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
700 match self {
701 VmErrorKind::AllocError { error } => error.fmt(f),
702 VmErrorKind::AccessError { error } => error.fmt(f),
703 VmErrorKind::StackError { error } => error.fmt(f),
704 VmErrorKind::SliceError { error } => error.fmt(f),
705 VmErrorKind::BadInstruction { error } => error.fmt(f),
706 VmErrorKind::BadJump { error } => error.fmt(f),
707 VmErrorKind::DynArgsUsed { error } => error.fmt(f),
708 VmErrorKind::Panic { reason } => write!(f, "Panicked: {reason}"),
709 VmErrorKind::NoRunningVm => write!(f, "No running virtual machines"),
710 VmErrorKind::Halted { halt } => write!(f, "Halted for unexpected reason `{halt}`"),
711 VmErrorKind::Overflow => write!(f, "Numerical overflow"),
712 VmErrorKind::Underflow => write!(f, "Numerical underflow"),
713 VmErrorKind::DivideByZero => write!(f, "Division by zero"),
714 VmErrorKind::MissingEntry { item, hash } => {
715 write!(f, "Missing entry `{item}` with hash `{hash}`")
716 }
717 VmErrorKind::MissingEntryHash { hash } => {
718 write!(f, "Missing entry with hash `{hash}`")
719 }
720 VmErrorKind::MissingFunction { hash } => {
721 write!(f, "Missing function with hash `{hash}`")
722 }
723 VmErrorKind::MissingContextFunction { hash } => {
724 write!(f, "Missing context function with hash `{hash}`")
725 }
726 VmErrorKind::NotOwned { type_info } => {
727 write!(f, "Cannot use owned operations for {type_info}")
728 }
729 VmErrorKind::MissingProtocolFunction { protocol, instance } => {
730 write!(f, "Missing protocol function `{protocol}` for `{instance}`")
731 }
732 VmErrorKind::MissingInstanceFunction { hash, instance } => {
733 write!(f, "Missing instance function `{hash}` for `{instance}`")
734 }
735 VmErrorKind::IpOutOfBounds { ip, length } => write!(
736 f,
737 "Instruction pointer `{ip}` is out-of-bounds `0-{length}`",
738 ),
739 VmErrorKind::UnsupportedBinaryOperation { op, lhs, rhs } => {
740 write!(
741 f,
742 "Unsupported binary operation `{op}` on `{lhs}` and `{rhs}`",
743 )
744 }
745 VmErrorKind::UnsupportedUnaryOperation { op, operand } => {
746 write!(f, "Unsupported unary operation `{op}` on {operand}")
747 }
748 VmErrorKind::MissingStaticString { slot } => {
749 write!(f, "Static string slot {slot} does not exist")
750 }
751 VmErrorKind::MissingStaticBytes { slot } => {
752 write!(f, "Static bytes slot {slot} does not exist")
753 }
754 VmErrorKind::MissingStaticObjectKeys { slot } => {
755 write!(f, "Static object keys slot {slot} does not exist")
756 }
757 VmErrorKind::MissingDropSet { set } => {
758 write!(f, "Static drop set {set} does not exist")
759 }
760 VmErrorKind::MissingGlobals { slot, name } => {
761 write!(f, "No storage has been configured for the static ")?;
762 fmt_global(f, *slot, name.as_deref())
763 }
764 VmErrorKind::BadGlobalSlot { slot, name } => {
765 write!(f, "The configured storage has no slot for the static ")?;
766 fmt_global(f, *slot, name.as_deref())
767 }
768 VmErrorKind::UninitializedGlobal { slot, name } => {
769 write!(f, "Reading uninitialized static ")?;
770 fmt_global(f, *slot, name.as_deref())
771 }
772 VmErrorKind::MissingRtti { hash } => {
773 write!(f, "Missing runtime information for type with hash `{hash}`")
774 }
775 VmErrorKind::BadArgumentCount { actual, expected } => {
776 write!(f, "Wrong number of arguments {actual}, expected {expected}",)
777 }
778 VmErrorKind::BadEnvironmentCount { actual, expected } => write!(
779 f,
780 "Wrong environment size `{actual}`, expected `{expected}`",
781 ),
782 VmErrorKind::BadArgument { arg } => write!(f, "Bad argument #{arg}"),
783 VmErrorKind::UnsupportedIndexSet {
784 target,
785 index,
786 value,
787 } => write!(
788 f,
789 "The index set operation `{target}[{index}] = {value}` is not supported",
790 ),
791 VmErrorKind::UnsupportedIndexGet { target, index } => write!(
792 f,
793 "The index get operation `{target}[{index}]` is not supported",
794 ),
795 VmErrorKind::UnsupportedTupleIndexGet { target, index } => write!(
796 f,
797 "The tuple index get {index} operation is not supported on `{target}`",
798 ),
799 VmErrorKind::UnsupportedTupleIndexSet { target } => write!(
800 f,
801 "The tuple index set operation is not supported on `{target}`",
802 ),
803 VmErrorKind::UnsupportedObjectSlotIndexGet { target, field } => {
804 write!(f, "Field `{field}` not available on `{target}`")
805 }
806 VmErrorKind::UnsupportedObjectSlotIndexSet { target, field } => {
807 write!(f, "Field `{field}` not available to set on `{target}`")
808 }
809 VmErrorKind::UnsupportedIs { value, test_type } => {
810 write!(f, "Operation `{value} is {test_type}` is not supported")
811 }
812 VmErrorKind::UnsupportedAs { value, type_hash } => {
813 write!(f, "Operation `{value} as {type_hash}` is not supported")
814 }
815 VmErrorKind::UnsupportedCallFn { actual } => write!(
816 f,
817 "Type `{actual}` cannot be called since it's not a function",
818 ),
819 VmErrorKind::ObjectIndexMissing { slot } => {
820 write!(f, "Missing index by static string slot `{slot}`")
821 }
822 VmErrorKind::MissingIndex { target } => {
823 write!(f, "Type `{target}` missing index")
824 }
825 VmErrorKind::MissingIndexInteger { target, index } => {
826 write!(f, "Type `{target}` missing integer index `{index}`")
827 }
828 VmErrorKind::MissingIndexKey { target } => {
829 write!(f, "Type `{target}` missing index")
830 }
831 VmErrorKind::OutOfRange { index, length } => write!(
832 f,
833 "Index out of bounds, the length is `{length}` but the index is `{index}`",
834 ),
835 VmErrorKind::UnsupportedTryOperand { actual } => {
836 write!(f, "Type `{actual}` is not supported as try operand")
837 }
838 VmErrorKind::UnsupportedIterRangeInclusive { start, end } => {
839 write!(f, "Cannot build an iterator out of {start}..={end}")
840 }
841 VmErrorKind::UnsupportedIterRangeFrom { start } => {
842 write!(f, "Cannot build an iterator out of {start}..")
843 }
844 VmErrorKind::UnsupportedIterRange { start, end } => {
845 write!(f, "Cannot build an iterator out of {start}..{end}")
846 }
847 VmErrorKind::UnsupportedIterNextOperand { actual } => {
848 write!(f, "Type `{actual}` is not supported as iter-next operand")
849 }
850 VmErrorKind::ExpectedType { expected, actual } => {
851 write!(f, "Expected type `{expected}` but found `{actual}`")
852 }
853 VmErrorKind::ExpectedAny { actual } => {
854 write!(f, "Expected `Any` type, but found `{actual}`")
855 }
856 VmErrorKind::ExpectedNumber { actual } => {
857 write!(f, "Expected number type, but found `{actual}`")
858 }
859 VmErrorKind::ExpectedEmpty { actual } => {
860 write!(f, "Expected empty, but found `{actual}`")
861 }
862 VmErrorKind::ExpectedTuple { actual } => {
863 write!(f, "Expected tuple, but found `{actual}`")
864 }
865 VmErrorKind::ExpectedStruct { actual } => {
866 write!(f, "Expected struct, but found `{actual}`")
867 }
868 VmErrorKind::MissingConstantConstructor { hash } => {
869 write!(f, "Missing constant constructor for type with hash {hash}")
870 }
871 VmErrorKind::ValueToIntegerCoercionError { from, to } => {
872 write!(f, "Failed to convert value `{from}` to integer `{to}`")
873 }
874 VmErrorKind::IntegerToValueCoercionError { from, to } => {
875 write!(f, "Failed to convert integer `{from}` to value `{to}`")
876 }
877 VmErrorKind::ExpectedTupleLength { actual, expected } => write!(
878 f,
879 "Expected a tuple of length `{expected}`, but found one with length `{actual}`",
880 ),
881 VmErrorKind::ExpectedVecLength { actual, expected } => write!(
882 f,
883 "Expected a vector of length `{expected}`, but found one with length `{actual}`",
884 ),
885 VmErrorKind::ConstNotSupported { actual } => {
886 write!(f, "Type `{actual}` can't be converted to a constant value")
887 }
888 VmErrorKind::MissingInterfaceEnvironment => {
889 write!(f, "Missing interface environment")
890 }
891 VmErrorKind::ExpectedExitedExecutionState { actual } => {
892 write!(f, "Expected exited execution state, but was {actual}")
893 }
894 VmErrorKind::GeneratorComplete => {
895 write!(f, "Cannot resume a generator that has completed")
896 }
897 VmErrorKind::FutureCompleted => write!(f, "Future already completed"),
898 VmErrorKind::MissingVariant { name } => write!(f, "No variant matching `{name}`"),
899 VmErrorKind::MissingField { target, field } => {
900 write!(f, "Missing field `{field}` on `{target}`")
901 }
902 VmErrorKind::MissingVariantName => {
903 write!(f, "missing variant name in runtime information")
904 }
905 VmErrorKind::MissingStructField { target, name } => write!(
906 f,
907 "missing dynamic field for struct field `{target}::{name}`",
908 ),
909 VmErrorKind::MissingTupleIndex { target, index } => write!(
910 f,
911 "missing dynamic index #{index} in tuple struct `{target}`",
912 ),
913 VmErrorKind::ExpectedVariant { actual } => {
914 write!(f, "Expected an enum variant, but got `{actual}`")
915 }
916 VmErrorKind::UnsupportedObjectFieldGet { target } => write!(
917 f,
918 "The object field get operation is not supported on `{target}`",
919 ),
920 VmErrorKind::IllegalFloatComparison { lhs, rhs } => {
921 write!(
922 f,
923 "Cannot perform a comparison of the floats {lhs} and {rhs}",
924 )
925 }
926 VmErrorKind::IllegalFloatOperation { value } => {
927 write!(f, "Cannot perform operation on float `{value}`")
928 }
929 VmErrorKind::MissingCallFrame => {
930 write!(f, "Missing call frame for internal vm call")
931 }
932 VmErrorKind::IllegalFormat => {
933 write!(f, "Value cannot be formatted")
934 }
935 }
936 }
937}
938
939impl From<Infallible> for VmErrorKind {
940 #[inline]
941 fn from(error: Infallible) -> Self {
942 match error {}
943 }
944}
945
946impl<E> From<StoreError<E>> for VmErrorKind
947where
948 VmErrorKind: From<E>,
949{
950 #[inline]
951 fn from(value: StoreError<E>) -> Self {
952 match value.into_kind() {
953 StoreErrorKind::Stack(error) => VmErrorKind::StackError { error },
954 StoreErrorKind::Error(error) => VmErrorKind::from(error),
955 }
956 }
957}
958
959impl From<RuntimeError> for VmErrorKind {
960 #[inline]
961 fn from(value: RuntimeError) -> Self {
962 value.into_vm_error_kind()
963 }
964}
965
966impl From<AnySequenceTakeError> for VmErrorKind {
967 #[inline]
968 fn from(value: AnySequenceTakeError) -> Self {
969 match value {
970 AnySequenceTakeError::Access(error) => Self::from(error),
971 AnySequenceTakeError::Alloc(error) => Self::from(error),
972 }
973 }
974}
975
976impl From<AnyObjError> for VmErrorKind {
977 #[inline]
978 fn from(value: AnyObjError) -> Self {
979 match value.into_kind() {
980 AnyObjErrorKind::Alloc(error) => Self::from(error),
981 AnyObjErrorKind::Cast(expected, actual) => VmErrorKind::ExpectedType {
982 expected: TypeInfo::any_type_info(expected),
983 actual,
984 },
985 AnyObjErrorKind::AccessError(error) => Self::from(error),
986 AnyObjErrorKind::NotOwned(type_info) => VmErrorKind::NotOwned { type_info },
987 }
988 }
989}
990
991impl From<AccessError> for VmErrorKind {
992 #[inline]
993 fn from(error: AccessError) -> Self {
994 VmErrorKind::AccessError { error }
995 }
996}
997
998impl From<StackError> for VmErrorKind {
999 #[inline]
1000 fn from(error: StackError) -> Self {
1001 VmErrorKind::StackError { error }
1002 }
1003}
1004
1005impl From<SliceError> for VmErrorKind {
1006 #[inline]
1007 fn from(error: SliceError) -> Self {
1008 VmErrorKind::SliceError { error }
1009 }
1010}
1011
1012impl From<BadInstruction> for VmErrorKind {
1013 #[inline]
1014 fn from(error: BadInstruction) -> Self {
1015 VmErrorKind::BadInstruction { error }
1016 }
1017}
1018
1019impl From<BadJump> for VmErrorKind {
1020 #[inline]
1021 fn from(error: BadJump) -> Self {
1022 VmErrorKind::BadJump { error }
1023 }
1024}
1025
1026impl From<DynArgsUsed> for VmErrorKind {
1027 #[inline]
1028 fn from(error: DynArgsUsed) -> Self {
1029 VmErrorKind::DynArgsUsed { error }
1030 }
1031}
1032
1033impl From<alloc::Error> for VmErrorKind {
1034 #[inline]
1035 fn from(error: alloc::Error) -> Self {
1036 VmErrorKind::AllocError { error }
1037 }
1038}
1039
1040impl From<alloc::alloc::AllocError> for VmErrorKind {
1041 #[inline]
1042 fn from(error: alloc::alloc::AllocError) -> Self {
1043 VmErrorKind::AllocError {
1044 error: error.into(),
1045 }
1046 }
1047}
1048
1049impl VmErrorKind {
1050 pub(crate) fn bad_argument(arg: usize) -> Self {
1052 Self::BadArgument { arg }
1053 }
1054
1055 pub(crate) fn expected<T>(actual: TypeInfo) -> Self
1057 where
1058 T: ?Sized + TypeOf,
1059 {
1060 Self::ExpectedType {
1061 expected: T::type_info(),
1062 actual,
1063 }
1064 }
1065}
1066
1067#[derive(Debug, Clone, Copy)]
1068#[cfg_attr(test, derive(PartialEq))]
1069enum VmIntegerReprKind {
1070 Signed(i128),
1071 Unsigned(u128),
1072 Isize(isize),
1073 Usize(usize),
1074}
1075
1076#[derive(Clone)]
1078#[cfg_attr(test, derive(PartialEq))]
1079pub(crate) struct VmIntegerRepr {
1080 kind: VmIntegerReprKind,
1081}
1082
1083impl VmIntegerRepr {
1084 #[inline]
1085 fn new(kind: VmIntegerReprKind) -> Self {
1086 Self { kind }
1087 }
1088}
1089
1090macro_rules! impl_from {
1091 ($($variant:ident => [$($ty:ty),* $(,)?]),* $(,)?) => {
1092 $($(
1093 impl From<$ty> for VmIntegerRepr {
1094 #[inline]
1095 fn from(value: $ty) -> Self {
1096 Self::new(VmIntegerReprKind::$variant(From::from(value)))
1097 }
1098 }
1099 )*)*
1100 };
1101}
1102
1103impl_from! {
1104 Signed => [i8, i16, i32, i64, i128],
1105 Unsigned => [u8, u16, u32, u64, u128],
1106 Isize => [isize],
1107 Usize => [usize],
1108}
1109
1110impl fmt::Display for VmIntegerRepr {
1111 #[inline]
1112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1113 match &self.kind {
1114 VmIntegerReprKind::Signed(value) => value.fmt(f),
1115 VmIntegerReprKind::Unsigned(value) => value.fmt(f),
1116 VmIntegerReprKind::Isize(value) => value.fmt(f),
1117 VmIntegerReprKind::Usize(value) => value.fmt(f),
1118 }
1119 }
1120}
1121
1122impl fmt::Debug for VmIntegerRepr {
1123 #[inline]
1124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1125 self.kind.fmt(f)
1126 }
1127}
1128
1129fn fmt_global(f: &mut fmt::Formatter<'_>, slot: usize, name: Option<&Item>) -> fmt::Result {
1132 match name {
1133 Some(name) => write!(f, "`{name}` (slot {slot})"),
1134 None => write!(f, "in slot {slot}"),
1135 }
1136}