Skip to main content

rustc_public/unstable/convert/stable/
mir.rs

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