rune/runtime/
vm_error.rs

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
35/// A virtual machine error which includes tracing information.
36pub 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    /// Construct an error containing a panic.
60    #[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    /// Construct an expectation error. The actual type received is `actual`,
69    /// but we expected `E`.
70    #[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    /// Get the location where the error happened.
79    #[inline]
80    pub fn at(&self) -> &VmErrorAt {
81        &self.inner.error
82    }
83
84    /// Get the top-level error.
85    #[inline]
86    pub fn error(&self) -> &VmErrorAt {
87        &self.inner.error
88    }
89
90    /// Get the full backtrace of errors and their corresponding instructions.
91    #[inline]
92    pub fn chain(&self) -> &[VmErrorAt] {
93        &self.inner.chain
94    }
95
96    /// Get the full backtrace of errors and their corresponding instructions.
97    #[inline]
98    pub fn stacktrace(&self) -> &[VmErrorLocation] {
99        &self.inner.stacktrace
100    }
101
102    /// Construct an overflow error.
103    #[inline]
104    pub fn overflow() -> Self {
105        Self::from(VmErrorKind::Overflow)
106    }
107
108    /// Get the first error location.
109    #[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    /// Apply the given frame to the current result.
120    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    /// Add auxilliary errors if appropriate.
136    #[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/// A single unit producing errors.
174#[derive(Debug)]
175#[non_exhaustive]
176pub struct VmErrorLocation {
177    /// Associated unit.
178    pub unit: Arc<Unit>,
179    /// Frozen instruction pointer.
180    pub ip: usize,
181    /// All lower call frames before the unwind trigger point
182    pub frames: rust_alloc::vec::Vec<CallFrame>,
183}
184
185#[derive(Debug)]
186#[non_exhaustive]
187pub struct VmErrorAt {
188    /// Index into the backtrace which contains information of what caused this error.
189    #[cfg(feature = "emit")]
190    index: usize,
191    /// The kind of error.
192    kind: VmErrorKind,
193}
194
195impl VmErrorAt {
196    /// Get the instruction which caused the error.
197    #[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/// A result produced by the virtual machine.
223#[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
298/// A expected error.
299pub struct ExpectedType {
300    pub(crate) expected: TypeInfo,
301    pub(crate) actual: TypeInfo,
302}
303
304impl ExpectedType {
305    /// Construct an expected error.
306    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/// An opaque simple runtime error.
320#[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    /// Construct an error containing a panic.
342    #[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    /// Bad argument count.
351    pub fn bad_argument_count(actual: usize, expected: usize) -> Self {
352        Self::new(VmErrorKind::BadArgumentCount { actual, expected })
353    }
354
355    /// Construct an expected error.
356    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    /// Construct an expected error from any.
367    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    /// Construct an expected any error.
378    pub(crate) fn expected_any_obj(actual: TypeInfo) -> Self {
379        Self::new(VmErrorKind::ExpectedAny { actual })
380    }
381
382    /// Indicate that a constant constructor is missing.
383    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/// The kind of error encountered.
438#[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    // Used in rune-macros.
653    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    /// Bad argument.
1027    pub(crate) fn bad_argument(arg: usize) -> Self {
1028        Self::BadArgument { arg }
1029    }
1030
1031    /// Construct an expected error.
1032    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/// A type-erased integer representation.
1053#[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}