-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-enum LocationExtended {
- Plain(Location),
- Arg,
-}
-
-#[derive(Debug)]
-struct SsaLocals {
- /// Assignments to each local. This defines whether the local is SSA.
- assignments: IndexVec<Local, Set1<LocationExtended>>,
- /// We visit the body in reverse postorder, to ensure each local is assigned before it is used.
- /// We remember the order in which we saw the assignments to compute the SSA values in a single
- /// pass.
- assignment_order: Vec<Local>,
-}
-
-impl SsaLocals {
- fn new<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, body: &Body<'tcx>) -> SsaLocals {
- let assignment_order = Vec::new();
-
- let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
- let mut this = SsaLocals { assignments, assignment_order };
-
- let borrowed = borrowed_locals(body);
- for (local, decl) in body.local_decls.iter_enumerated() {
- if matches!(body.local_kind(local), LocalKind::Arg) {
- this.assignments[local] = Set1::One(LocationExtended::Arg);
- }
- if borrowed.contains(local) && !decl.ty.is_freeze(tcx, param_env) {
- this.assignments[local] = Set1::Many;
- }
- }
-
- for (bb, data) in traversal::reverse_postorder(body) {
- this.visit_basic_block_data(bb, data);
- }
-
- for var_debug_info in &body.var_debug_info {
- this.visit_var_debug_info(var_debug_info);
- }
-
- debug!(?this.assignments);
-
- this.assignment_order.retain(|&local| matches!(this.assignments[local], Set1::One(_)));
- debug!(?this.assignment_order);
-
- this
- }
-}
-
-impl<'tcx> Visitor<'tcx> for SsaLocals {
- fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) {
- match ctxt {
- PlaceContext::MutatingUse(MutatingUseContext::Store) => {
- self.assignments[local].insert(LocationExtended::Plain(loc));
- self.assignment_order.push(local);
- }
- PlaceContext::MutatingUse(_) => self.assignments[local] = Set1::Many,
- // Immutable borrows and AddressOf are taken into account in `SsaLocals::new` by
- // removing non-freeze locals.
- PlaceContext::NonMutatingUse(_) | PlaceContext::NonUse(_) => {}
- }
- }
-}
-
-/// Compute the equivalence classes for locals, based on copy statements.
-///
-/// The returned vector maps each local to the one it copies. In the following case:
-/// _a = &mut _0
-/// _b = move? _a
-/// _c = move? _a
-/// _d = move? _c
-/// We return the mapping
-/// _a => _a // not a copy so, represented by itself
-/// _b => _a
-/// _c => _a
-/// _d => _a // transitively through _c