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