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