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