Reuse generator slots after StorageDead #52924

What is required

  • Implementation: changes to…
  • librustc_mir/transform/generator.rs
  • GeneratorLayout to express the new layout constraints
  • whatever code generates the layout of the closure type
  • whatever code consumes GeneratorLayout
  • Testing:
  • issue description has an example test like this
  • Debuginfo:
  • generated in librustc_codegen_ssa/mir/mod.rs
  • anywhere else?
  • Other concerns


  • Layout described in librustc_target/abi/mod.rs

  • Today, a generator is lowered as a function which takes one argument, a Pin<&mut {{generator}}>, where {{generator}} is a generated struct containing:
  • any upvars
  • an int indicating what the state of the generator is (i.e. which yield point to resume from)
  • every variable that is live across any yield point
  • {{state}} is actually the general closure struct-like type
  • The fields in {{state}} from the generator state are listed in the function MIR as mir.generator_layout
  • Currently this is assumed to be a flat list appended onto the end of any captured upvars
  • Presumably, closure_layout (in librustc_codegen_ssa/mir/mod.rs) is a struct layout with a list of fields.
  • The layout is computed in rustc_mir::transform::generator::compute_layout
  • Prior to this, the set of locals which “might” live across a suspension point (or do, from the perspective of typeck,”) are computed inside rustc_typeck::check::generator_interior. The types of these locals are stored inside the ty::GeneratorWitness. This is a superset of the types that eventually make it into the layout.
  • How do we tie the actual usage of these locals to their types inside the GeneratorWitness? It looks like substs may play a role…


Mapping: Local => (type of local, generator struct index)

Questions

  • How do we do the analysis and represent the result?
  • How do we represent a tagged union in MIR?
  • How do we represent the layout for codegen, including debuginfo?

Plan

  1. Lower GeneratorLayout to a layout with FieldPlacement::Arbitrary, mapping our fields to be overlapping within the same struct
  1. Create a scope for each local that represents the points when it is valid
  1. Take care that this doesn’t make debugging more difficult or opaque, somehow
  1. Can punt on this at first if it’s easier
  1. Define GeneratorLayout::fields() to be a list of the always-valid locals, followed by our union-ed fields (this will map to the name of each field within the layout)
  1. Perhaps ignore the discriminant when declaring locals in debuginfo (or handle it specially, somehow)
  1. Everything in rustc_codegen_ssa::mir should just work after that