Skip to main content

rustc_public/unstable/convert/stable/
mir.rs

1//! Conversion of internal Rust compiler `mir` items to stable ones.
2
3use rustc_middle::mir;
4use rustc_middle::mono::MonoItem;
5use rustc_public_bridge::context::CompilerCtxt;
6use rustc_public_bridge::{Tables, bridge};
7use rustc_span::bug;
8
9use crate::compiler_interface::BridgeTys;
10use crate::mir::alloc::GlobalAlloc;
11use crate::mir::{
12    ConstOperand, SourceScopeInfo, Statement, UserTypeProjection, VarDebugInfoFragment,
13};
14use crate::ty::{Allocation, ConstantKind, MirConst};
15use crate::unstable::Stable;
16use crate::{Error, alloc, opaque};
17
18impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
19    type T = crate::mir::Body;
20
21    fn stable<'cx>(
22        &self,
23        tables: &mut Tables<'cx, BridgeTys>,
24        cx: &CompilerCtxt<'cx, BridgeTys>,
25    ) -> Self::T {
26        crate::mir::Body {
27            blocks: self
28                .basic_blocks
29                .iter()
30                .map(|block| crate::mir::BasicBlock {
31                    terminator: block.terminator().stable(tables, cx),
32                    statements: block
33                        .statements
34                        .iter()
35                        .map(|statement| statement.stable(tables, cx))
36                        .collect(),
37                })
38                .collect(),
39            locals: self
40                .local_decls
41                .iter()
42                .map(|decl| crate::mir::LocalDecl {
43                    ty: decl.ty.stable(tables, cx),
44                    span: decl.source_info.span.stable(tables, cx),
45                    mutability: decl.mutability.stable(tables, cx),
46                })
47                .collect(),
48            arg_count: self.arg_count,
49            var_debug_info: self
50                .var_debug_info
51                .iter()
52                .map(|info| info.stable(tables, cx))
53                .collect(),
54            spread_arg: self.spread_arg.stable(tables, cx),
55            span: self.span.stable(tables, cx),
56            source_scopes: self
57                .source_scopes
58                .iter()
59                .map(|scope_data| SourceScopeInfo {
60                    inlined: scope_data.inlined.map(|(instance, span)| {
61                        (instance.def.requires_caller_location(cx.tcx), span.stable(tables, cx))
62                    }),
63                    inlined_parent_scope: scope_data.inlined_parent_scope.map(|s| s.as_u32()),
64                })
65                .collect(),
66        }
67    }
68}
69
70impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
71    type T = crate::mir::VarDebugInfo;
72    fn stable<'cx>(
73        &self,
74        tables: &mut Tables<'cx, BridgeTys>,
75        cx: &CompilerCtxt<'cx, BridgeTys>,
76    ) -> Self::T {
77        crate::mir::VarDebugInfo {
78            name: self.name.to_string(),
79            source_info: self.source_info.stable(tables, cx),
80            composite: self.composite.as_ref().map(|composite| composite.stable(tables, cx)),
81            value: self.value.stable(tables, cx),
82            argument_index: self.argument_index,
83        }
84    }
85}
86
87impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
88    type T = crate::mir::Statement;
89    fn stable<'cx>(
90        &self,
91        tables: &mut Tables<'cx, BridgeTys>,
92        cx: &CompilerCtxt<'cx, BridgeTys>,
93    ) -> Self::T {
94        Statement {
95            kind: self.kind.stable(tables, cx),
96            source_info: self.source_info.stable(tables, cx),
97        }
98    }
99}
100
101impl<'tcx> Stable<'tcx> for mir::SourceInfo {
102    type T = crate::mir::SourceInfo;
103    fn stable<'cx>(
104        &self,
105        tables: &mut Tables<'cx, BridgeTys>,
106        cx: &CompilerCtxt<'cx, BridgeTys>,
107    ) -> Self::T {
108        crate::mir::SourceInfo { span: self.span.stable(tables, cx), scope: self.scope.into() }
109    }
110}
111
112impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
113    type T = crate::mir::VarDebugInfoFragment;
114    fn stable<'cx>(
115        &self,
116        tables: &mut Tables<'cx, BridgeTys>,
117        cx: &CompilerCtxt<'cx, BridgeTys>,
118    ) -> Self::T {
119        VarDebugInfoFragment {
120            ty: self.ty.stable(tables, cx),
121            projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(),
122        }
123    }
124}
125
126impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
127    type T = crate::mir::VarDebugInfoContents;
128    fn stable<'cx>(
129        &self,
130        tables: &mut Tables<'cx, BridgeTys>,
131        cx: &CompilerCtxt<'cx, BridgeTys>,
132    ) -> Self::T {
133        match self {
134            mir::VarDebugInfoContents::Place(place) => {
135                crate::mir::VarDebugInfoContents::Place(place.stable(tables, cx))
136            }
137            mir::VarDebugInfoContents::Const(const_operand) => {
138                let op = ConstOperand {
139                    span: const_operand.span.stable(tables, cx),
140                    user_ty: const_operand.user_ty.map(|index| index.as_usize()),
141                    const_: const_operand.const_.stable(tables, cx),
142                };
143                crate::mir::VarDebugInfoContents::Const(op)
144            }
145        }
146    }
147}
148
149impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
150    type T = crate::mir::StatementKind;
151    fn stable<'cx>(
152        &self,
153        tables: &mut Tables<'cx, BridgeTys>,
154        cx: &CompilerCtxt<'cx, BridgeTys>,
155    ) -> Self::T {
156        match self {
157            mir::StatementKind::Assign(assign) => crate::mir::StatementKind::Assign(
158                assign.0.stable(tables, cx),
159                assign.1.stable(tables, cx),
160            ),
161            mir::StatementKind::FakeRead(fake_read_place) => crate::mir::StatementKind::FakeRead(
162                fake_read_place.0.stable(tables, cx),
163                fake_read_place.1.stable(tables, cx),
164            ),
165            mir::StatementKind::SetDiscriminant { place, variant_index } => {
166                crate::mir::StatementKind::SetDiscriminant {
167                    place: place.as_ref().stable(tables, cx),
168                    variant_index: variant_index.stable(tables, cx),
169                }
170            }
171
172            mir::StatementKind::StorageLive(place) => {
173                crate::mir::StatementKind::StorageLive(place.stable(tables, cx))
174            }
175
176            mir::StatementKind::StorageDead(place) => {
177                crate::mir::StatementKind::StorageDead(place.stable(tables, cx))
178            }
179            mir::StatementKind::PlaceMention(place) => {
180                crate::mir::StatementKind::PlaceMention(place.stable(tables, cx))
181            }
182            mir::StatementKind::AscribeUserType(place_projection, variance) => {
183                crate::mir::StatementKind::AscribeUserType {
184                    place: place_projection.as_ref().0.stable(tables, cx),
185                    projections: place_projection.as_ref().1.stable(tables, cx),
186                    variance: variance.stable(tables, cx),
187                }
188            }
189            mir::StatementKind::Coverage(coverage) => {
190                crate::mir::StatementKind::Coverage(opaque(coverage))
191            }
192            mir::StatementKind::Intrinsic(intrinstic) => {
193                crate::mir::StatementKind::Intrinsic(intrinstic.stable(tables, cx))
194            }
195            mir::StatementKind::ConstEvalCounter => crate::mir::StatementKind::ConstEvalCounter,
196            // BackwardIncompatibleDropHint has no semantics, so it is translated to Nop.
197            mir::StatementKind::BackwardIncompatibleDropHint { .. } => {
198                crate::mir::StatementKind::Nop
199            }
200            mir::StatementKind::Nop => crate::mir::StatementKind::Nop,
201        }
202    }
203}
204
205impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
206    type T = crate::mir::Rvalue;
207    fn stable<'cx>(
208        &self,
209        tables: &mut Tables<'cx, BridgeTys>,
210        cx: &CompilerCtxt<'cx, BridgeTys>,
211    ) -> Self::T {
212        use rustc_middle::mir::Rvalue::*;
213        match self {
214            Use(op, retag) => {
215                crate::mir::Rvalue::Use(op.stable(tables, cx), retag.stable(tables, cx))
216            }
217            Repeat(op, len) => {
218                let len = len.stable(tables, cx);
219                crate::mir::Rvalue::Repeat(op.stable(tables, cx), len)
220            }
221            Ref(region, kind, place) => crate::mir::Rvalue::Ref(
222                region.stable(tables, cx),
223                kind.stable(tables, cx),
224                place.stable(tables, cx),
225            ),
226            Reborrow(target, kind, place) => crate::mir::Rvalue::Reborrow(
227                target.stable(tables, cx),
228                kind.stable(tables, cx),
229                place.stable(tables, cx),
230            ),
231            ThreadLocalRef(def_id) => {
232                crate::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id))
233            }
234            RawPtr(mutability, place) => crate::mir::Rvalue::AddressOf(
235                mutability.stable(tables, cx),
236                place.stable(tables, cx),
237            ),
238            Cast(cast_kind, op, ty) => crate::mir::Rvalue::Cast(
239                cast_kind.stable(tables, cx),
240                op.stable(tables, cx),
241                ty.stable(tables, cx),
242            ),
243            BinaryOp(bin_op, ops) => {
244                if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
245                    crate::mir::Rvalue::CheckedBinaryOp(
246                        bin_op.stable(tables, cx),
247                        ops.0.stable(tables, cx),
248                        ops.1.stable(tables, cx),
249                    )
250                } else {
251                    crate::mir::Rvalue::BinaryOp(
252                        bin_op.stable(tables, cx),
253                        ops.0.stable(tables, cx),
254                        ops.1.stable(tables, cx),
255                    )
256                }
257            }
258            UnaryOp(un_op, op) => {
259                crate::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx))
260            }
261            Discriminant(place) => crate::mir::Rvalue::Discriminant(place.stable(tables, cx)),
262            Aggregate(agg_kind, operands) => {
263                let operands = operands.iter().map(|op| op.stable(tables, cx)).collect();
264                crate::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands)
265            }
266            CopyForDeref(place) => crate::mir::Rvalue::CopyForDeref(place.stable(tables, cx)),
267            WrapUnsafeBinder(..) => {
    ::core::panicking::panic_fmt(format_args!("not implemented: {0}",
            format_args!("FIXME(unsafe_binders):")));
}unimplemented!("FIXME(unsafe_binders):"),
268        }
269    }
270}
271
272impl<'tcx> Stable<'tcx> for mir::Mutability {
273    type T = crate::mir::Mutability;
274    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
275        use rustc_hir::Mutability::*;
276        match *self {
277            Not => crate::mir::Mutability::Not,
278            Mut => crate::mir::Mutability::Mut,
279        }
280    }
281}
282
283impl<'tcx> Stable<'tcx> for mir::RawPtrKind {
284    type T = crate::mir::RawPtrKind;
285    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
286        use mir::RawPtrKind::*;
287        match *self {
288            Const => crate::mir::RawPtrKind::Const,
289            Mut => crate::mir::RawPtrKind::Mut,
290            FakeForPtrMetadata => crate::mir::RawPtrKind::FakeForPtrMetadata,
291        }
292    }
293}
294
295impl<'tcx> Stable<'tcx> for mir::BorrowKind {
296    type T = crate::mir::BorrowKind;
297    fn stable<'cx>(
298        &self,
299        tables: &mut Tables<'cx, BridgeTys>,
300        cx: &CompilerCtxt<'cx, BridgeTys>,
301    ) -> Self::T {
302        use rustc_middle::mir::BorrowKind::*;
303        match *self {
304            Shared => crate::mir::BorrowKind::Shared,
305            Fake(kind) => crate::mir::BorrowKind::Fake(kind.stable(tables, cx)),
306            Mut { kind } => crate::mir::BorrowKind::Mut { kind: kind.stable(tables, cx) },
307        }
308    }
309}
310
311impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
312    type T = crate::mir::MutBorrowKind;
313    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
314        use rustc_middle::mir::MutBorrowKind::*;
315        match *self {
316            Default => crate::mir::MutBorrowKind::Default,
317            TwoPhaseBorrow => crate::mir::MutBorrowKind::TwoPhaseBorrow,
318            ClosureCapture => crate::mir::MutBorrowKind::ClosureCapture,
319        }
320    }
321}
322
323impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
324    type T = crate::mir::FakeBorrowKind;
325    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
326        use rustc_middle::mir::FakeBorrowKind::*;
327        match *self {
328            Deep => crate::mir::FakeBorrowKind::Deep,
329            Shallow => crate::mir::FakeBorrowKind::Shallow,
330        }
331    }
332}
333
334impl<'tcx> Stable<'tcx> for mir::RuntimeChecks {
335    type T = crate::mir::RuntimeChecks;
336    fn stable<'cx>(
337        &self,
338        _: &mut Tables<'cx, BridgeTys>,
339        _: &CompilerCtxt<'cx, BridgeTys>,
340    ) -> Self::T {
341        use rustc_middle::mir::RuntimeChecks::*;
342        match self {
343            UbChecks => crate::mir::RuntimeChecks::UbChecks,
344            ContractChecks => crate::mir::RuntimeChecks::ContractChecks,
345            OverflowChecks => crate::mir::RuntimeChecks::OverflowChecks,
346        }
347    }
348}
349
350impl<'tcx> Stable<'tcx> for mir::CastKind {
351    type T = crate::mir::CastKind;
352    fn stable<'cx>(
353        &self,
354        tables: &mut Tables<'cx, BridgeTys>,
355        cx: &CompilerCtxt<'cx, BridgeTys>,
356    ) -> Self::T {
357        use rustc_middle::mir::CastKind::*;
358        match self {
359            PointerExposeProvenance => crate::mir::CastKind::PointerExposeAddress,
360            PointerWithExposedProvenance => crate::mir::CastKind::PointerWithExposedProvenance,
361            PointerCoercion(c, _) => crate::mir::CastKind::PointerCoercion(c.stable(tables, cx)),
362            IntToInt => crate::mir::CastKind::IntToInt,
363            FloatToInt => crate::mir::CastKind::FloatToInt,
364            FloatToFloat => crate::mir::CastKind::FloatToFloat,
365            IntToFloat => crate::mir::CastKind::IntToFloat,
366            PtrToPtr => crate::mir::CastKind::PtrToPtr,
367            FnPtrToPtr => crate::mir::CastKind::FnPtrToPtr,
368            Transmute => crate::mir::CastKind::Transmute,
369            BoxDerefTransmute => crate::mir::CastKind::BoxDerefTransmute,
370            Subtype => crate::mir::CastKind::Subtype,
371        }
372    }
373}
374
375impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
376    type T = crate::mir::FakeReadCause;
377    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
378        use rustc_middle::mir::FakeReadCause::*;
379        match self {
380            ForMatchGuard => crate::mir::FakeReadCause::ForMatchGuard,
381            ForMatchedPlace(local_def_id) => {
382                crate::mir::FakeReadCause::ForMatchedPlace(opaque(local_def_id))
383            }
384            ForGuardBinding => crate::mir::FakeReadCause::ForGuardBinding,
385            ForLet(local_def_id) => crate::mir::FakeReadCause::ForLet(opaque(local_def_id)),
386            ForIndex => crate::mir::FakeReadCause::ForIndex,
387        }
388    }
389}
390
391impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
392    type T = crate::mir::Operand;
393    fn stable<'cx>(
394        &self,
395        tables: &mut Tables<'cx, BridgeTys>,
396        cx: &CompilerCtxt<'cx, BridgeTys>,
397    ) -> Self::T {
398        use rustc_middle::mir::Operand::*;
399        match self {
400            Copy(place) => crate::mir::Operand::Copy(place.stable(tables, cx)),
401            Move(place) => crate::mir::Operand::Move(place.stable(tables, cx)),
402            Constant(c) => crate::mir::Operand::Constant(c.stable(tables, cx)),
403            RuntimeChecks(c) => crate::mir::Operand::RuntimeChecks(c.stable(tables, cx)),
404        }
405    }
406}
407
408impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
409    type T = crate::mir::ConstOperand;
410
411    fn stable<'cx>(
412        &self,
413        tables: &mut Tables<'cx, BridgeTys>,
414        cx: &CompilerCtxt<'cx, BridgeTys>,
415    ) -> Self::T {
416        crate::mir::ConstOperand {
417            span: self.span.stable(tables, cx),
418            user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
419            const_: self.const_.stable(tables, cx),
420        }
421    }
422}
423
424impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
425    type T = crate::mir::Place;
426    fn stable<'cx>(
427        &self,
428        tables: &mut Tables<'cx, BridgeTys>,
429        cx: &CompilerCtxt<'cx, BridgeTys>,
430    ) -> Self::T {
431        crate::mir::Place {
432            local: self.local.as_usize(),
433            projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(),
434        }
435    }
436}
437
438impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
439    type T = crate::mir::ProjectionElem;
440    fn stable<'cx>(
441        &self,
442        tables: &mut Tables<'cx, BridgeTys>,
443        cx: &CompilerCtxt<'cx, BridgeTys>,
444    ) -> Self::T {
445        use rustc_middle::mir::ProjectionElem::*;
446        match self {
447            Deref => crate::mir::ProjectionElem::Deref,
448            PhantomDeref => bug_impl(None, format_args!("Hopefully we don\'t come here"),
    Location::caller())bug!("Hopefully we don't come here"),
449            Field(idx, ty) => {
450                crate::mir::ProjectionElem::Field(idx.stable(tables, cx), ty.stable(tables, cx))
451            }
452            Index(local) => crate::mir::ProjectionElem::Index(local.stable(tables, cx)),
453            ConstantIndex { offset, min_length, from_end } => {
454                crate::mir::ProjectionElem::ConstantIndex {
455                    offset: *offset,
456                    min_length: *min_length,
457                    from_end: *from_end,
458                }
459            }
460            Subslice { from, to, from_end } => {
461                crate::mir::ProjectionElem::Subslice { from: *from, to: *to, from_end: *from_end }
462            }
463            // MIR includes an `Option<Symbol>` argument for `Downcast` that is the name of the
464            // variant, used for printing MIR. However this information should also be accessible
465            // via a lookup using the `VariantIdx`. The `Option<Symbol>` argument is therefore
466            // dropped when converting to Stable MIR. A brief justification for this decision can be
467            // found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486
468            Downcast(_, idx) => crate::mir::ProjectionElem::Downcast(idx.stable(tables, cx)),
469            OpaqueCast(ty) => crate::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)),
470            UnwrapUnsafeBinder(..) => {
    ::core::panicking::panic_fmt(format_args!("not implemented: {0}",
            format_args!("FIXME(unsafe_binders):")));
}unimplemented!("FIXME(unsafe_binders):"),
471        }
472    }
473}
474
475impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
476    type T = crate::mir::UserTypeProjection;
477
478    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
479        UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) }
480    }
481}
482
483impl<'tcx> Stable<'tcx> for mir::Local {
484    type T = crate::mir::Local;
485    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
486        self.as_usize()
487    }
488}
489
490impl<'tcx> Stable<'tcx> for mir::WithRetag {
491    type T = crate::mir::WithRetag;
492    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
493        use rustc_middle::mir::WithRetag;
494        match self {
495            WithRetag::Yes => crate::mir::WithRetag::Yes,
496            WithRetag::No => crate::mir::WithRetag::No,
497        }
498    }
499}
500
501impl<'tcx> Stable<'tcx> for mir::UnwindAction {
502    type T = crate::mir::UnwindAction;
503    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
504        use rustc_middle::mir::UnwindAction;
505        match self {
506            UnwindAction::Continue => crate::mir::UnwindAction::Continue,
507            UnwindAction::Unreachable => crate::mir::UnwindAction::Unreachable,
508            UnwindAction::Terminate(_) => crate::mir::UnwindAction::Terminate,
509            UnwindAction::Cleanup(bb) => crate::mir::UnwindAction::Cleanup(bb.as_usize()),
510        }
511    }
512}
513
514impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
515    type T = crate::mir::NonDivergingIntrinsic;
516
517    fn stable<'cx>(
518        &self,
519        tables: &mut Tables<'cx, BridgeTys>,
520        cx: &CompilerCtxt<'cx, BridgeTys>,
521    ) -> Self::T {
522        use rustc_middle::mir::NonDivergingIntrinsic;
523
524        use crate::mir::CopyNonOverlapping;
525        match self {
526            NonDivergingIntrinsic::Assume(op) => {
527                crate::mir::NonDivergingIntrinsic::Assume(op.stable(tables, cx))
528            }
529            NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => {
530                crate::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
531                    src: copy_non_overlapping.src.stable(tables, cx),
532                    dst: copy_non_overlapping.dst.stable(tables, cx),
533                    count: copy_non_overlapping.count.stable(tables, cx),
534                })
535            }
536        }
537    }
538}
539
540impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
541    type T = crate::mir::AssertMessage;
542    fn stable<'cx>(
543        &self,
544        tables: &mut Tables<'cx, BridgeTys>,
545        cx: &CompilerCtxt<'cx, BridgeTys>,
546    ) -> Self::T {
547        use rustc_middle::mir::AssertKind;
548        match self {
549            AssertKind::BoundsCheck { len, index } => crate::mir::AssertMessage::BoundsCheck {
550                len: len.stable(tables, cx),
551                index: index.stable(tables, cx),
552            },
553            AssertKind::Overflow(bin_op, op1, op2) => crate::mir::AssertMessage::Overflow(
554                bin_op.stable(tables, cx),
555                op1.stable(tables, cx),
556                op2.stable(tables, cx),
557            ),
558            AssertKind::OverflowNeg(op) => {
559                crate::mir::AssertMessage::OverflowNeg(op.stable(tables, cx))
560            }
561            AssertKind::DivisionByZero(op) => {
562                crate::mir::AssertMessage::DivisionByZero(op.stable(tables, cx))
563            }
564            AssertKind::RemainderByZero(op) => {
565                crate::mir::AssertMessage::RemainderByZero(op.stable(tables, cx))
566            }
567            AssertKind::ResumedAfterReturn(coroutine) => {
568                crate::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables, cx))
569            }
570            AssertKind::ResumedAfterPanic(coroutine) => {
571                crate::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables, cx))
572            }
573            AssertKind::ResumedAfterDrop(coroutine) => {
574                crate::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables, cx))
575            }
576            AssertKind::MisalignedPointerDereference { required, found } => {
577                crate::mir::AssertMessage::MisalignedPointerDereference {
578                    required: required.stable(tables, cx),
579                    found: found.stable(tables, cx),
580                }
581            }
582            AssertKind::NullPointerDereference => crate::mir::AssertMessage::NullPointerDereference,
583            AssertKind::NullReferenceConstructed => {
584                crate::mir::AssertMessage::NullReferenceConstructed
585            }
586            AssertKind::InvalidEnumConstruction(source) => {
587                crate::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx))
588            }
589        }
590    }
591}
592
593impl<'tcx> Stable<'tcx> for mir::BinOp {
594    type T = crate::mir::BinOp;
595    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
596        use rustc_middle::mir::BinOp;
597        match self {
598            BinOp::Add => crate::mir::BinOp::Add,
599            BinOp::AddUnchecked => crate::mir::BinOp::AddUnchecked,
600            BinOp::AddWithOverflow => bug_impl(None,
    format_args!("AddWithOverflow should have been translated already"),
    Location::caller())bug!("AddWithOverflow should have been translated already"),
601            BinOp::Sub => crate::mir::BinOp::Sub,
602            BinOp::SubUnchecked => crate::mir::BinOp::SubUnchecked,
603            BinOp::SubWithOverflow => bug_impl(None,
    format_args!("AddWithOverflow should have been translated already"),
    Location::caller())bug!("AddWithOverflow should have been translated already"),
604            BinOp::Mul => crate::mir::BinOp::Mul,
605            BinOp::MulUnchecked => crate::mir::BinOp::MulUnchecked,
606            BinOp::MulWithOverflow => bug_impl(None,
    format_args!("AddWithOverflow should have been translated already"),
    Location::caller())bug!("AddWithOverflow should have been translated already"),
607            BinOp::Div => crate::mir::BinOp::Div,
608            BinOp::Rem => crate::mir::BinOp::Rem,
609            BinOp::BitXor => crate::mir::BinOp::BitXor,
610            BinOp::BitAnd => crate::mir::BinOp::BitAnd,
611            BinOp::BitOr => crate::mir::BinOp::BitOr,
612            BinOp::Shl => crate::mir::BinOp::Shl,
613            BinOp::ShlUnchecked => crate::mir::BinOp::ShlUnchecked,
614            BinOp::Shr => crate::mir::BinOp::Shr,
615            BinOp::ShrUnchecked => crate::mir::BinOp::ShrUnchecked,
616            BinOp::Eq => crate::mir::BinOp::Eq,
617            BinOp::Lt => crate::mir::BinOp::Lt,
618            BinOp::Le => crate::mir::BinOp::Le,
619            BinOp::Ne => crate::mir::BinOp::Ne,
620            BinOp::Ge => crate::mir::BinOp::Ge,
621            BinOp::Gt => crate::mir::BinOp::Gt,
622            BinOp::Cmp => crate::mir::BinOp::Cmp,
623            BinOp::Offset => crate::mir::BinOp::Offset,
624        }
625    }
626}
627
628impl<'tcx> Stable<'tcx> for mir::UnOp {
629    type T = crate::mir::UnOp;
630    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
631        use rustc_middle::mir::UnOp;
632        match self {
633            UnOp::Not => crate::mir::UnOp::Not,
634            UnOp::Neg => crate::mir::UnOp::Neg,
635            UnOp::PtrMetadata => crate::mir::UnOp::PtrMetadata,
636        }
637    }
638}
639
640impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
641    type T = crate::mir::AggregateKind;
642    fn stable<'cx>(
643        &self,
644        tables: &mut Tables<'cx, BridgeTys>,
645        cx: &CompilerCtxt<'cx, BridgeTys>,
646    ) -> Self::T {
647        match self {
648            mir::AggregateKind::Array(ty) => {
649                crate::mir::AggregateKind::Array(ty.stable(tables, cx))
650            }
651            mir::AggregateKind::Tuple => crate::mir::AggregateKind::Tuple,
652            mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => {
653                crate::mir::AggregateKind::Adt(
654                    tables.adt_def(*def_id),
655                    var_idx.stable(tables, cx),
656                    generic_arg.stable(tables, cx),
657                    user_ty_index.map(|idx| idx.index()),
658                    field_idx.map(|idx| idx.index()),
659                )
660            }
661            mir::AggregateKind::Closure(def_id, generic_arg) => crate::mir::AggregateKind::Closure(
662                tables.closure_def(*def_id),
663                generic_arg.stable(tables, cx),
664            ),
665            mir::AggregateKind::Coroutine(def_id, generic_arg) => {
666                crate::mir::AggregateKind::Coroutine(
667                    tables.coroutine_def(*def_id),
668                    generic_arg.stable(tables, cx),
669                )
670            }
671            mir::AggregateKind::CoroutineClosure(def_id, generic_args) => {
672                crate::mir::AggregateKind::CoroutineClosure(
673                    tables.coroutine_closure_def(*def_id),
674                    generic_args.stable(tables, cx),
675                )
676            }
677            mir::AggregateKind::RawPtr(ty, mutability) => crate::mir::AggregateKind::RawPtr(
678                ty.stable(tables, cx),
679                mutability.stable(tables, cx),
680            ),
681        }
682    }
683}
684
685impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
686    type T = crate::mir::InlineAsmOperand;
687    fn stable<'cx>(
688        &self,
689        tables: &mut Tables<'cx, BridgeTys>,
690        cx: &CompilerCtxt<'cx, BridgeTys>,
691    ) -> Self::T {
692        use rustc_middle::mir::InlineAsmOperand;
693
694        let (in_value, out_place) = match self {
695            InlineAsmOperand::In { value, .. } => (Some(value.stable(tables, cx)), None),
696            InlineAsmOperand::Out { place, .. } => {
697                (None, place.map(|place| place.stable(tables, cx)))
698            }
699            InlineAsmOperand::InOut { in_value, out_place, .. } => {
700                (Some(in_value.stable(tables, cx)), out_place.map(|place| place.stable(tables, cx)))
701            }
702            InlineAsmOperand::Const { .. }
703            | InlineAsmOperand::SymFn { .. }
704            | InlineAsmOperand::SymStatic { .. }
705            | InlineAsmOperand::Label { .. } => (None, None),
706        };
707
708        crate::mir::InlineAsmOperand { in_value, out_place, raw_rpr: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", self))
    })format!("{self:?}") }
709    }
710}
711
712impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
713    type T = crate::mir::Terminator;
714    fn stable<'cx>(
715        &self,
716        tables: &mut Tables<'cx, BridgeTys>,
717        cx: &CompilerCtxt<'cx, BridgeTys>,
718    ) -> Self::T {
719        use crate::mir::Terminator;
720        Terminator {
721            kind: self.kind.stable(tables, cx),
722            source_info: self.source_info.stable(tables, cx),
723        }
724    }
725}
726
727impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
728    type T = crate::mir::TerminatorKind;
729    fn stable<'cx>(
730        &self,
731        tables: &mut Tables<'cx, BridgeTys>,
732        cx: &CompilerCtxt<'cx, BridgeTys>,
733    ) -> Self::T {
734        use crate::mir::TerminatorKind;
735        match self {
736            mir::TerminatorKind::Goto { target } => {
737                TerminatorKind::Goto { target: target.as_usize() }
738            }
739            mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
740                discr: discr.stable(tables, cx),
741                targets: {
742                    let branches = targets.iter().map(|(val, target)| (val, target.as_usize()));
743                    crate::mir::SwitchTargets::new(
744                        branches.collect(),
745                        targets.otherwise().as_usize(),
746                    )
747                },
748            },
749            mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,
750            mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort,
751            mir::TerminatorKind::Return => TerminatorKind::Return,
752            mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable,
753            mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop: _ } => {
754                TerminatorKind::Drop {
755                    place: place.stable(tables, cx),
756                    target: target.as_usize(),
757                    unwind: unwind.stable(tables, cx),
758                }
759            }
760            mir::TerminatorKind::Call {
761                func,
762                args,
763                destination,
764                target,
765                unwind,
766                call_source: _,
767                fn_span: _,
768            } => TerminatorKind::Call {
769                func: func.stable(tables, cx),
770                args: args.iter().map(|arg| arg.node.stable(tables, cx)).collect(),
771                destination: destination.stable(tables, cx),
772                target: target.map(|t| t.as_usize()),
773                unwind: unwind.stable(tables, cx),
774            },
775            mir::TerminatorKind::TailCall { func: _, args: _, fn_span: _ } => ::core::panicking::panic("not implemented")unimplemented!(),
776            mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
777                TerminatorKind::Assert {
778                    cond: cond.stable(tables, cx),
779                    expected: *expected,
780                    msg: msg.stable(tables, cx),
781                    target: target.as_usize(),
782                    unwind: unwind.stable(tables, cx),
783                }
784            }
785            mir::TerminatorKind::InlineAsm {
786                asm_macro: _,
787                template,
788                operands,
789                options,
790                line_spans,
791                targets,
792                unwind,
793            } => TerminatorKind::InlineAsm {
794                template: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", template))
    })format!("{template:?}"),
795                operands: operands.iter().map(|operand| operand.stable(tables, cx)).collect(),
796                options: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", options))
    })format!("{options:?}"),
797                line_spans: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", line_spans))
    })format!("{line_spans:?}"),
798                // FIXME: Figure out how to do labels in SMIR
799                destination: targets.first().map(|d| d.as_usize()),
800                unwind: unwind.stable(tables, cx),
801            },
802            mir::TerminatorKind::Yield { .. }
803            | mir::TerminatorKind::CoroutineDrop
804            | mir::TerminatorKind::FalseEdge { .. }
805            | mir::TerminatorKind::FalseUnwind { .. } => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
806        }
807    }
808}
809
810impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
811    type T = Allocation;
812
813    fn stable<'cx>(
814        &self,
815        tables: &mut Tables<'cx, BridgeTys>,
816        cx: &CompilerCtxt<'cx, BridgeTys>,
817    ) -> Self::T {
818        self.inner().stable(tables, cx)
819    }
820}
821
822impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
823    type T = crate::ty::Allocation;
824
825    fn stable<'cx>(
826        &self,
827        tables: &mut Tables<'cx, BridgeTys>,
828        cx: &CompilerCtxt<'cx, BridgeTys>,
829    ) -> Self::T {
830        use rustc_public_bridge::context::AllocRangeHelpers;
831        alloc::allocation_filter(
832            self,
833            cx.alloc_range(rustc_abi::Size::ZERO, self.size()),
834            tables,
835            cx,
836        )
837    }
838}
839
840impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
841    type T = crate::mir::alloc::AllocId;
842    fn stable<'cx>(
843        &self,
844        tables: &mut Tables<'cx, BridgeTys>,
845        _: &CompilerCtxt<'cx, BridgeTys>,
846    ) -> Self::T {
847        tables.create_alloc_id(*self)
848    }
849}
850
851impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
852    type T = GlobalAlloc;
853
854    fn stable<'cx>(
855        &self,
856        tables: &mut Tables<'cx, BridgeTys>,
857        cx: &CompilerCtxt<'cx, BridgeTys>,
858    ) -> Self::T {
859        match self {
860            mir::interpret::GlobalAlloc::Function { instance, .. } => {
861                GlobalAlloc::Function(instance.stable(tables, cx))
862            }
863            mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => {
864                // FIXME: Should we record the whole vtable?
865                GlobalAlloc::VTable(ty.stable(tables, cx), dyn_ty.principal().stable(tables, cx))
866            }
867            mir::interpret::GlobalAlloc::Static(def) => {
868                GlobalAlloc::Static(tables.static_def(*def))
869            }
870            mir::interpret::GlobalAlloc::Memory(alloc) => {
871                GlobalAlloc::Memory(alloc.stable(tables, cx))
872            }
873            mir::interpret::GlobalAlloc::TypeId { ty } => {
874                GlobalAlloc::TypeId { ty: ty.stable(tables, cx) }
875            }
876        }
877    }
878}
879
880impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
881    type T = crate::ty::MirConst;
882
883    fn stable<'cx>(
884        &self,
885        tables: &mut Tables<'cx, BridgeTys>,
886        cx: &CompilerCtxt<'cx, BridgeTys>,
887    ) -> Self::T {
888        let id = tables.intern_mir_const(cx.lift(*self));
889        match *self {
890            mir::Const::Ty(ty, c) => MirConst::new(
891                crate::ty::ConstantKind::Ty(c.stable(tables, cx)),
892                ty.stable(tables, cx),
893                id,
894            ),
895            mir::Const::Unevaluated(unev_const, ty) => {
896                let kind = crate::ty::ConstantKind::Unevaluated(crate::ty::UnevaluatedConst {
897                    def: tables.const_def(unev_const.def),
898                    args: unev_const.args.stable(tables, cx),
899                    promoted: unev_const.promoted.map(|u| u.as_u32()),
900                });
901                let ty = ty.stable(tables, cx);
902                MirConst::new(kind, ty, id)
903            }
904            mir::Const::Val(mir::ConstValue::ZeroSized, ty) => {
905                let ty = ty.stable(tables, cx);
906                MirConst::new(ConstantKind::ZeroSized, ty, id)
907            }
908            mir::Const::Val(val, ty) => {
909                let ty = cx.lift(ty);
910                let val = cx.lift(val);
911                let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables, cx));
912                let ty = ty.stable(tables, cx);
913                MirConst::new(kind, ty, id)
914            }
915        }
916    }
917}
918
919impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
920    type T = Error;
921
922    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
923        bridge::Error::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", self))
    })format!("{self:?}"))
924    }
925}
926
927impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
928    type T = crate::mir::mono::MonoItem;
929
930    fn stable<'cx>(
931        &self,
932        tables: &mut Tables<'cx, BridgeTys>,
933        cx: &CompilerCtxt<'cx, BridgeTys>,
934    ) -> Self::T {
935        use crate::mir::mono::MonoItem as StableMonoItem;
936        match self {
937            MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables, cx)),
938            MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
939            MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
940        }
941    }
942}