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            Cast(cast_kind, op, ty) => crate::mir::Rvalue::Cast(
219                cast_kind.stable(tables, cx),
220                op.stable(tables, cx),
221                ty.stable(tables, cx),
222            ),
223            BinaryOp(bin_op, ops) => {
224                if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
225                    crate::mir::Rvalue::CheckedBinaryOp(
226                        bin_op.stable(tables, cx),
227                        ops.0.stable(tables, cx),
228                        ops.1.stable(tables, cx),
229                    )
230                } else {
231                    crate::mir::Rvalue::BinaryOp(
232                        bin_op.stable(tables, cx),
233                        ops.0.stable(tables, cx),
234                        ops.1.stable(tables, cx),
235                    )
236                }
237            }
238            NullaryOp(null_op, ty) => {
239                crate::mir::Rvalue::NullaryOp(null_op.stable(tables, cx), ty.stable(tables, cx))
240            }
241            UnaryOp(un_op, op) => {
242                crate::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx))
243            }
244            Discriminant(place) => crate::mir::Rvalue::Discriminant(place.stable(tables, cx)),
245            Aggregate(agg_kind, operands) => {
246                let operands = operands.iter().map(|op| op.stable(tables, cx)).collect();
247                crate::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands)
248            }
249            ShallowInitBox(op, ty) => {
250                crate::mir::Rvalue::ShallowInitBox(op.stable(tables, cx), ty.stable(tables, cx))
251            }
252            CopyForDeref(place) => crate::mir::Rvalue::CopyForDeref(place.stable(tables, cx)),
253            WrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
254        }
255    }
256}
257
258impl<'tcx> Stable<'tcx> for mir::Mutability {
259    type T = crate::mir::Mutability;
260    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
261        use rustc_hir::Mutability::*;
262        match *self {
263            Not => crate::mir::Mutability::Not,
264            Mut => crate::mir::Mutability::Mut,
265        }
266    }
267}
268
269impl<'tcx> Stable<'tcx> for mir::RawPtrKind {
270    type T = crate::mir::RawPtrKind;
271    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
272        use mir::RawPtrKind::*;
273        match *self {
274            Const => crate::mir::RawPtrKind::Const,
275            Mut => crate::mir::RawPtrKind::Mut,
276            FakeForPtrMetadata => crate::mir::RawPtrKind::FakeForPtrMetadata,
277        }
278    }
279}
280
281impl<'tcx> Stable<'tcx> for mir::BorrowKind {
282    type T = crate::mir::BorrowKind;
283    fn stable<'cx>(
284        &self,
285        tables: &mut Tables<'cx, BridgeTys>,
286        cx: &CompilerCtxt<'cx, BridgeTys>,
287    ) -> Self::T {
288        use rustc_middle::mir::BorrowKind::*;
289        match *self {
290            Shared => crate::mir::BorrowKind::Shared,
291            Fake(kind) => crate::mir::BorrowKind::Fake(kind.stable(tables, cx)),
292            Mut { kind } => crate::mir::BorrowKind::Mut { kind: kind.stable(tables, cx) },
293        }
294    }
295}
296
297impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
298    type T = crate::mir::MutBorrowKind;
299    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
300        use rustc_middle::mir::MutBorrowKind::*;
301        match *self {
302            Default => crate::mir::MutBorrowKind::Default,
303            TwoPhaseBorrow => crate::mir::MutBorrowKind::TwoPhaseBorrow,
304            ClosureCapture => crate::mir::MutBorrowKind::ClosureCapture,
305        }
306    }
307}
308
309impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
310    type T = crate::mir::FakeBorrowKind;
311    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
312        use rustc_middle::mir::FakeBorrowKind::*;
313        match *self {
314            Deep => crate::mir::FakeBorrowKind::Deep,
315            Shallow => crate::mir::FakeBorrowKind::Shallow,
316        }
317    }
318}
319
320impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
321    type T = crate::mir::NullOp;
322    fn stable<'cx>(
323        &self,
324        tables: &mut Tables<'cx, BridgeTys>,
325        cx: &CompilerCtxt<'cx, BridgeTys>,
326    ) -> Self::T {
327        use rustc_middle::mir::NullOp::*;
328        match self {
329            SizeOf => crate::mir::NullOp::SizeOf,
330            AlignOf => crate::mir::NullOp::AlignOf,
331            OffsetOf(indices) => crate::mir::NullOp::OffsetOf(
332                indices.iter().map(|idx| idx.stable(tables, cx)).collect(),
333            ),
334            UbChecks => crate::mir::NullOp::UbChecks,
335            ContractChecks => crate::mir::NullOp::ContractChecks,
336        }
337    }
338}
339
340impl<'tcx> Stable<'tcx> for mir::CastKind {
341    type T = crate::mir::CastKind;
342    fn stable<'cx>(
343        &self,
344        tables: &mut Tables<'cx, BridgeTys>,
345        cx: &CompilerCtxt<'cx, BridgeTys>,
346    ) -> Self::T {
347        use rustc_middle::mir::CastKind::*;
348        match self {
349            PointerExposeProvenance => crate::mir::CastKind::PointerExposeAddress,
350            PointerWithExposedProvenance => crate::mir::CastKind::PointerWithExposedProvenance,
351            PointerCoercion(c, _) => crate::mir::CastKind::PointerCoercion(c.stable(tables, cx)),
352            IntToInt => crate::mir::CastKind::IntToInt,
353            FloatToInt => crate::mir::CastKind::FloatToInt,
354            FloatToFloat => crate::mir::CastKind::FloatToFloat,
355            IntToFloat => crate::mir::CastKind::IntToFloat,
356            PtrToPtr => crate::mir::CastKind::PtrToPtr,
357            FnPtrToPtr => crate::mir::CastKind::FnPtrToPtr,
358            Transmute => crate::mir::CastKind::Transmute,
359            Subtype => crate::mir::CastKind::Subtype,
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            UnwrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
458        }
459    }
460}
461
462impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
463    type T = crate::mir::UserTypeProjection;
464
465    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
466        UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) }
467    }
468}
469
470impl<'tcx> Stable<'tcx> for mir::Local {
471    type T = crate::mir::Local;
472    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
473        self.as_usize()
474    }
475}
476
477impl<'tcx> Stable<'tcx> for mir::RetagKind {
478    type T = crate::mir::RetagKind;
479    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
480        use rustc_middle::mir::RetagKind;
481        match self {
482            RetagKind::FnEntry => crate::mir::RetagKind::FnEntry,
483            RetagKind::TwoPhase => crate::mir::RetagKind::TwoPhase,
484            RetagKind::Raw => crate::mir::RetagKind::Raw,
485            RetagKind::Default => crate::mir::RetagKind::Default,
486        }
487    }
488}
489
490impl<'tcx> Stable<'tcx> for mir::UnwindAction {
491    type T = crate::mir::UnwindAction;
492    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
493        use rustc_middle::mir::UnwindAction;
494        match self {
495            UnwindAction::Continue => crate::mir::UnwindAction::Continue,
496            UnwindAction::Unreachable => crate::mir::UnwindAction::Unreachable,
497            UnwindAction::Terminate(_) => crate::mir::UnwindAction::Terminate,
498            UnwindAction::Cleanup(bb) => crate::mir::UnwindAction::Cleanup(bb.as_usize()),
499        }
500    }
501}
502
503impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
504    type T = crate::mir::NonDivergingIntrinsic;
505
506    fn stable<'cx>(
507        &self,
508        tables: &mut Tables<'cx, BridgeTys>,
509        cx: &CompilerCtxt<'cx, BridgeTys>,
510    ) -> Self::T {
511        use rustc_middle::mir::NonDivergingIntrinsic;
512
513        use crate::mir::CopyNonOverlapping;
514        match self {
515            NonDivergingIntrinsic::Assume(op) => {
516                crate::mir::NonDivergingIntrinsic::Assume(op.stable(tables, cx))
517            }
518            NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => {
519                crate::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
520                    src: copy_non_overlapping.src.stable(tables, cx),
521                    dst: copy_non_overlapping.dst.stable(tables, cx),
522                    count: copy_non_overlapping.count.stable(tables, cx),
523                })
524            }
525        }
526    }
527}
528
529impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
530    type T = crate::mir::AssertMessage;
531    fn stable<'cx>(
532        &self,
533        tables: &mut Tables<'cx, BridgeTys>,
534        cx: &CompilerCtxt<'cx, BridgeTys>,
535    ) -> Self::T {
536        use rustc_middle::mir::AssertKind;
537        match self {
538            AssertKind::BoundsCheck { len, index } => crate::mir::AssertMessage::BoundsCheck {
539                len: len.stable(tables, cx),
540                index: index.stable(tables, cx),
541            },
542            AssertKind::Overflow(bin_op, op1, op2) => crate::mir::AssertMessage::Overflow(
543                bin_op.stable(tables, cx),
544                op1.stable(tables, cx),
545                op2.stable(tables, cx),
546            ),
547            AssertKind::OverflowNeg(op) => {
548                crate::mir::AssertMessage::OverflowNeg(op.stable(tables, cx))
549            }
550            AssertKind::DivisionByZero(op) => {
551                crate::mir::AssertMessage::DivisionByZero(op.stable(tables, cx))
552            }
553            AssertKind::RemainderByZero(op) => {
554                crate::mir::AssertMessage::RemainderByZero(op.stable(tables, cx))
555            }
556            AssertKind::ResumedAfterReturn(coroutine) => {
557                crate::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables, cx))
558            }
559            AssertKind::ResumedAfterPanic(coroutine) => {
560                crate::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables, cx))
561            }
562            AssertKind::ResumedAfterDrop(coroutine) => {
563                crate::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables, cx))
564            }
565            AssertKind::MisalignedPointerDereference { required, found } => {
566                crate::mir::AssertMessage::MisalignedPointerDereference {
567                    required: required.stable(tables, cx),
568                    found: found.stable(tables, cx),
569                }
570            }
571            AssertKind::NullPointerDereference => crate::mir::AssertMessage::NullPointerDereference,
572            AssertKind::InvalidEnumConstruction(source) => {
573                crate::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx))
574            }
575        }
576    }
577}
578
579impl<'tcx> Stable<'tcx> for mir::BinOp {
580    type T = crate::mir::BinOp;
581    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
582        use rustc_middle::mir::BinOp;
583        match self {
584            BinOp::Add => crate::mir::BinOp::Add,
585            BinOp::AddUnchecked => crate::mir::BinOp::AddUnchecked,
586            BinOp::AddWithOverflow => bug!("AddWithOverflow should have been translated already"),
587            BinOp::Sub => crate::mir::BinOp::Sub,
588            BinOp::SubUnchecked => crate::mir::BinOp::SubUnchecked,
589            BinOp::SubWithOverflow => bug!("AddWithOverflow should have been translated already"),
590            BinOp::Mul => crate::mir::BinOp::Mul,
591            BinOp::MulUnchecked => crate::mir::BinOp::MulUnchecked,
592            BinOp::MulWithOverflow => bug!("AddWithOverflow should have been translated already"),
593            BinOp::Div => crate::mir::BinOp::Div,
594            BinOp::Rem => crate::mir::BinOp::Rem,
595            BinOp::BitXor => crate::mir::BinOp::BitXor,
596            BinOp::BitAnd => crate::mir::BinOp::BitAnd,
597            BinOp::BitOr => crate::mir::BinOp::BitOr,
598            BinOp::Shl => crate::mir::BinOp::Shl,
599            BinOp::ShlUnchecked => crate::mir::BinOp::ShlUnchecked,
600            BinOp::Shr => crate::mir::BinOp::Shr,
601            BinOp::ShrUnchecked => crate::mir::BinOp::ShrUnchecked,
602            BinOp::Eq => crate::mir::BinOp::Eq,
603            BinOp::Lt => crate::mir::BinOp::Lt,
604            BinOp::Le => crate::mir::BinOp::Le,
605            BinOp::Ne => crate::mir::BinOp::Ne,
606            BinOp::Ge => crate::mir::BinOp::Ge,
607            BinOp::Gt => crate::mir::BinOp::Gt,
608            BinOp::Cmp => crate::mir::BinOp::Cmp,
609            BinOp::Offset => crate::mir::BinOp::Offset,
610        }
611    }
612}
613
614impl<'tcx> Stable<'tcx> for mir::UnOp {
615    type T = crate::mir::UnOp;
616    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
617        use rustc_middle::mir::UnOp;
618        match self {
619            UnOp::Not => crate::mir::UnOp::Not,
620            UnOp::Neg => crate::mir::UnOp::Neg,
621            UnOp::PtrMetadata => crate::mir::UnOp::PtrMetadata,
622        }
623    }
624}
625
626impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
627    type T = crate::mir::AggregateKind;
628    fn stable<'cx>(
629        &self,
630        tables: &mut Tables<'cx, BridgeTys>,
631        cx: &CompilerCtxt<'cx, BridgeTys>,
632    ) -> Self::T {
633        match self {
634            mir::AggregateKind::Array(ty) => {
635                crate::mir::AggregateKind::Array(ty.stable(tables, cx))
636            }
637            mir::AggregateKind::Tuple => crate::mir::AggregateKind::Tuple,
638            mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => {
639                crate::mir::AggregateKind::Adt(
640                    tables.adt_def(*def_id),
641                    var_idx.stable(tables, cx),
642                    generic_arg.stable(tables, cx),
643                    user_ty_index.map(|idx| idx.index()),
644                    field_idx.map(|idx| idx.index()),
645                )
646            }
647            mir::AggregateKind::Closure(def_id, generic_arg) => crate::mir::AggregateKind::Closure(
648                tables.closure_def(*def_id),
649                generic_arg.stable(tables, cx),
650            ),
651            mir::AggregateKind::Coroutine(def_id, generic_arg) => {
652                crate::mir::AggregateKind::Coroutine(
653                    tables.coroutine_def(*def_id),
654                    generic_arg.stable(tables, cx),
655                )
656            }
657            mir::AggregateKind::CoroutineClosure(def_id, generic_args) => {
658                crate::mir::AggregateKind::CoroutineClosure(
659                    tables.coroutine_closure_def(*def_id),
660                    generic_args.stable(tables, cx),
661                )
662            }
663            mir::AggregateKind::RawPtr(ty, mutability) => crate::mir::AggregateKind::RawPtr(
664                ty.stable(tables, cx),
665                mutability.stable(tables, cx),
666            ),
667        }
668    }
669}
670
671impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
672    type T = crate::mir::InlineAsmOperand;
673    fn stable<'cx>(
674        &self,
675        tables: &mut Tables<'cx, BridgeTys>,
676        cx: &CompilerCtxt<'cx, BridgeTys>,
677    ) -> Self::T {
678        use rustc_middle::mir::InlineAsmOperand;
679
680        let (in_value, out_place) = match self {
681            InlineAsmOperand::In { value, .. } => (Some(value.stable(tables, cx)), None),
682            InlineAsmOperand::Out { place, .. } => {
683                (None, place.map(|place| place.stable(tables, cx)))
684            }
685            InlineAsmOperand::InOut { in_value, out_place, .. } => {
686                (Some(in_value.stable(tables, cx)), out_place.map(|place| place.stable(tables, cx)))
687            }
688            InlineAsmOperand::Const { .. }
689            | InlineAsmOperand::SymFn { .. }
690            | InlineAsmOperand::SymStatic { .. }
691            | InlineAsmOperand::Label { .. } => (None, None),
692        };
693
694        crate::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") }
695    }
696}
697
698impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
699    type T = crate::mir::Terminator;
700    fn stable<'cx>(
701        &self,
702        tables: &mut Tables<'cx, BridgeTys>,
703        cx: &CompilerCtxt<'cx, BridgeTys>,
704    ) -> Self::T {
705        use crate::mir::Terminator;
706        Terminator {
707            kind: self.kind.stable(tables, cx),
708            span: self.source_info.span.stable(tables, cx),
709        }
710    }
711}
712
713impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
714    type T = crate::mir::TerminatorKind;
715    fn stable<'cx>(
716        &self,
717        tables: &mut Tables<'cx, BridgeTys>,
718        cx: &CompilerCtxt<'cx, BridgeTys>,
719    ) -> Self::T {
720        use crate::mir::TerminatorKind;
721        match self {
722            mir::TerminatorKind::Goto { target } => {
723                TerminatorKind::Goto { target: target.as_usize() }
724            }
725            mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
726                discr: discr.stable(tables, cx),
727                targets: {
728                    let branches = targets.iter().map(|(val, target)| (val, target.as_usize()));
729                    crate::mir::SwitchTargets::new(
730                        branches.collect(),
731                        targets.otherwise().as_usize(),
732                    )
733                },
734            },
735            mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,
736            mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort,
737            mir::TerminatorKind::Return => TerminatorKind::Return,
738            mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable,
739            mir::TerminatorKind::Drop {
740                place,
741                target,
742                unwind,
743                replace: _,
744                drop: _,
745                async_fut: _,
746            } => TerminatorKind::Drop {
747                place: place.stable(tables, cx),
748                target: target.as_usize(),
749                unwind: unwind.stable(tables, cx),
750            },
751            mir::TerminatorKind::Call {
752                func,
753                args,
754                destination,
755                target,
756                unwind,
757                call_source: _,
758                fn_span: _,
759            } => TerminatorKind::Call {
760                func: func.stable(tables, cx),
761                args: args.iter().map(|arg| arg.node.stable(tables, cx)).collect(),
762                destination: destination.stable(tables, cx),
763                target: target.map(|t| t.as_usize()),
764                unwind: unwind.stable(tables, cx),
765            },
766            mir::TerminatorKind::TailCall { func: _, args: _, fn_span: _ } => todo!(),
767            mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
768                TerminatorKind::Assert {
769                    cond: cond.stable(tables, cx),
770                    expected: *expected,
771                    msg: msg.stable(tables, cx),
772                    target: target.as_usize(),
773                    unwind: unwind.stable(tables, cx),
774                }
775            }
776            mir::TerminatorKind::InlineAsm {
777                asm_macro: _,
778                template,
779                operands,
780                options,
781                line_spans,
782                targets,
783                unwind,
784            } => TerminatorKind::InlineAsm {
785                template: format!("{template:?}"),
786                operands: operands.iter().map(|operand| operand.stable(tables, cx)).collect(),
787                options: format!("{options:?}"),
788                line_spans: format!("{line_spans:?}"),
789                // FIXME: Figure out how to do labels in SMIR
790                destination: targets.first().map(|d| d.as_usize()),
791                unwind: unwind.stable(tables, cx),
792            },
793            mir::TerminatorKind::Yield { .. }
794            | mir::TerminatorKind::CoroutineDrop
795            | mir::TerminatorKind::FalseEdge { .. }
796            | mir::TerminatorKind::FalseUnwind { .. } => unreachable!(),
797        }
798    }
799}
800
801impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
802    type T = Allocation;
803
804    fn stable<'cx>(
805        &self,
806        tables: &mut Tables<'cx, BridgeTys>,
807        cx: &CompilerCtxt<'cx, BridgeTys>,
808    ) -> Self::T {
809        self.inner().stable(tables, cx)
810    }
811}
812
813impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
814    type T = crate::ty::Allocation;
815
816    fn stable<'cx>(
817        &self,
818        tables: &mut Tables<'cx, BridgeTys>,
819        cx: &CompilerCtxt<'cx, BridgeTys>,
820    ) -> Self::T {
821        use rustc_public_bridge::context::AllocRangeHelpers;
822        alloc::allocation_filter(
823            self,
824            cx.alloc_range(rustc_abi::Size::ZERO, self.size()),
825            tables,
826            cx,
827        )
828    }
829}
830
831impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
832    type T = crate::mir::alloc::AllocId;
833    fn stable<'cx>(
834        &self,
835        tables: &mut Tables<'cx, BridgeTys>,
836        _: &CompilerCtxt<'cx, BridgeTys>,
837    ) -> Self::T {
838        tables.create_alloc_id(*self)
839    }
840}
841
842impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
843    type T = GlobalAlloc;
844
845    fn stable<'cx>(
846        &self,
847        tables: &mut Tables<'cx, BridgeTys>,
848        cx: &CompilerCtxt<'cx, BridgeTys>,
849    ) -> Self::T {
850        match self {
851            mir::interpret::GlobalAlloc::Function { instance, .. } => {
852                GlobalAlloc::Function(instance.stable(tables, cx))
853            }
854            mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => {
855                // FIXME: Should we record the whole vtable?
856                GlobalAlloc::VTable(ty.stable(tables, cx), dyn_ty.principal().stable(tables, cx))
857            }
858            mir::interpret::GlobalAlloc::Static(def) => {
859                GlobalAlloc::Static(tables.static_def(*def))
860            }
861            mir::interpret::GlobalAlloc::Memory(alloc) => {
862                GlobalAlloc::Memory(alloc.stable(tables, cx))
863            }
864            mir::interpret::GlobalAlloc::TypeId { ty } => {
865                GlobalAlloc::TypeId { ty: ty.stable(tables, cx) }
866            }
867        }
868    }
869}
870
871impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
872    type T = crate::ty::MirConst;
873
874    fn stable<'cx>(
875        &self,
876        tables: &mut Tables<'cx, BridgeTys>,
877        cx: &CompilerCtxt<'cx, BridgeTys>,
878    ) -> Self::T {
879        let id = tables.intern_mir_const(cx.lift(*self).unwrap());
880        match *self {
881            mir::Const::Ty(ty, c) => MirConst::new(
882                crate::ty::ConstantKind::Ty(c.stable(tables, cx)),
883                ty.stable(tables, cx),
884                id,
885            ),
886            mir::Const::Unevaluated(unev_const, ty) => {
887                let kind = crate::ty::ConstantKind::Unevaluated(crate::ty::UnevaluatedConst {
888                    def: tables.const_def(unev_const.def),
889                    args: unev_const.args.stable(tables, cx),
890                    promoted: unev_const.promoted.map(|u| u.as_u32()),
891                });
892                let ty = ty.stable(tables, cx);
893                MirConst::new(kind, ty, id)
894            }
895            mir::Const::Val(mir::ConstValue::ZeroSized, ty) => {
896                let ty = ty.stable(tables, cx);
897                MirConst::new(ConstantKind::ZeroSized, ty, id)
898            }
899            mir::Const::Val(val, ty) => {
900                let ty = cx.lift(ty).unwrap();
901                let val = cx.lift(val).unwrap();
902                let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables, cx));
903                let ty = ty.stable(tables, cx);
904                MirConst::new(kind, ty, id)
905            }
906        }
907    }
908}
909
910impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
911    type T = Error;
912
913    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
914        bridge::Error::new(format!("{self:?}"))
915    }
916}
917
918impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
919    type T = crate::mir::mono::MonoItem;
920
921    fn stable<'cx>(
922        &self,
923        tables: &mut Tables<'cx, BridgeTys>,
924        cx: &CompilerCtxt<'cx, BridgeTys>,
925    ) -> Self::T {
926        use crate::mir::mono::MonoItem as StableMonoItem;
927        match self {
928            MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables, cx)),
929            MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
930            MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
931        }
932    }
933}