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