1use rustc_hir::def::DefKind;
8use rustc_middle::mir;
9use rustc_middle::mir::visit::MutVisitor;
10use rustc_middle::ty::{self, TyCtxt};
11
12pub(crate) struct BodyBuilder<'tcx> {
14 tcx: TyCtxt<'tcx>,
15 instance: ty::Instance<'tcx>,
16}
17
18impl<'tcx> BodyBuilder<'tcx> {
19 pub(crate) fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
20 let instance = match instance.def {
21 ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new_raw(def_id, instance.args),
23 _ => instance,
24 };
25 BodyBuilder { tcx, instance }
26 }
27
28 pub(crate) fn build(mut self) -> mir::Body<'tcx> {
32 let body = self.tcx.instance_mir(self.instance.def).clone();
33 let mono_body = if !self.instance.args.is_empty()
34 || self.tcx.def_kind(self.instance.def_id()) != DefKind::AnonConst
38 {
39 let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions(
40 self.tcx,
41 ty::TypingEnv::fully_monomorphized(),
42 ty::EarlyBinder::bind(body),
43 );
44 self.visit_body(&mut mono_body);
45 mono_body
46 } else {
47 body
49 };
50
51 mono_body
52 }
53}
54
55impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
56 fn visit_const_operand(
57 &mut self,
58 constant: &mut mir::ConstOperand<'tcx>,
59 location: mir::Location,
60 ) {
61 let const_ = constant.const_;
62 let val = match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) {
63 Ok(v) => v,
64 Err(mir::interpret::ErrorHandled::Reported(..)) => return,
65 Err(mir::interpret::ErrorHandled::TooGeneric(..)) => {
66 unreachable!("Failed to evaluate instance constant: {:?}", const_)
67 }
68 };
69 let ty = constant.ty();
70 constant.const_ = mir::Const::Val(val, ty);
71 self.super_const_operand(constant, location);
72 }
73
74 fn tcx(&self) -> TyCtxt<'tcx> {
75 self.tcx
76 }
77}