1use std::any::Any;
2use std::backtrace::Backtrace;
3use std::borrow::Cow;
4use std::{convert, fmt, mem, ops};
5
6use either::Either;
7use rustc_abi::{Align, Size, VariantIdx, WrappingRange};
8use rustc_ast_ir::Mutability;
9use rustc_data_structures::sync::Lock;
10use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
11use rustc_macros::{HashStable, TyDecodable, TyEncodable};
12use rustc_session::CtfeBacktrace;
13use rustc_span::def_id::DefId;
14use rustc_span::{DUMMY_SP, Span, Symbol};
15
16use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
17use crate::error;
18use crate::mir::{ConstAlloc, ConstValue};
19use crate::ty::{self, Ty, TyCtxt, ValTree, layout, tls};
20
21#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
22pub enum ErrorHandled {
23 Reported(ReportedErrorInfo, Span),
26 TooGeneric(Span),
29}
30
31impl From<ReportedErrorInfo> for ErrorHandled {
32 #[inline]
33 fn from(error: ReportedErrorInfo) -> ErrorHandled {
34 ErrorHandled::Reported(error, DUMMY_SP)
35 }
36}
37
38impl ErrorHandled {
39 pub fn with_span(self, span: Span) -> Self {
40 match self {
41 ErrorHandled::Reported(err, _span) => ErrorHandled::Reported(err, span),
42 ErrorHandled::TooGeneric(_span) => ErrorHandled::TooGeneric(span),
43 }
44 }
45
46 pub fn emit_note(&self, tcx: TyCtxt<'_>) {
47 match self {
48 &ErrorHandled::Reported(err, span) => {
49 if !err.allowed_in_infallible && !span.is_dummy() {
50 tcx.dcx().emit_note(error::ErroneousConstant { span });
51 }
52 }
53 &ErrorHandled::TooGeneric(_) => {}
54 }
55 }
56}
57
58#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
59pub struct ReportedErrorInfo {
60 error: ErrorGuaranteed,
61 allowed_in_infallible: bool,
64}
65
66impl ReportedErrorInfo {
67 #[inline]
68 pub fn const_eval_error(error: ErrorGuaranteed) -> ReportedErrorInfo {
69 ReportedErrorInfo { allowed_in_infallible: false, error }
70 }
71
72 #[inline]
75 pub fn non_const_eval_error(error: ErrorGuaranteed) -> ReportedErrorInfo {
76 ReportedErrorInfo { allowed_in_infallible: true, error }
77 }
78
79 #[inline]
82 pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo {
83 ReportedErrorInfo { allowed_in_infallible: true, error }
84 }
85
86 pub fn is_allowed_in_infallible(&self) -> bool {
87 self.allowed_in_infallible
88 }
89}
90
91impl From<ReportedErrorInfo> for ErrorGuaranteed {
92 #[inline]
93 fn from(val: ReportedErrorInfo) -> Self {
94 val.error
95 }
96}
97
98pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
99pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
100pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
101pub type EvalToValTreeResult<'tcx> = Result<Result<ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>;
106
107#[cfg(target_pointer_width = "64")]
108rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8);
109
110#[derive(Debug)]
120pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
121
122#[derive(Debug)]
123struct InterpErrorInfoInner<'tcx> {
124 kind: InterpErrorKind<'tcx>,
125 backtrace: InterpErrorBacktrace,
126}
127
128#[derive(Debug)]
129pub struct InterpErrorBacktrace {
130 backtrace: Option<Box<Backtrace>>,
131}
132
133impl InterpErrorBacktrace {
134 pub fn new() -> InterpErrorBacktrace {
135 let capture_backtrace = tls::with_opt(|tcx| {
136 if let Some(tcx) = tcx {
137 *Lock::borrow(&tcx.sess.ctfe_backtrace)
138 } else {
139 CtfeBacktrace::Disabled
140 }
141 });
142
143 let backtrace = match capture_backtrace {
144 CtfeBacktrace::Disabled => None,
145 CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
146 CtfeBacktrace::Immediate => {
147 let backtrace = Backtrace::force_capture();
149 print_backtrace(&backtrace);
150 None
151 }
152 };
153
154 InterpErrorBacktrace { backtrace }
155 }
156
157 pub fn print_backtrace(&self) {
158 if let Some(backtrace) = self.backtrace.as_ref() {
159 print_backtrace(backtrace);
160 }
161 }
162}
163
164impl<'tcx> InterpErrorInfo<'tcx> {
165 pub fn into_parts(self) -> (InterpErrorKind<'tcx>, InterpErrorBacktrace) {
166 let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
167 (kind, backtrace)
168 }
169
170 pub fn into_kind(self) -> InterpErrorKind<'tcx> {
171 self.0.kind
172 }
173
174 pub fn from_parts(kind: InterpErrorKind<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
175 Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
176 }
177
178 #[inline]
179 pub fn kind(&self) -> &InterpErrorKind<'tcx> {
180 &self.0.kind
181 }
182}
183
184fn print_backtrace(backtrace: &Backtrace) {
185 eprintln!("\n\nAn error occurred in the MIR interpreter:\n{backtrace}");
186}
187
188impl From<ErrorHandled> for InterpErrorInfo<'_> {
189 fn from(err: ErrorHandled) -> Self {
190 InterpErrorKind::InvalidProgram(match err {
191 ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
192 ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
193 })
194 .into()
195 }
196}
197
198impl<'tcx> From<InterpErrorKind<'tcx>> for InterpErrorInfo<'tcx> {
199 fn from(kind: InterpErrorKind<'tcx>) -> Self {
200 InterpErrorInfo(Box::new(InterpErrorInfoInner {
201 kind,
202 backtrace: InterpErrorBacktrace::new(),
203 }))
204 }
205}
206
207#[derive(Debug)]
212pub enum InvalidProgramInfo<'tcx> {
213 TooGeneric,
215 AlreadyReported(ReportedErrorInfo),
217 Layout(layout::LayoutError<'tcx>),
219}
220
221#[derive(Debug, Copy, Clone)]
223pub enum CheckInAllocMsg {
224 MemoryAccessTest,
226 PointerArithmeticTest,
228 OffsetFromTest,
230 InboundsTest,
232}
233
234#[derive(Debug, Copy, Clone)]
236pub enum CheckAlignMsg {
237 AccessedPtr,
239 BasedOn,
241}
242
243#[derive(Debug, Copy, Clone)]
244pub enum InvalidMetaKind {
245 SliceTooBig,
247 TooBig,
249}
250
251impl IntoDiagArg for InvalidMetaKind {
252 fn into_diag_arg(self) -> DiagArgValue {
253 DiagArgValue::Str(Cow::Borrowed(match self {
254 InvalidMetaKind::SliceTooBig => "slice_too_big",
255 InvalidMetaKind::TooBig => "too_big",
256 }))
257 }
258}
259
260#[derive(Debug, Clone, Copy)]
262pub struct BadBytesAccess {
263 pub access: AllocRange,
265 pub bad: AllocRange,
267}
268
269#[derive(Debug)]
271pub struct ScalarSizeMismatch {
272 pub target_size: u64,
273 pub data_size: u64,
274}
275
276#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
278pub struct Misalignment {
279 pub has: Align,
280 pub required: Align,
281}
282
283macro_rules! impl_into_diag_arg_through_debug {
284 ($($ty:ty),*$(,)?) => {$(
285 impl IntoDiagArg for $ty {
286 fn into_diag_arg(self) -> DiagArgValue {
287 DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
288 }
289 }
290 )*}
291}
292
293impl_into_diag_arg_through_debug! {
295 AllocId,
296 Pointer<AllocId>,
297 AllocRange,
298}
299
300#[derive(Debug)]
302pub enum UndefinedBehaviorInfo<'tcx> {
303 Ub(String),
305 Custom(crate::error::CustomSubdiagnostic<'tcx>),
309 ValidationError(ValidationErrorInfo<'tcx>),
311
312 Unreachable,
314 BoundsCheckFailed { len: u64, index: u64 },
316 DivisionByZero,
318 RemainderByZero,
320 DivisionOverflow,
322 RemainderOverflow,
324 PointerArithOverflow,
326 ArithOverflow { intrinsic: Symbol },
328 ShiftOverflow { intrinsic: Symbol, shift_amount: Either<u128, i128> },
330 InvalidMeta(InvalidMetaKind),
332 UnterminatedCString(Pointer<AllocId>),
334 PointerUseAfterFree(AllocId, CheckInAllocMsg),
336 PointerOutOfBounds {
338 alloc_id: AllocId,
339 alloc_size: Size,
340 ptr_offset: i64,
341 inbounds_size: i64,
343 msg: CheckInAllocMsg,
344 },
345 DanglingIntPointer {
347 addr: u64,
348 inbounds_size: i64,
351 msg: CheckInAllocMsg,
352 },
353 AlignmentCheckFailed(Misalignment, CheckAlignMsg),
355 WriteToReadOnly(AllocId),
357 DerefFunctionPointer(AllocId),
359 DerefVTablePointer(AllocId),
361 InvalidBool(u8),
363 InvalidChar(u32),
365 InvalidTag(Scalar<AllocId>),
367 InvalidFunctionPointer(Pointer<AllocId>),
369 InvalidVTablePointer(Pointer<AllocId>),
371 InvalidVTableTrait {
373 vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
375 expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
377 },
378 InvalidStr(std::str::Utf8Error),
380 InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
382 DeadLocal,
384 ScalarSizeMismatch(ScalarSizeMismatch),
386 UninhabitedEnumVariantWritten(VariantIdx),
388 UninhabitedEnumVariantRead(Option<VariantIdx>),
390 InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
392 AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
394 AbiMismatchReturn { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
396}
397
398#[derive(Debug, Clone, Copy)]
399pub enum PointerKind {
400 Ref(Mutability),
401 Box,
402}
403
404impl IntoDiagArg for PointerKind {
405 fn into_diag_arg(self) -> DiagArgValue {
406 DiagArgValue::Str(
407 match self {
408 Self::Ref(_) => "ref",
409 Self::Box => "box",
410 }
411 .into(),
412 )
413 }
414}
415
416#[derive(Debug)]
417pub struct ValidationErrorInfo<'tcx> {
418 pub path: Option<String>,
419 pub kind: ValidationErrorKind<'tcx>,
420}
421
422#[derive(Debug)]
423pub enum ExpectedKind {
424 Reference,
425 Box,
426 RawPtr,
427 InitScalar,
428 Bool,
429 Char,
430 Float,
431 Int,
432 FnPtr,
433 EnumTag,
434 Str,
435}
436
437impl From<PointerKind> for ExpectedKind {
438 fn from(x: PointerKind) -> ExpectedKind {
439 match x {
440 PointerKind::Box => ExpectedKind::Box,
441 PointerKind::Ref(_) => ExpectedKind::Reference,
442 }
443 }
444}
445
446#[derive(Debug)]
447pub enum ValidationErrorKind<'tcx> {
448 PointerAsInt {
449 expected: ExpectedKind,
450 },
451 PartialPointer,
452 PtrToUninhabited {
453 ptr_kind: PointerKind,
454 ty: Ty<'tcx>,
455 },
456 ConstRefToMutable,
457 ConstRefToExtern,
458 MutableRefToImmutable,
459 UnsafeCellInImmutable,
460 NullFnPtr,
461 NeverVal,
462 NullablePtrOutOfRange {
463 range: WrappingRange,
464 max_value: u128,
465 },
466 PtrOutOfRange {
467 range: WrappingRange,
468 max_value: u128,
469 },
470 OutOfRange {
471 value: String,
472 range: WrappingRange,
473 max_value: u128,
474 },
475 UninhabitedVal {
476 ty: Ty<'tcx>,
477 },
478 InvalidEnumTag {
479 value: String,
480 },
481 UninhabitedEnumVariant,
482 Uninit {
483 expected: ExpectedKind,
484 },
485 InvalidVTablePtr {
486 value: String,
487 },
488 InvalidMetaWrongTrait {
489 vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
491 expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
493 },
494 InvalidMetaSliceTooLarge {
495 ptr_kind: PointerKind,
496 },
497 InvalidMetaTooLarge {
498 ptr_kind: PointerKind,
499 },
500 UnalignedPtr {
501 ptr_kind: PointerKind,
502 required_bytes: u64,
503 found_bytes: u64,
504 },
505 NullPtr {
506 ptr_kind: PointerKind,
507 },
508 DanglingPtrNoProvenance {
509 ptr_kind: PointerKind,
510 pointer: String,
511 },
512 DanglingPtrOutOfBounds {
513 ptr_kind: PointerKind,
514 },
515 DanglingPtrUseAfterFree {
516 ptr_kind: PointerKind,
517 },
518 InvalidBool {
519 value: String,
520 },
521 InvalidChar {
522 value: String,
523 },
524 InvalidFnPtr {
525 value: String,
526 },
527}
528
529#[derive(Debug)]
534pub enum UnsupportedOpInfo {
535 Unsupported(String),
538 UnsizedLocal,
540 ExternTypeField,
542 OverwritePartialPointer(Pointer<AllocId>),
548 ReadPartialPointer(Pointer<AllocId>),
551 ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
553 ThreadLocalStatic(DefId),
555 ExternStatic(DefId),
557}
558
559#[derive(Debug)]
562pub enum ResourceExhaustionInfo {
563 StackFrameLimitReached,
565 MemoryExhausted,
567 AddressSpaceFull,
569 Interrupted,
571}
572
573pub trait MachineStopType: Any + fmt::Debug + Send {
575 fn diagnostic_message(&self) -> DiagMessage;
577 fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagArgName, DiagArgValue));
580}
581
582impl dyn MachineStopType {
583 #[inline(always)]
584 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
585 let x: &dyn Any = self;
586 x.downcast_ref()
587 }
588}
589
590#[derive(Debug)]
591pub enum InterpErrorKind<'tcx> {
592 UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
594 Unsupported(UnsupportedOpInfo),
597 InvalidProgram(InvalidProgramInfo<'tcx>),
599 ResourceExhaustion(ResourceExhaustionInfo),
602 MachineStop(Box<dyn MachineStopType>),
605}
606
607impl InterpErrorKind<'_> {
608 pub fn formatted_string(&self) -> bool {
612 matches!(
613 self,
614 InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_))
615 | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
616 | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
617 )
618 }
619}
620
621#[macro_export]
623macro_rules! err_unsup {
624 ($($tt:tt)*) => {
625 $crate::mir::interpret::InterpErrorKind::Unsupported(
626 $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
627 )
628 };
629}
630
631#[macro_export]
632macro_rules! err_unsup_format {
633 ($($tt:tt)*) => { $crate::err_unsup!(Unsupported(format!($($tt)*))) };
634}
635
636#[macro_export]
637macro_rules! err_inval {
638 ($($tt:tt)*) => {
639 $crate::mir::interpret::InterpErrorKind::InvalidProgram(
640 $crate::mir::interpret::InvalidProgramInfo::$($tt)*
641 )
642 };
643}
644
645#[macro_export]
646macro_rules! err_ub {
647 ($($tt:tt)*) => {
648 $crate::mir::interpret::InterpErrorKind::UndefinedBehavior(
649 $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
650 )
651 };
652}
653
654#[macro_export]
655macro_rules! err_ub_format {
656 ($($tt:tt)*) => { $crate::err_ub!(Ub(format!($($tt)*))) };
657}
658
659#[macro_export]
660macro_rules! err_ub_custom {
661 ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{
662 $(
663 let ($($name,)*) = ($($value,)*);
664 )?
665 $crate::err_ub!(Custom(
666 $crate::error::CustomSubdiagnostic {
667 msg: || $msg,
668 add_args: Box::new(move |mut set_arg| {
669 $($(
670 set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name));
671 )*)?
672 })
673 }
674 ))
675 }};
676}
677
678#[macro_export]
679macro_rules! err_exhaust {
680 ($($tt:tt)*) => {
681 $crate::mir::interpret::InterpErrorKind::ResourceExhaustion(
682 $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
683 )
684 };
685}
686
687#[macro_export]
688macro_rules! err_machine_stop {
689 ($($tt:tt)*) => {
690 $crate::mir::interpret::InterpErrorKind::MachineStop(Box::new($($tt)*))
691 };
692}
693
694#[macro_export]
696macro_rules! throw_unsup {
697 ($($tt:tt)*) => { do yeet $crate::err_unsup!($($tt)*) };
698}
699
700#[macro_export]
701macro_rules! throw_unsup_format {
702 ($($tt:tt)*) => { do yeet $crate::err_unsup_format!($($tt)*) };
703}
704
705#[macro_export]
706macro_rules! throw_inval {
707 ($($tt:tt)*) => { do yeet $crate::err_inval!($($tt)*) };
708}
709
710#[macro_export]
711macro_rules! throw_ub {
712 ($($tt:tt)*) => { do yeet $crate::err_ub!($($tt)*) };
713}
714
715#[macro_export]
716macro_rules! throw_ub_format {
717 ($($tt:tt)*) => { do yeet $crate::err_ub_format!($($tt)*) };
718}
719
720#[macro_export]
721macro_rules! throw_ub_custom {
722 ($($tt:tt)*) => { do yeet $crate::err_ub_custom!($($tt)*) };
723}
724
725#[macro_export]
726macro_rules! throw_exhaust {
727 ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) };
728}
729
730#[macro_export]
731macro_rules! throw_machine_stop {
732 ($($tt:tt)*) => { do yeet $crate::err_machine_stop!($($tt)*) };
733}
734
735#[derive(Debug)]
737struct Guard;
738
739impl Drop for Guard {
740 fn drop(&mut self) {
741 if !std::thread::panicking() {
743 panic!(
744 "an interpreter error got improperly discarded; use `discard_err()` if this is intentional"
745 );
746 }
747 }
748}
749
750#[derive(Debug)]
755#[must_use]
756pub struct InterpResult_<'tcx, T> {
757 res: Result<T, InterpErrorInfo<'tcx>>,
758 guard: Guard,
759}
760
761pub type InterpResult<'tcx, T = ()> = InterpResult_<'tcx, T>;
763
764impl<'tcx, T> ops::Try for InterpResult_<'tcx, T> {
765 type Output = T;
766 type Residual = InterpResult_<'tcx, convert::Infallible>;
767
768 #[inline]
769 fn from_output(output: Self::Output) -> Self {
770 InterpResult_::new(Ok(output))
771 }
772
773 #[inline]
774 fn branch(self) -> ops::ControlFlow<Self::Residual, Self::Output> {
775 match self.disarm() {
776 Ok(v) => ops::ControlFlow::Continue(v),
777 Err(e) => ops::ControlFlow::Break(InterpResult_::new(Err(e))),
778 }
779 }
780}
781
782impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
783 #[inline]
784 #[track_caller]
785 fn from_residual(residual: InterpResult_<'tcx, convert::Infallible>) -> Self {
786 match residual.disarm() {
787 Err(e) => Self::new(Err(e)),
788 }
789 }
790}
791
792impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult_<'tcx, T> {
794 #[inline]
795 fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
796 Self::new(Err(e.into()))
797 }
798}
799
800impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> ops::FromResidual<Result<convert::Infallible, E>>
803 for InterpResult_<'tcx, T>
804{
805 #[inline]
806 fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
807 match residual {
808 Err(e) => Self::new(Err(e.into())),
809 }
810 }
811}
812
813impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> From<Result<T, E>> for InterpResult<'tcx, T> {
814 #[inline]
815 fn from(value: Result<T, E>) -> Self {
816 Self::new(value.map_err(|e| e.into()))
817 }
818}
819
820impl<'tcx, T, V: FromIterator<T>> FromIterator<InterpResult<'tcx, T>> for InterpResult<'tcx, V> {
821 fn from_iter<I: IntoIterator<Item = InterpResult<'tcx, T>>>(iter: I) -> Self {
822 Self::new(iter.into_iter().map(|x| x.disarm()).collect())
823 }
824}
825
826impl<'tcx, T> InterpResult_<'tcx, T> {
827 #[inline(always)]
828 fn new(res: Result<T, InterpErrorInfo<'tcx>>) -> Self {
829 Self { res, guard: Guard }
830 }
831
832 #[inline(always)]
833 fn disarm(self) -> Result<T, InterpErrorInfo<'tcx>> {
834 mem::forget(self.guard);
835 self.res
836 }
837
838 #[inline]
840 pub fn discard_err(self) -> Option<T> {
841 self.disarm().ok()
842 }
843
844 #[inline]
847 pub fn report_err(self) -> Result<T, InterpErrorInfo<'tcx>> {
848 self.disarm()
849 }
850
851 #[inline]
852 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> InterpResult<'tcx, U> {
853 InterpResult_::new(self.disarm().map(f))
854 }
855
856 #[inline]
857 pub fn map_err_info(
858 self,
859 f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>,
860 ) -> InterpResult<'tcx, T> {
861 InterpResult_::new(self.disarm().map_err(f))
862 }
863
864 #[inline]
865 pub fn map_err_kind(
866 self,
867 f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
868 ) -> InterpResult<'tcx, T> {
869 InterpResult_::new(self.disarm().map_err(|mut e| {
870 e.0.kind = f(e.0.kind);
871 e
872 }))
873 }
874
875 #[inline]
876 pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> {
877 InterpResult_::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
878 }
879
880 #[inline]
881 #[track_caller]
882 pub fn unwrap(self) -> T {
883 self.disarm().unwrap()
884 }
885
886 #[inline]
887 #[track_caller]
888 pub fn unwrap_or_else(self, f: impl FnOnce(InterpErrorInfo<'tcx>) -> T) -> T {
889 self.disarm().unwrap_or_else(f)
890 }
891
892 #[inline]
893 #[track_caller]
894 pub fn expect(self, msg: &str) -> T {
895 self.disarm().expect(msg)
896 }
897
898 #[inline]
899 pub fn and_then<U>(self, f: impl FnOnce(T) -> InterpResult<'tcx, U>) -> InterpResult<'tcx, U> {
900 InterpResult_::new(self.disarm().and_then(|t| f(t).disarm()))
901 }
902
903 #[inline]
908 pub fn and<U>(self, other: InterpResult<'tcx, U>) -> InterpResult<'tcx, (T, U)> {
909 match self.disarm() {
910 Ok(t) => interp_ok((t, other?)),
911 Err(e) => {
912 drop(other.disarm());
914 InterpResult_::new(Err(e))
916 }
917 }
918 }
919}
920
921#[inline(always)]
922pub fn interp_ok<'tcx, T>(x: T) -> InterpResult<'tcx, T> {
923 InterpResult_::new(Ok(x))
924}