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(crate) 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
97#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
100pub enum ValTreeCreationError<'tcx> {
101 NodesOverflow,
103 InvalidConst,
105 NonSupportedType(Ty<'tcx>),
107 ErrorHandled(ErrorHandled),
109}
110
111impl<'tcx> From<ErrorHandled> for ValTreeCreationError<'tcx> {
112 fn from(err: ErrorHandled) -> Self {
113 ValTreeCreationError::ErrorHandled(err)
114 }
115}
116
117impl<'tcx> From<InterpErrorInfo<'tcx>> for ValTreeCreationError<'tcx> {
118 fn from(err: InterpErrorInfo<'tcx>) -> Self {
119 let (_kind, backtrace) = err.into_parts();
123 backtrace.print_backtrace();
124 ValTreeCreationError::InvalidConst
125 }
126}
127
128impl<'tcx> ValTreeCreationError<'tcx> {
129 pub(crate) fn with_span(self, span: Span) -> Self {
130 use ValTreeCreationError::*;
131 match self {
132 ErrorHandled(handled) => ErrorHandled(handled.with_span(span)),
133 other => other,
134 }
135 }
136}
137
138pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
139pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
140pub type EvalToConstValueResult<'tcx> = Result<ConstValue, ErrorHandled>;
141pub type EvalToValTreeResult<'tcx> = Result<ValTree<'tcx>, ValTreeCreationError<'tcx>>;
142
143#[cfg(target_pointer_width = "64")]
144rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8);
145
146#[derive(Debug)]
156pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
157
158#[derive(Debug)]
159struct InterpErrorInfoInner<'tcx> {
160 kind: InterpErrorKind<'tcx>,
161 backtrace: InterpErrorBacktrace,
162}
163
164#[derive(Debug)]
165pub struct InterpErrorBacktrace {
166 backtrace: Option<Box<Backtrace>>,
167}
168
169impl InterpErrorBacktrace {
170 pub fn new() -> InterpErrorBacktrace {
171 let capture_backtrace = tls::with_opt(|tcx| {
172 if let Some(tcx) = tcx {
173 *Lock::borrow(&tcx.sess.ctfe_backtrace)
174 } else {
175 CtfeBacktrace::Disabled
176 }
177 });
178
179 let backtrace = match capture_backtrace {
180 CtfeBacktrace::Disabled => None,
181 CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
182 CtfeBacktrace::Immediate => {
183 let backtrace = Backtrace::force_capture();
185 print_backtrace(&backtrace);
186 None
187 }
188 };
189
190 InterpErrorBacktrace { backtrace }
191 }
192
193 pub fn print_backtrace(&self) {
194 if let Some(backtrace) = self.backtrace.as_ref() {
195 print_backtrace(backtrace);
196 }
197 }
198}
199
200impl<'tcx> InterpErrorInfo<'tcx> {
201 pub fn into_parts(self) -> (InterpErrorKind<'tcx>, InterpErrorBacktrace) {
202 let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
203 (kind, backtrace)
204 }
205
206 pub fn into_kind(self) -> InterpErrorKind<'tcx> {
207 self.0.kind
208 }
209
210 pub fn from_parts(kind: InterpErrorKind<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
211 Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
212 }
213
214 #[inline]
215 pub fn kind(&self) -> &InterpErrorKind<'tcx> {
216 &self.0.kind
217 }
218}
219
220fn print_backtrace(backtrace: &Backtrace) {
221 eprintln!("\n\nAn error occurred in the MIR interpreter:\n{backtrace}");
222}
223
224impl From<ErrorHandled> for InterpErrorInfo<'_> {
225 fn from(err: ErrorHandled) -> Self {
226 InterpErrorKind::InvalidProgram(match err {
227 ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
228 ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
229 })
230 .into()
231 }
232}
233
234impl<'tcx> From<InterpErrorKind<'tcx>> for InterpErrorInfo<'tcx> {
235 fn from(kind: InterpErrorKind<'tcx>) -> Self {
236 InterpErrorInfo(Box::new(InterpErrorInfoInner {
237 kind,
238 backtrace: InterpErrorBacktrace::new(),
239 }))
240 }
241}
242
243#[derive(Debug)]
248pub enum InvalidProgramInfo<'tcx> {
249 TooGeneric,
251 AlreadyReported(ReportedErrorInfo),
253 Layout(layout::LayoutError<'tcx>),
255}
256
257#[derive(Debug, Copy, Clone)]
259pub enum CheckInAllocMsg {
260 MemoryAccess,
262 InboundsPointerArithmetic,
264 Dereferenceable,
266}
267
268#[derive(Debug, Copy, Clone)]
270pub enum CheckAlignMsg {
271 AccessedPtr,
273 BasedOn,
275}
276
277#[derive(Debug, Copy, Clone)]
278pub enum InvalidMetaKind {
279 SliceTooBig,
281 TooBig,
283}
284
285impl IntoDiagArg for InvalidMetaKind {
286 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
287 DiagArgValue::Str(Cow::Borrowed(match self {
288 InvalidMetaKind::SliceTooBig => "slice_too_big",
289 InvalidMetaKind::TooBig => "too_big",
290 }))
291 }
292}
293
294#[derive(Debug, Clone, Copy)]
296pub struct BadBytesAccess {
297 pub access: AllocRange,
299 pub bad: AllocRange,
301}
302
303#[derive(Debug)]
305pub struct ScalarSizeMismatch {
306 pub target_size: u64,
307 pub data_size: u64,
308}
309
310#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
312pub struct Misalignment {
313 pub has: Align,
314 pub required: Align,
315}
316
317macro_rules! impl_into_diag_arg_through_debug {
318 ($($ty:ty),*$(,)?) => {$(
319 impl IntoDiagArg for $ty {
320 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
321 DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
322 }
323 }
324 )*}
325}
326
327impl_into_diag_arg_through_debug! {
329 AllocId,
330 Pointer<AllocId>,
331 AllocRange,
332}
333
334#[derive(Debug)]
336pub enum UndefinedBehaviorInfo<'tcx> {
337 Ub(String),
339 Custom(crate::error::CustomSubdiagnostic<'tcx>),
343 ValidationError(ValidationErrorInfo<'tcx>),
345
346 Unreachable,
348 BoundsCheckFailed { len: u64, index: u64 },
350 DivisionByZero,
352 RemainderByZero,
354 DivisionOverflow,
356 RemainderOverflow,
358 PointerArithOverflow,
360 ArithOverflow { intrinsic: Symbol },
362 ShiftOverflow { intrinsic: Symbol, shift_amount: Either<u128, i128> },
364 InvalidMeta(InvalidMetaKind),
366 UnterminatedCString(Pointer<AllocId>),
368 PointerUseAfterFree(AllocId, CheckInAllocMsg),
370 PointerOutOfBounds {
372 alloc_id: AllocId,
373 alloc_size: Size,
374 ptr_offset: i64,
375 inbounds_size: i64,
377 msg: CheckInAllocMsg,
378 },
379 DanglingIntPointer {
381 addr: u64,
382 inbounds_size: i64,
385 msg: CheckInAllocMsg,
386 },
387 AlignmentCheckFailed(Misalignment, CheckAlignMsg),
389 WriteToReadOnly(AllocId),
391 DerefFunctionPointer(AllocId),
393 DerefVTablePointer(AllocId),
395 DerefTypeIdPointer(AllocId),
397 InvalidBool(u8),
399 InvalidChar(u32),
401 InvalidTag(Scalar<AllocId>),
403 InvalidFunctionPointer(Pointer<AllocId>),
405 InvalidVTablePointer(Pointer<AllocId>),
407 InvalidVTableTrait {
409 vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
411 expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
413 },
414 InvalidStr(std::str::Utf8Error),
416 InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
418 DeadLocal,
420 ScalarSizeMismatch(ScalarSizeMismatch),
422 UninhabitedEnumVariantWritten(VariantIdx),
424 UninhabitedEnumVariantRead(Option<VariantIdx>),
426 InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
428 AbiMismatchArgument {
430 arg_idx: usize,
432 caller_ty: Ty<'tcx>,
433 callee_ty: Ty<'tcx>,
434 },
435 AbiMismatchReturn { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
437}
438
439#[derive(Debug, Clone, Copy)]
440pub enum PointerKind {
441 Ref(Mutability),
442 Box,
443}
444
445impl IntoDiagArg for PointerKind {
446 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
447 DiagArgValue::Str(
448 match self {
449 Self::Ref(_) => "ref",
450 Self::Box => "box",
451 }
452 .into(),
453 )
454 }
455}
456
457#[derive(Debug)]
458pub struct ValidationErrorInfo<'tcx> {
459 pub path: Option<String>,
460 pub kind: ValidationErrorKind<'tcx>,
461}
462
463#[derive(Debug)]
464pub enum ExpectedKind {
465 Reference,
466 Box,
467 RawPtr,
468 InitScalar,
469 Bool,
470 Char,
471 Float,
472 Int,
473 FnPtr,
474 EnumTag,
475 Str,
476}
477
478impl From<PointerKind> for ExpectedKind {
479 fn from(x: PointerKind) -> ExpectedKind {
480 match x {
481 PointerKind::Box => ExpectedKind::Box,
482 PointerKind::Ref(_) => ExpectedKind::Reference,
483 }
484 }
485}
486
487#[derive(Debug)]
488pub enum ValidationErrorKind<'tcx> {
489 PointerAsInt {
490 expected: ExpectedKind,
491 },
492 PartialPointer,
493 PtrToUninhabited {
494 ptr_kind: PointerKind,
495 ty: Ty<'tcx>,
496 },
497 MutableRefToImmutable,
498 UnsafeCellInImmutable,
499 MutableRefInConst,
500 NullFnPtr,
501 NeverVal,
502 NullablePtrOutOfRange {
503 range: WrappingRange,
504 max_value: u128,
505 },
506 PtrOutOfRange {
507 range: WrappingRange,
508 max_value: u128,
509 },
510 OutOfRange {
511 value: String,
512 range: WrappingRange,
513 max_value: u128,
514 },
515 UninhabitedVal {
516 ty: Ty<'tcx>,
517 },
518 InvalidEnumTag {
519 value: String,
520 },
521 UninhabitedEnumVariant,
522 Uninit {
523 expected: ExpectedKind,
524 },
525 InvalidVTablePtr {
526 value: String,
527 },
528 InvalidMetaWrongTrait {
529 vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
531 expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
533 },
534 InvalidMetaSliceTooLarge {
535 ptr_kind: PointerKind,
536 },
537 InvalidMetaTooLarge {
538 ptr_kind: PointerKind,
539 },
540 UnalignedPtr {
541 ptr_kind: PointerKind,
542 required_bytes: u64,
543 found_bytes: u64,
544 },
545 NullPtr {
546 ptr_kind: PointerKind,
547 },
548 DanglingPtrNoProvenance {
549 ptr_kind: PointerKind,
550 pointer: String,
551 },
552 DanglingPtrOutOfBounds {
553 ptr_kind: PointerKind,
554 },
555 DanglingPtrUseAfterFree {
556 ptr_kind: PointerKind,
557 },
558 InvalidBool {
559 value: String,
560 },
561 InvalidChar {
562 value: String,
563 },
564 InvalidFnPtr {
565 value: String,
566 },
567}
568
569#[derive(Debug)]
574pub enum UnsupportedOpInfo {
575 Unsupported(String),
578 UnsizedLocal,
580 ExternTypeField,
582 OverwritePartialPointer(Pointer<AllocId>),
588 ReadPartialPointer(Pointer<AllocId>),
591 ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
593 ThreadLocalStatic(DefId),
595 ExternStatic(DefId),
597}
598
599#[derive(Debug)]
602pub enum ResourceExhaustionInfo {
603 StackFrameLimitReached,
605 MemoryExhausted,
607 AddressSpaceFull,
609 Interrupted,
611}
612
613pub trait MachineStopType: Any + fmt::Debug + Send {
615 fn diagnostic_message(&self) -> DiagMessage;
617 fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagArgName, DiagArgValue));
620}
621
622impl dyn MachineStopType {
623 #[inline(always)]
624 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
625 let x: &dyn Any = self;
626 x.downcast_ref()
627 }
628}
629
630#[derive(Debug)]
631pub enum InterpErrorKind<'tcx> {
632 UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
634 Unsupported(UnsupportedOpInfo),
637 InvalidProgram(InvalidProgramInfo<'tcx>),
639 ResourceExhaustion(ResourceExhaustionInfo),
642 MachineStop(Box<dyn MachineStopType>),
645}
646
647impl InterpErrorKind<'_> {
648 pub fn formatted_string(&self) -> bool {
652 matches!(
653 self,
654 InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_))
655 | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
656 | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
657 )
658 }
659}
660
661#[macro_export]
663macro_rules! err_unsup {
664 ($($tt:tt)*) => {
665 $crate::mir::interpret::InterpErrorKind::Unsupported(
666 $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
667 )
668 };
669}
670
671#[macro_export]
672macro_rules! err_unsup_format {
673 ($($tt:tt)*) => { $crate::err_unsup!(Unsupported(format!($($tt)*))) };
674}
675
676#[macro_export]
677macro_rules! err_inval {
678 ($($tt:tt)*) => {
679 $crate::mir::interpret::InterpErrorKind::InvalidProgram(
680 $crate::mir::interpret::InvalidProgramInfo::$($tt)*
681 )
682 };
683}
684
685#[macro_export]
686macro_rules! err_ub {
687 ($($tt:tt)*) => {
688 $crate::mir::interpret::InterpErrorKind::UndefinedBehavior(
689 $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
690 )
691 };
692}
693
694#[macro_export]
695macro_rules! err_ub_format {
696 ($($tt:tt)*) => { $crate::err_ub!(Ub(format!($($tt)*))) };
697}
698
699#[macro_export]
700macro_rules! err_ub_custom {
701 ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{
702 $(
703 let ($($name,)*) = ($($value,)*);
704 )?
705 $crate::err_ub!(Custom(
706 $crate::error::CustomSubdiagnostic {
707 msg: || $msg,
708 add_args: Box::new(move |mut set_arg| {
709 $($(
710 set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name, &mut None));
711 )*)?
712 })
713 }
714 ))
715 }};
716}
717
718#[macro_export]
719macro_rules! err_exhaust {
720 ($($tt:tt)*) => {
721 $crate::mir::interpret::InterpErrorKind::ResourceExhaustion(
722 $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
723 )
724 };
725}
726
727#[macro_export]
728macro_rules! err_machine_stop {
729 ($($tt:tt)*) => {
730 $crate::mir::interpret::InterpErrorKind::MachineStop(Box::new($($tt)*))
731 };
732}
733
734#[macro_export]
736macro_rules! throw_unsup {
737 ($($tt:tt)*) => { do yeet $crate::err_unsup!($($tt)*) };
738}
739
740#[macro_export]
741macro_rules! throw_unsup_format {
742 ($($tt:tt)*) => { do yeet $crate::err_unsup_format!($($tt)*) };
743}
744
745#[macro_export]
746macro_rules! throw_inval {
747 ($($tt:tt)*) => { do yeet $crate::err_inval!($($tt)*) };
748}
749
750#[macro_export]
751macro_rules! throw_ub {
752 ($($tt:tt)*) => { do yeet $crate::err_ub!($($tt)*) };
753}
754
755#[macro_export]
756macro_rules! throw_ub_format {
757 ($($tt:tt)*) => { do yeet $crate::err_ub_format!($($tt)*) };
758}
759
760#[macro_export]
761macro_rules! throw_ub_custom {
762 ($($tt:tt)*) => { do yeet $crate::err_ub_custom!($($tt)*) };
763}
764
765#[macro_export]
766macro_rules! throw_exhaust {
767 ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) };
768}
769
770#[macro_export]
771macro_rules! throw_machine_stop {
772 ($($tt:tt)*) => { do yeet $crate::err_machine_stop!($($tt)*) };
773}
774
775#[derive(Debug)]
777struct Guard;
778
779impl Drop for Guard {
780 fn drop(&mut self) {
781 if !std::thread::panicking() {
783 panic!(
784 "an interpreter error got improperly discarded; use `discard_err()` if this is intentional"
785 );
786 }
787 }
788}
789
790#[derive(Debug)]
795#[must_use]
796pub struct InterpResult_<'tcx, T> {
797 res: Result<T, InterpErrorInfo<'tcx>>,
798 guard: Guard,
799}
800
801pub type InterpResult<'tcx, T = ()> = InterpResult_<'tcx, T>;
803
804impl<'tcx, T> ops::Try for InterpResult_<'tcx, T> {
805 type Output = T;
806 type Residual = InterpResult_<'tcx, convert::Infallible>;
807
808 #[inline]
809 fn from_output(output: Self::Output) -> Self {
810 InterpResult_::new(Ok(output))
811 }
812
813 #[inline]
814 fn branch(self) -> ops::ControlFlow<Self::Residual, Self::Output> {
815 match self.disarm() {
816 Ok(v) => ops::ControlFlow::Continue(v),
817 Err(e) => ops::ControlFlow::Break(InterpResult_::new(Err(e))),
818 }
819 }
820}
821
822impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
823 #[inline]
824 #[track_caller]
825 fn from_residual(residual: InterpResult_<'tcx, convert::Infallible>) -> Self {
826 match residual.disarm() {
827 Err(e) => Self::new(Err(e)),
828 }
829 }
830}
831
832impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult_<'tcx, T> {
834 #[inline]
835 fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
836 Self::new(Err(e.into()))
837 }
838}
839
840impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> ops::FromResidual<Result<convert::Infallible, E>>
843 for InterpResult_<'tcx, T>
844{
845 #[inline]
846 fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
847 match residual {
848 Err(e) => Self::new(Err(e.into())),
849 }
850 }
851}
852
853impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> From<Result<T, E>> for InterpResult<'tcx, T> {
854 #[inline]
855 fn from(value: Result<T, E>) -> Self {
856 Self::new(value.map_err(|e| e.into()))
857 }
858}
859
860impl<'tcx, T, V: FromIterator<T>> FromIterator<InterpResult<'tcx, T>> for InterpResult<'tcx, V> {
861 fn from_iter<I: IntoIterator<Item = InterpResult<'tcx, T>>>(iter: I) -> Self {
862 Self::new(iter.into_iter().map(|x| x.disarm()).collect())
863 }
864}
865
866impl<'tcx, T> InterpResult_<'tcx, T> {
867 #[inline(always)]
868 fn new(res: Result<T, InterpErrorInfo<'tcx>>) -> Self {
869 Self { res, guard: Guard }
870 }
871
872 #[inline(always)]
873 fn disarm(self) -> Result<T, InterpErrorInfo<'tcx>> {
874 mem::forget(self.guard);
875 self.res
876 }
877
878 #[inline]
880 pub fn discard_err(self) -> Option<T> {
881 self.disarm().ok()
882 }
883
884 #[inline]
887 pub fn report_err(self) -> Result<T, InterpErrorInfo<'tcx>> {
888 self.disarm()
889 }
890
891 #[inline]
892 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> InterpResult<'tcx, U> {
893 InterpResult_::new(self.disarm().map(f))
894 }
895
896 #[inline]
897 pub fn map_err_info(
898 self,
899 f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>,
900 ) -> InterpResult<'tcx, T> {
901 InterpResult_::new(self.disarm().map_err(f))
902 }
903
904 #[inline]
905 pub fn map_err_kind(
906 self,
907 f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
908 ) -> InterpResult<'tcx, T> {
909 InterpResult_::new(self.disarm().map_err(|mut e| {
910 e.0.kind = f(e.0.kind);
911 e
912 }))
913 }
914
915 #[inline]
916 pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> {
917 InterpResult_::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
918 }
919
920 #[inline]
921 #[track_caller]
922 pub fn unwrap(self) -> T {
923 self.disarm().unwrap()
924 }
925
926 #[inline]
927 #[track_caller]
928 pub fn unwrap_or_else(self, f: impl FnOnce(InterpErrorInfo<'tcx>) -> T) -> T {
929 self.disarm().unwrap_or_else(f)
930 }
931
932 #[inline]
933 #[track_caller]
934 pub fn expect(self, msg: &str) -> T {
935 self.disarm().expect(msg)
936 }
937
938 #[inline]
939 pub fn and_then<U>(self, f: impl FnOnce(T) -> InterpResult<'tcx, U>) -> InterpResult<'tcx, U> {
940 InterpResult_::new(self.disarm().and_then(|t| f(t).disarm()))
941 }
942
943 #[inline]
948 pub fn and<U>(self, other: InterpResult<'tcx, U>) -> InterpResult<'tcx, (T, U)> {
949 match self.disarm() {
950 Ok(t) => interp_ok((t, other?)),
951 Err(e) => {
952 drop(other.disarm());
954 InterpResult_::new(Err(e))
956 }
957 }
958 }
959}
960
961#[inline(always)]
962pub fn interp_ok<'tcx, T>(x: T) -> InterpResult<'tcx, T> {
963 InterpResult_::new(Ok(x))
964}