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