Skip to content

Operational Semantics for Generators #367

Open
@JakobDegen

Description

@JakobDegen

We need to spec what generators are operationally. One option is to simply include the current generator lowering that rustc does in the spec. This has a number of downsides though, the biggest one being that it significantly inhibits optimizations. Specifically, for an async block like this:

async {
    let x = 5_u64;
    something.await;
    dbg!(x);
}

We would like to justify two optimizations:

  1. Const propagating the 5 into the dbg! invocation.
  2. The Future that results from this async block having size less than size_of::<u64>().

If our spec simply says that async blocks are subjected to the standard generator lowering, neither of these optimizations is correct. The &mut Future that the caller of poll has when the .await point is hit might be used to modify x, so we cannot const-prop, and x is clearly alive across an await point, and so we must allocate space for it in the future.

Specifically, we are looking to prove two theorems:

  1. An optimization can soundly treat a _ret = yield(_arg) [resume => bbA, drop => bbB] as a _ret = call UNKNOWN_FN(_arg) [return => bbA, unwind => bbB]. Here UNKNOWN_FN is some unknown function that is unique to this yield point.
  2. The generator lowering pass in MIR today is sound.

cc @tmandry and @saethlin with whom I talked about this issue at some length during rustconf

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions