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 MemoryAccess,
225 InboundsPointerArithmetic,
227 Dereferenceable,
229}
230
231#[derive(Debug, Copy, Clone)]
233pub enum CheckAlignMsg {
234 AccessedPtr,
236 BasedOn,
238}
239
240#[derive(Debug, Copy, Clone)]
241pub enum InvalidMetaKind {
242 SliceTooBig,
244 TooBig,
246}
247
248impl IntoDiagArg for InvalidMetaKind {
249 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
250 DiagArgValue::Str(Cow::Borrowed(match self {
251 InvalidMetaKind::SliceTooBig => "slice_too_big",
252 InvalidMetaKind::TooBig => "too_big",
253 }))
254 }
255}
256
257#[derive(Debug, Clone, Copy)]
259pub struct BadBytesAccess {
260 pub access: AllocRange,
262 pub bad: AllocRange,
264}
265
266#[derive(Debug)]
268pub struct ScalarSizeMismatch {
269 pub target_size: u64,
270 pub data_size: u64,
271}
272
273#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
275pub struct Misalignment {
276 pub has: Align,
277 pub required: Align,
278}
279
280macro_rules! impl_into_diag_arg_through_debug {
281 ($($ty:ty),*$(,)?) => {$(
282 impl IntoDiagArg for $ty {
283 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
284 DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
285 }
286 }
287 )*}
288}
289
290impl_into_diag_arg_through_debug! {
292 AllocId,
293 Pointer<AllocId>,
294 AllocRange,
295}
296
297#[derive(Debug)]
299pub enum UndefinedBehaviorInfo<'tcx> {
300 Ub(String),
302 Custom(crate::error::CustomSubdiagnostic<'tcx>),
306 ValidationError(ValidationErrorInfo<'tcx>),
308
309 Unreachable,
311 BoundsCheckFailed { len: u64, index: u64 },
313 DivisionByZero,
315 RemainderByZero,
317 DivisionOverflow,
319 RemainderOverflow,
321 PointerArithOverflow,
323 ArithOverflow { intrinsic: Symbol },
325 ShiftOverflow { intrinsic: Symbol, shift_amount: Either<u128, i128> },
327 InvalidMeta(InvalidMetaKind),
329 UnterminatedCString(Pointer<AllocId>),
331 PointerUseAfterFree(AllocId, CheckInAllocMsg),
333 PointerOutOfBounds {
335 alloc_id: AllocId,
336 alloc_size: Size,
337 ptr_offset: i64,
338 inbounds_size: i64,
340 msg: CheckInAllocMsg,
341 },
342 DanglingIntPointer {
344 addr: u64,
345 inbounds_size: i64,
348 msg: CheckInAllocMsg,
349 },
350 AlignmentCheckFailed(Misalignment, CheckAlignMsg),
352 WriteToReadOnly(AllocId),
354 DerefFunctionPointer(AllocId),
356 DerefVTablePointer(AllocId),
358 InvalidBool(u8),
360 InvalidChar(u32),
362 InvalidTag(Scalar<AllocId>),
364 InvalidFunctionPointer(Pointer<AllocId>),
366 InvalidVTablePointer(Pointer<AllocId>),
368 InvalidVTableTrait {
370 vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
372 expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
374 },
375 InvalidStr(std::str::Utf8Error),
377 InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
379 DeadLocal,
381 ScalarSizeMismatch(ScalarSizeMismatch),
383 UninhabitedEnumVariantWritten(VariantIdx),
385 UninhabitedEnumVariantRead(Option<VariantIdx>),
387 InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
389 AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
391 AbiMismatchReturn { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
393}
394
395#[derive(Debug, Clone, Copy)]
396pub enum PointerKind {
397 Ref(Mutability),
398 Box,
399}
400
401impl IntoDiagArg for PointerKind {
402 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
403 DiagArgValue::Str(
404 match self {
405 Self::Ref(_) => "ref",
406 Self::Box => "box",
407 }
408 .into(),
409 )
410 }
411}
412
413#[derive(Debug)]
414pub struct ValidationErrorInfo<'tcx> {
415 pub path: Option<String>,
416 pub kind: ValidationErrorKind<'tcx>,
417}
418
419#[derive(Debug)]
420pub enum ExpectedKind {
421 Reference,
422 Box,
423 RawPtr,
424 InitScalar,
425 Bool,
426 Char,
427 Float,
428 Int,
429 FnPtr,
430 EnumTag,
431 Str,
432}
433
434impl From<PointerKind> for ExpectedKind {
435 fn from(x: PointerKind) -> ExpectedKind {
436 match x {
437 PointerKind::Box => ExpectedKind::Box,
438 PointerKind::Ref(_) => ExpectedKind::Reference,
439 }
440 }
441}
442
443#[derive(Debug)]
444pub enum ValidationErrorKind<'tcx> {
445 PointerAsInt {
446 expected: ExpectedKind,
447 },
448 PartialPointer,
449 PtrToUninhabited {
450 ptr_kind: PointerKind,
451 ty: Ty<'tcx>,
452 },
453 ConstRefToMutable,
454 ConstRefToExtern,
455 MutableRefToImmutable,
456 UnsafeCellInImmutable,
457 NullFnPtr,
458 NeverVal,
459 NullablePtrOutOfRange {
460 range: WrappingRange,
461 max_value: u128,
462 },
463 PtrOutOfRange {
464 range: WrappingRange,
465 max_value: u128,
466 },
467 OutOfRange {
468 value: String,
469 range: WrappingRange,
470 max_value: u128,
471 },
472 UninhabitedVal {
473 ty: Ty<'tcx>,
474 },
475 InvalidEnumTag {
476 value: String,
477 },
478 UninhabitedEnumVariant,
479 Uninit {
480 expected: ExpectedKind,
481 },
482 InvalidVTablePtr {
483 value: String,
484 },
485 InvalidMetaWrongTrait {
486 vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
488 expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
490 },
491 InvalidMetaSliceTooLarge {
492 ptr_kind: PointerKind,
493 },
494 InvalidMetaTooLarge {
495 ptr_kind: PointerKind,
496 },
497 UnalignedPtr {
498 ptr_kind: PointerKind,
499 required_bytes: u64,
500 found_bytes: u64,
501 },
502 NullPtr {
503 ptr_kind: PointerKind,
504 },
505 DanglingPtrNoProvenance {
506 ptr_kind: PointerKind,
507 pointer: String,
508 },
509 DanglingPtrOutOfBounds {
510 ptr_kind: PointerKind,
511 },
512 DanglingPtrUseAfterFree {
513 ptr_kind: PointerKind,
514 },
515 InvalidBool {
516 value: String,
517 },
518 InvalidChar {
519 value: String,
520 },
521 InvalidFnPtr {
522 value: String,
523 },
524}
525
526#[derive(Debug)]
531pub enum UnsupportedOpInfo {
532 Unsupported(String),
535 UnsizedLocal,
537 ExternTypeField,
539 OverwritePartialPointer(Pointer<AllocId>),
545 ReadPartialPointer(Pointer<AllocId>),
548 ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
550 ThreadLocalStatic(DefId),
552 ExternStatic(DefId),
554}
555
556#[derive(Debug)]
559pub enum ResourceExhaustionInfo {
560 StackFrameLimitReached,
562 MemoryExhausted,
564 AddressSpaceFull,
566 Interrupted,
568}
569
570pub trait MachineStopType: Any + fmt::Debug + Send {
572 fn diagnostic_message(&self) -> DiagMessage;
574 fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagArgName, DiagArgValue));
577}
578
579impl dyn MachineStopType {
580 #[inline(always)]
581 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
582 let x: &dyn Any = self;
583 x.downcast_ref()
584 }
585}
586
587#[derive(Debug)]
588pub enum InterpErrorKind<'tcx> {
589 UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
591 Unsupported(UnsupportedOpInfo),
594 InvalidProgram(InvalidProgramInfo<'tcx>),
596 ResourceExhaustion(ResourceExhaustionInfo),
599 MachineStop(Box<dyn MachineStopType>),
602}
603
604impl InterpErrorKind<'_> {
605 pub fn formatted_string(&self) -> bool {
609 matches!(
610 self,
611 InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_))
612 | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
613 | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
614 )
615 }
616}
617
618#[macro_export]
620macro_rules! err_unsup {
621 ($($tt:tt)*) => {
622 $crate::mir::interpret::InterpErrorKind::Unsupported(
623 $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
624 )
625 };
626}
627
628#[macro_export]
629macro_rules! err_unsup_format {
630 ($($tt:tt)*) => { $crate::err_unsup!(Unsupported(format!($($tt)*))) };
631}
632
633#[macro_export]
634macro_rules! err_inval {
635 ($($tt:tt)*) => {
636 $crate::mir::interpret::InterpErrorKind::InvalidProgram(
637 $crate::mir::interpret::InvalidProgramInfo::$($tt)*
638 )
639 };
640}
641
642#[macro_export]
643macro_rules! err_ub {
644 ($($tt:tt)*) => {
645 $crate::mir::interpret::InterpErrorKind::UndefinedBehavior(
646 $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
647 )
648 };
649}
650
651#[macro_export]
652macro_rules! err_ub_format {
653 ($($tt:tt)*) => { $crate::err_ub!(Ub(format!($($tt)*))) };
654}
655
656#[macro_export]
657macro_rules! err_ub_custom {
658 ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{
659 $(
660 let ($($name,)*) = ($($value,)*);
661 )?
662 $crate::err_ub!(Custom(
663 $crate::error::CustomSubdiagnostic {
664 msg: || $msg,
665 add_args: Box::new(move |mut set_arg| {
666 $($(
667 set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name, &mut None));
668 )*)?
669 })
670 }
671 ))
672 }};
673}
674
675#[macro_export]
676macro_rules! err_exhaust {
677 ($($tt:tt)*) => {
678 $crate::mir::interpret::InterpErrorKind::ResourceExhaustion(
679 $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
680 )
681 };
682}
683
684#[macro_export]
685macro_rules! err_machine_stop {
686 ($($tt:tt)*) => {
687 $crate::mir::interpret::InterpErrorKind::MachineStop(Box::new($($tt)*))
688 };
689}
690
691#[macro_export]
693macro_rules! throw_unsup {
694 ($($tt:tt)*) => { do yeet $crate::err_unsup!($($tt)*) };
695}
696
697#[macro_export]
698macro_rules! throw_unsup_format {
699 ($($tt:tt)*) => { do yeet $crate::err_unsup_format!($($tt)*) };
700}
701
702#[macro_export]
703macro_rules! throw_inval {
704 ($($tt:tt)*) => { do yeet $crate::err_inval!($($tt)*) };
705}
706
707#[macro_export]
708macro_rules! throw_ub {
709 ($($tt:tt)*) => { do yeet $crate::err_ub!($($tt)*) };
710}
711
712#[macro_export]
713macro_rules! throw_ub_format {
714 ($($tt:tt)*) => { do yeet $crate::err_ub_format!($($tt)*) };
715}
716
717#[macro_export]
718macro_rules! throw_ub_custom {
719 ($($tt:tt)*) => { do yeet $crate::err_ub_custom!($($tt)*) };
720}
721
722#[macro_export]
723macro_rules! throw_exhaust {
724 ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) };
725}
726
727#[macro_export]
728macro_rules! throw_machine_stop {
729 ($($tt:tt)*) => { do yeet $crate::err_machine_stop!($($tt)*) };
730}
731
732#[derive(Debug)]
734struct Guard;
735
736impl Drop for Guard {
737 fn drop(&mut self) {
738 if !std::thread::panicking() {
740 panic!(
741 "an interpreter error got improperly discarded; use `discard_err()` if this is intentional"
742 );
743 }
744 }
745}
746
747#[derive(Debug)]
752#[must_use]
753pub struct InterpResult_<'tcx, T> {
754 res: Result<T, InterpErrorInfo<'tcx>>,
755 guard: Guard,
756}
757
758pub type InterpResult<'tcx, T = ()> = InterpResult_<'tcx, T>;
760
761impl<'tcx, T> ops::Try for InterpResult_<'tcx, T> {
762 type Output = T;
763 type Residual = InterpResult_<'tcx, convert::Infallible>;
764
765 #[inline]
766 fn from_output(output: Self::Output) -> Self {
767 InterpResult_::new(Ok(output))
768 }
769
770 #[inline]
771 fn branch(self) -> ops::ControlFlow<Self::Residual, Self::Output> {
772 match self.disarm() {
773 Ok(v) => ops::ControlFlow::Continue(v),
774 Err(e) => ops::ControlFlow::Break(InterpResult_::new(Err(e))),
775 }
776 }
777}
778
779impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
780 #[inline]
781 #[track_caller]
782 fn from_residual(residual: InterpResult_<'tcx, convert::Infallible>) -> Self {
783 match residual.disarm() {
784 Err(e) => Self::new(Err(e)),
785 }
786 }
787}
788
789impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult_<'tcx, T> {
791 #[inline]
792 fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
793 Self::new(Err(e.into()))
794 }
795}
796
797impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> ops::FromResidual<Result<convert::Infallible, E>>
800 for InterpResult_<'tcx, T>
801{
802 #[inline]
803 fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
804 match residual {
805 Err(e) => Self::new(Err(e.into())),
806 }
807 }
808}
809
810impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> From<Result<T, E>> for InterpResult<'tcx, T> {
811 #[inline]
812 fn from(value: Result<T, E>) -> Self {
813 Self::new(value.map_err(|e| e.into()))
814 }
815}
816
817impl<'tcx, T, V: FromIterator<T>> FromIterator<InterpResult<'tcx, T>> for InterpResult<'tcx, V> {
818 fn from_iter<I: IntoIterator<Item = InterpResult<'tcx, T>>>(iter: I) -> Self {
819 Self::new(iter.into_iter().map(|x| x.disarm()).collect())
820 }
821}
822
823impl<'tcx, T> InterpResult_<'tcx, T> {
824 #[inline(always)]
825 fn new(res: Result<T, InterpErrorInfo<'tcx>>) -> Self {
826 Self { res, guard: Guard }
827 }
828
829 #[inline(always)]
830 fn disarm(self) -> Result<T, InterpErrorInfo<'tcx>> {
831 mem::forget(self.guard);
832 self.res
833 }
834
835 #[inline]
837 pub fn discard_err(self) -> Option<T> {
838 self.disarm().ok()
839 }
840
841 #[inline]
844 pub fn report_err(self) -> Result<T, InterpErrorInfo<'tcx>> {
845 self.disarm()
846 }
847
848 #[inline]
849 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> InterpResult<'tcx, U> {
850 InterpResult_::new(self.disarm().map(f))
851 }
852
853 #[inline]
854 pub fn map_err_info(
855 self,
856 f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>,
857 ) -> InterpResult<'tcx, T> {
858 InterpResult_::new(self.disarm().map_err(f))
859 }
860
861 #[inline]
862 pub fn map_err_kind(
863 self,
864 f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
865 ) -> InterpResult<'tcx, T> {
866 InterpResult_::new(self.disarm().map_err(|mut e| {
867 e.0.kind = f(e.0.kind);
868 e
869 }))
870 }
871
872 #[inline]
873 pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> {
874 InterpResult_::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
875 }
876
877 #[inline]
878 #[track_caller]
879 pub fn unwrap(self) -> T {
880 self.disarm().unwrap()
881 }
882
883 #[inline]
884 #[track_caller]
885 pub fn unwrap_or_else(self, f: impl FnOnce(InterpErrorInfo<'tcx>) -> T) -> T {
886 self.disarm().unwrap_or_else(f)
887 }
888
889 #[inline]
890 #[track_caller]
891 pub fn expect(self, msg: &str) -> T {
892 self.disarm().expect(msg)
893 }
894
895 #[inline]
896 pub fn and_then<U>(self, f: impl FnOnce(T) -> InterpResult<'tcx, U>) -> InterpResult<'tcx, U> {
897 InterpResult_::new(self.disarm().and_then(|t| f(t).disarm()))
898 }
899
900 #[inline]
905 pub fn and<U>(self, other: InterpResult<'tcx, U>) -> InterpResult<'tcx, (T, U)> {
906 match self.disarm() {
907 Ok(t) => interp_ok((t, other?)),
908 Err(e) => {
909 drop(other.disarm());
911 InterpResult_::new(Err(e))
913 }
914 }
915 }
916}
917
918#[inline(always)]
919pub fn interp_ok<'tcx, T>(x: T) -> InterpResult<'tcx, T> {
920 InterpResult_::new(Ok(x))
921}