in checker/src/body_visitor.rs [812:901]
fn promote_constants(&mut self) -> Environment {
let mut environment = Environment::default();
if matches!(
self.tcx.def_kind(self.def_id),
rustc_hir::def::DefKind::Variant
) {
return environment;
}
trace!("def_id {:?}", self.tcx.def_kind(self.def_id));
let saved_mir = self.mir;
for (ordinal, constant_mir) in self.tcx.promoted_mir(self.def_id).iter().enumerate() {
self.mir = constant_mir;
self.type_visitor_mut().mir = self.mir;
let result_rustc_type = self.mir.local_decls[mir::Local::from(0usize)].ty;
self.visit_promoted_constants_block();
if let Some(exit_environment) = &self.exit_environment {
self.current_environment = exit_environment.clone();
let mut result_root: Rc<Path> = Path::new_result();
let mut promoted_root: Rc<Path> =
Rc::new(PathEnum::PromotedConstant { ordinal }.into());
if self
.type_visitor()
.is_slice_pointer(result_rustc_type.kind())
{
let source_length_path = Path::new_length(result_root.clone());
let length_val = self
.exit_environment
.as_ref()
.unwrap()
.value_map
.get(&source_length_path)
.expect("collection to have a length");
let target_length_path = Path::new_length(promoted_root.clone());
environment.strong_update_value_at(target_length_path, length_val.clone());
promoted_root = Path::new_field(promoted_root, 0);
result_root = Path::new_field(result_root, 0);
}
let value =
self.lookup_path_and_refine_result(result_root.clone(), result_rustc_type);
match &value.expression {
Expression::HeapBlock { .. } => {
let heap_root: Rc<Path> = Path::new_heap_block(value.clone());
for (path, value) in self
.exit_environment
.as_ref()
.unwrap()
.value_map
.iter()
.filter(|(p, _)| p.is_rooted_by(&heap_root))
{
environment.strong_update_value_at(path.clone(), value.clone());
}
environment.strong_update_value_at(promoted_root.clone(), value.clone());
}
Expression::Reference(local_path) => {
self.promote_reference(
&mut environment,
result_rustc_type,
&promoted_root,
local_path,
);
}
_ => {
for (path, value) in self
.exit_environment
.as_ref()
.unwrap()
.value_map
.iter()
.filter(|(p, _)| p.is_rooted_by(&result_root))
{
let promoted_path =
path.replace_root(&result_root, promoted_root.clone());
environment.strong_update_value_at(promoted_path, value.clone());
}
if let Expression::Variable { .. } = &value.expression {
// The constant is a stack allocated struct. No need for a separate entry.
} else {
environment
.strong_update_value_at(promoted_root.clone(), value.clone());
}
}
}
}
self.reset_visitor_state();
}
self.mir = saved_mir;
self.type_visitor_mut().mir = saved_mir;
environment
}