rustc_public/unstable/convert/stable/
mir.rs

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