Skip to content

Instantly share code, notes, and snippets.

@Nemo157

Nemo157/foo.rs Secret

Last active March 12, 2019 02:34

Revisions

  1. Nemo157 revised this gist Mar 12, 2019. 2 changed files with 122 additions and 0 deletions.
    122 changes: 122 additions & 0 deletions mir.dot
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,122 @@
    digraph {
    node [shape=plaintext];

    bb0 -> bb2 [label="return", weight=10];
    bb0 -> bb12 [label="unwind", constraint=true];

    bb2 -> bb4 [label="resume", weight=10];
    bb2 -> bb6 [label="drop", constraint=true];

    bb3 -> bb1 [weight=10];

    bb4 -> bb9 [label="return", weight=1];
    bb4 -> bb12 [label="unwind", constraint=true];

    bb5 -> bb1 [weight=10];

    bb6 -> bb7 [label="return", weight=1];
    bb6 -> bb5 [label="unwind", constraint=true];

    bb7 -> bb8 [label="return", weight=1];
    bb7 -> bb1 [label="unwind", constraint=true];

    bb9 -> bb10 [label="return", weight=1];
    bb9 -> bb1 [label="unwind", constraint=true];

    bb11 -> bb3 [weight=10];

    bb12 -> bb3 [label="false"];
    bb12 -> bb11 [label="otherwise"];

    bb0 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>first_drop_flag = true<br />first = Foo([0; 1024])<br />foo()</td></tr>
    <tr><td>{self, first, first_drop_flag}</td></tr>
    </table>
    >]

    bb1 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>resume</td></tr>
    <tr><td>{}</td></tr>
    </table>
    >]

    bb2 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>first_drop_flag = false<br />_second = first<br />suspend</td></tr>
    <tr><td>{self, first, _second, first_drop_flag}</td></tr>
    </table>
    >]

    bb3 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>drop(self)</td></tr>
    <tr><td>{}</td></tr>
    </table>
    >]

    bb4 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>drop(_second)</td></tr>
    <tr><td>{self, first, first_drop_flag}</td></tr>
    </table>
    >]

    bb5 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>drop(self)</td></tr>
    <tr><td>{}</td></tr>
    </table>
    >]

    bb6 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>drop(_second)</td></tr>
    <tr><td>{self}</td></tr>
    </table>
    >]

    bb7 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>drop(self)</td></tr>
    <tr><td>{}</td></tr>
    </table>
    >]

    bb8 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>generator_drop</td></tr>
    <tr><td>{}</td></tr>
    </table>
    >]

    bb9 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>first_drop_flag = false<br />drop(self)</td></tr>
    <tr><td>{}</td></tr>
    </table>
    >]

    bb10 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>return</td></tr>
    <tr><td>{}</td></tr>
    </table>
    >]

    bb11 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>first_drop_flag = false<br />drop(first)</td></tr>
    <tr><td>{self}</td></tr>
    </table>
    >]

    bb12 [label=<
    <table border="0" cellborder="1" cellspacing="0">
    <tr><td>switchInt(first_drop_flag)</td></tr>
    <tr><td>{self, first}</td></tr>
    </table>
    >]

    }
    Binary file added mir.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  2. Nemo157 revised this gist Mar 12, 2019. 11 changed files with 1307 additions and 1 deletion.
    31 changes: 31 additions & 0 deletions foo.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,31 @@
    #![feature(generators, generator_trait)]

    use std::ops::Generator;

    struct Foo([u8; 1024]);

    impl Drop for Foo {
    fn drop(&mut self) {}
    }

    fn simple() -> impl Generator<Yield = (), Return = ()> {
    static || {
    let first = Foo([0; 1024]);
    let _second = first;
    yield;
    }
    }

    fn complex() -> impl Generator<Yield = (), Return = ()> {
    static || {
    let first = Foo([0; 1024]);
    { foo(); fn foo() {} }
    let _second = first;
    yield;
    }
    }

    fn main() {
    dbg!(std::mem::size_of_val(&simple()));
    dbg!(std::mem::size_of_val(&complex()));
    }
    79 changes: 79 additions & 0 deletions rustc.complex-{{closure}}.-------.generator_drop.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    // MIR for `complex::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:16 ~ foo[317d]::complex[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_drop
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:21:21: 21:35)), pat_span: foo.rs:21:13: 21:18 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(first), source_info: SourceInfo { span: foo.rs:21:13: 21:18, scope: scope[2] }, visibility_scope: scope[1] }, LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:23:23: 23:28)), pat_span: foo.rs:23:13: 23:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:23:13: 23:20, scope: scope[4] }, visibility_scope: scope[3] }, LocalDecl { mutability: Mut, is_user_variable: None, internal: true, is_block_tail: None, ty: bool, user_ty: UserTypeProjections { contents: [] }, name: None, source_info: SourceInfo { span: foo.rs:25:5: 25:6, scope: scope[0] }, visibility_scope: scope[0] }] }

    fn complex::{{closure}}(_1: *mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}]) -> () {
    let mut _0: (); // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    }
    let mut _2: ();
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();
    let mut _8: ();
    let mut _9: ();
    let mut _10: ();

    bb0: {
    switchInt(((*_1).0: u32)) -> [0u32: bb7, 3u32: bb11, otherwise: bb12]; // bb0[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb1: { // cleanup
    resume; // bb1[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb2: { // cleanup
    goto -> bb8; // bb2[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb3: {
    drop(((*_1).2: Foo)) -> [return: bb4, unwind: bb2]; // bb3[0]: scope 1 at foo.rs:25:5: 25:6
    }

    bb4: {
    goto -> bb9; // bb4[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb5: {
    return; // bb5[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb6: {
    return; // bb6[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb7: {
    goto -> bb10; // bb7[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb8: { // cleanup
    goto -> bb1; // bb8[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb9: {
    goto -> bb5; // bb9[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb10: { // cleanup
    goto -> bb6; // bb10[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb11: {
    StorageLive(_8); // bb11[0]: scope 0 at foo.rs:20:5: 25:6
    goto -> bb3; // bb11[1]: scope 0 at foo.rs:20:5: 25:6
    }

    bb12: {
    return; // bb12[0]: scope 0 at foo.rs:20:5: 25:6
    }
    }
    201 changes: 201 additions & 0 deletions rustc.complex-{{closure}}.-------.generator_post-transform.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,201 @@
    // MIR for `complex::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:16 ~ foo[317d]::complex[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_post-transform
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:21:21: 21:35)), pat_span: foo.rs:21:13: 21:18 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(first), source_info: SourceInfo { span: foo.rs:21:13: 21:18, scope: scope[2] }, visibility_scope: scope[1] }, LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:23:23: 23:28)), pat_span: foo.rs:23:13: 23:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:23:13: 23:20, scope: scope[4] }, visibility_scope: scope[3] }, LocalDecl { mutability: Mut, is_user_variable: None, internal: true, is_block_tail: None, ty: bool, user_ty: UserTypeProjections { contents: [] }, name: None, source_info: SourceInfo { span: foo.rs:25:5: 25:6, scope: scope[0] }, visibility_scope: scope[0] }] }

    fn complex::{{closure}}(_1: [static generator@foo.rs:20:5: 25:6 {Foo, ()}]) -> std::ops::GeneratorState<(), ()> {
    let mut _0: std::ops::GeneratorState<(), ()>; // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    }
    let mut _2: ();
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();
    let mut _8: ();
    let mut _9: ();
    let mut _10: ();

    bb0: {
    (_1.3: bool) = const false; // bb0[0]: scope 0 at foo.rs:21:13: 21:18
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:13: 21:18
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    nop; // bb0[1]: scope 0 at foo.rs:21:13: 21:18
    StorageLive(_3); // bb0[2]: scope 0 at foo.rs:21:25: 21:34
    _3 = [const 0u8; 1024]; // bb0[3]: scope 0 at foo.rs:21:25: 21:34
    // ty::Const
    // + ty: u8
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:26: 21:27
    // + ty: u8
    // + literal: Evaluated(Const { ty: u8, val: Scalar(Bits { size: 1, bits: 0 }) })
    (_1.3: bool) = const true; // bb0[4]: scope 0 at foo.rs:21:21: 21:35
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 1 })
    // mir::Constant
    // + span: foo.rs:21:21: 21:35
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 1 }) })
    (_1.1: Foo) = Foo(move _3,); // bb0[5]: scope 0 at foo.rs:21:21: 21:35
    StorageDead(_3); // bb0[6]: scope 0 at foo.rs:21:34: 21:35
    _5 = const complex::{{closure}}::foo() -> [return: bb2, unwind: bb12]; // bb0[7]: scope 1 at foo.rs:22:11: 22:16
    // ty::Const
    // + ty: fn() {complex::{{closure}}::foo}
    // + val: Scalar(Bits { size: 0, bits: 0 })
    // mir::Constant
    // + span: foo.rs:22:11: 22:14
    // + ty: fn() {complex::{{closure}}::foo}
    // + literal: Evaluated(Const { ty: fn() {complex::{{closure}}::foo}, val: Scalar(Bits { size: 0, bits: 0 }) })
    }

    bb1: { // cleanup
    resume; // bb1[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb2: {
    _4 = (); // bb2[0]: scope 1 at foo.rs:22:9: 22:31
    nop; // bb2[1]: scope 1 at foo.rs:23:13: 23:20
    (_1.3: bool) = const false; // bb2[2]: scope 1 at foo.rs:23:23: 23:28
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:23:23: 23:28
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    (_1.2: Foo) = move (_1.1: Foo); // bb2[3]: scope 1 at foo.rs:23:23: 23:28
    StorageLive(_8); // bb2[4]: scope 3 at foo.rs:24:9: 24:14
    _8 = (); // bb2[5]: scope 3 at foo.rs:24:9: 24:14
    _0 = std::ops::GeneratorState<(), ()>::Yielded(move _8,); // bb2[6]: scope 3 at foo.rs:24:9: 24:14
    (_1.0: u32) = const 3u32; // bb2[7]: scope 3 at foo.rs:24:9: 24:14
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 3 })
    // mir::Constant
    // + span: foo.rs:24:9: 24:14
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 3 }) })
    return; // bb2[8]: scope 3 at foo.rs:24:9: 24:14
    }

    bb3: { // cleanup
    goto -> bb15; // bb3[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb4: {
    _7 = (); // bb4[0]: scope 3 at foo.rs:24:9: 24:14
    StorageDead(_8); // bb4[1]: scope 3 at foo.rs:24:13: 24:14
    _10 = (); // bb4[2]: scope 0 at foo.rs:20:15: 25:6
    drop((_1.2: Foo)) -> [return: bb9, unwind: bb12]; // bb4[3]: scope 1 at foo.rs:25:5: 25:6
    }

    bb5: { // cleanup
    goto -> bb16; // bb5[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb6: {
    drop((_1.2: Foo)) -> [return: bb7, unwind: bb5]; // bb6[0]: scope 1 at foo.rs:25:5: 25:6
    }

    bb7: {
    goto -> bb17; // bb7[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb8: {
    generator_drop; // bb8[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb9: {
    nop; // bb9[0]: scope 1 at foo.rs:25:5: 25:6
    (_1.3: bool) = const false; // bb9[1]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    nop; // bb9[2]: scope 0 at foo.rs:25:5: 25:6
    goto -> bb19; // bb9[3]: scope 0 at foo.rs:25:5: 25:6
    }

    bb10: {
    _0 = std::ops::GeneratorState<(), ()>::Complete(move _10,); // bb10[0]: scope 0 at foo.rs:25:6: 25:6
    (_1.0: u32) = const 1u32; // bb10[1]: scope 0 at foo.rs:25:6: 25:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:25:6: 25:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    return; // bb10[2]: scope 0 at foo.rs:25:6: 25:6
    }

    bb11: { // cleanup
    (_1.3: bool) = const false; // bb11[0]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    drop((_1.1: Foo)) -> bb3; // bb11[1]: scope 0 at foo.rs:25:5: 25:6
    }

    bb12: { // cleanup
    switchInt((_1.3: bool)) -> [false: bb3, otherwise: bb11]; // bb12[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb13: {
    return; // bb13[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb14: {
    goto -> bb21; // bb14[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb15: { // cleanup
    goto -> bb1; // bb15[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb16: { // cleanup
    goto -> bb1; // bb16[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb17: {
    goto -> bb8; // bb17[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb18: { // cleanup
    goto -> bb1; // bb18[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb19: {
    goto -> bb10; // bb19[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb20: { // cleanup
    goto -> bb1; // bb20[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb21: { // cleanup
    goto -> bb13; // bb21[0]: scope 0 at foo.rs:20:5: 25:6
    }
    }
    173 changes: 173 additions & 0 deletions rustc.complex-{{closure}}.-------.generator_pre-elab.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,173 @@
    // MIR for `complex::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:16 ~ foo[317d]::complex[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_pre-elab
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:21:21: 21:35)), pat_span: foo.rs:21:13: 21:18 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(first), source_info: SourceInfo { span: foo.rs:21:13: 21:18, scope: scope[2] }, visibility_scope: scope[1] }, LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:23:23: 23:28)), pat_span: foo.rs:23:13: 23:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:23:13: 23:20, scope: scope[4] }, visibility_scope: scope[3] }, LocalDecl { mutability: Mut, is_user_variable: None, internal: true, is_block_tail: None, ty: bool, user_ty: UserTypeProjections { contents: [] }, name: None, source_info: SourceInfo { span: foo.rs:25:5: 25:6, scope: scope[0] }, visibility_scope: scope[0] }] }

    fn complex::{{closure}}(_1: [static generator@foo.rs:20:5: 25:6 {Foo, ()}]) -> std::ops::GeneratorState<(), ()> {
    let mut _0: std::ops::GeneratorState<(), ()>; // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    }
    let mut _2: ();
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();
    let mut _8: ();
    let mut _9: ();
    let mut _10: ();

    bb0: {
    (_1.3: bool) = const false; // bb0[0]: scope 0 at foo.rs:21:13: 21:18
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:13: 21:18
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    nop; // bb0[1]: scope 0 at foo.rs:21:13: 21:18
    StorageLive(_3); // bb0[2]: scope 0 at foo.rs:21:25: 21:34
    _3 = [const 0u8; 1024]; // bb0[3]: scope 0 at foo.rs:21:25: 21:34
    // ty::Const
    // + ty: u8
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:26: 21:27
    // + ty: u8
    // + literal: Evaluated(Const { ty: u8, val: Scalar(Bits { size: 1, bits: 0 }) })
    (_1.3: bool) = const true; // bb0[4]: scope 0 at foo.rs:21:21: 21:35
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 1 })
    // mir::Constant
    // + span: foo.rs:21:21: 21:35
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 1 }) })
    (_1.1: Foo) = Foo(move _3,); // bb0[5]: scope 0 at foo.rs:21:21: 21:35
    StorageDead(_3); // bb0[6]: scope 0 at foo.rs:21:34: 21:35
    _5 = const complex::{{closure}}::foo() -> [return: bb2, unwind: bb12]; // bb0[7]: scope 1 at foo.rs:22:11: 22:16
    // ty::Const
    // + ty: fn() {complex::{{closure}}::foo}
    // + val: Scalar(Bits { size: 0, bits: 0 })
    // mir::Constant
    // + span: foo.rs:22:11: 22:14
    // + ty: fn() {complex::{{closure}}::foo}
    // + literal: Evaluated(Const { ty: fn() {complex::{{closure}}::foo}, val: Scalar(Bits { size: 0, bits: 0 }) })
    }

    bb1: { // cleanup
    resume; // bb1[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb2: {
    _4 = (); // bb2[0]: scope 1 at foo.rs:22:9: 22:31
    nop; // bb2[1]: scope 1 at foo.rs:23:13: 23:20
    (_1.3: bool) = const false; // bb2[2]: scope 1 at foo.rs:23:23: 23:28
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:23:23: 23:28
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    (_1.2: Foo) = move (_1.1: Foo); // bb2[3]: scope 1 at foo.rs:23:23: 23:28
    StorageLive(_8); // bb2[4]: scope 3 at foo.rs:24:9: 24:14
    _8 = (); // bb2[5]: scope 3 at foo.rs:24:9: 24:14
    _0 = std::ops::GeneratorState<(), ()>::Yielded(move _8,); // bb2[6]: scope 3 at foo.rs:24:9: 24:14
    (_1.0: u32) = const 3u32; // bb2[7]: scope 3 at foo.rs:24:9: 24:14
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 3 })
    // mir::Constant
    // + span: foo.rs:24:9: 24:14
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 3 }) })
    return; // bb2[8]: scope 3 at foo.rs:24:9: 24:14
    }

    bb3: { // cleanup
    drop(_1) -> bb1; // bb3[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb4: {
    _7 = (); // bb4[0]: scope 3 at foo.rs:24:9: 24:14
    StorageDead(_8); // bb4[1]: scope 3 at foo.rs:24:13: 24:14
    _10 = (); // bb4[2]: scope 0 at foo.rs:20:15: 25:6
    drop((_1.2: Foo)) -> [return: bb9, unwind: bb12]; // bb4[3]: scope 1 at foo.rs:25:5: 25:6
    }

    bb5: { // cleanup
    drop(_1) -> bb1; // bb5[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb6: {
    drop((_1.2: Foo)) -> [return: bb7, unwind: bb5]; // bb6[0]: scope 1 at foo.rs:25:5: 25:6
    }

    bb7: {
    drop(_1) -> [return: bb8, unwind: bb1]; // bb7[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb8: {
    generator_drop; // bb8[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb9: {
    nop; // bb9[0]: scope 1 at foo.rs:25:5: 25:6
    (_1.3: bool) = const false; // bb9[1]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    nop; // bb9[2]: scope 0 at foo.rs:25:5: 25:6
    drop(_1) -> [return: bb10, unwind: bb1]; // bb9[3]: scope 0 at foo.rs:25:5: 25:6
    }

    bb10: {
    _0 = std::ops::GeneratorState<(), ()>::Complete(move _10,); // bb10[0]: scope 0 at foo.rs:25:6: 25:6
    (_1.0: u32) = const 1u32; // bb10[1]: scope 0 at foo.rs:25:6: 25:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:25:6: 25:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    return; // bb10[2]: scope 0 at foo.rs:25:6: 25:6
    }

    bb11: { // cleanup
    (_1.3: bool) = const false; // bb11[0]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    drop((_1.1: Foo)) -> bb3; // bb11[1]: scope 0 at foo.rs:25:5: 25:6
    }

    bb12: { // cleanup
    switchInt((_1.3: bool)) -> [false: bb3, otherwise: bb11]; // bb12[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb13: {
    return; // bb13[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb14: {
    drop(_1) -> bb13; // bb14[0]: scope 0 at foo.rs:20:5: 25:6
    }
    }
    200 changes: 200 additions & 0 deletions rustc.complex-{{closure}}.-------.generator_resume.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,200 @@
    // MIR for `complex::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:16 ~ foo[317d]::complex[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_resume
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:21:21: 21:35)), pat_span: foo.rs:21:13: 21:18 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(first), source_info: SourceInfo { span: foo.rs:21:13: 21:18, scope: scope[2] }, visibility_scope: scope[1] }, LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:23:23: 23:28)), pat_span: foo.rs:23:13: 23:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:23:13: 23:20, scope: scope[4] }, visibility_scope: scope[3] }, LocalDecl { mutability: Mut, is_user_variable: None, internal: true, is_block_tail: None, ty: bool, user_ty: UserTypeProjections { contents: [] }, name: None, source_info: SourceInfo { span: foo.rs:25:5: 25:6, scope: scope[0] }, visibility_scope: scope[0] }] }

    fn complex::{{closure}}(_1: std::pin::Pin<&mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}]>) -> std::ops::GeneratorState<(), ()> {
    let mut _0: std::ops::GeneratorState<(), ()>; // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    }
    let mut _2: ();
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();
    let mut _8: ();
    let mut _9: ();
    let mut _10: ();

    bb0: {
    switchInt(((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).0: u32)) -> [0u32: bb1, 1u32: bb13, 2u32: bb14, 3u32: bb12, otherwise: bb15]; // bb0[0]: scope 0 at foo.rs:20:5: 25:6
    }

    bb1: {
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).3: bool) = const false; // bb1[0]: scope 0 at foo.rs:21:13: 21:18
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:13: 21:18
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    nop; // bb1[1]: scope 0 at foo.rs:21:13: 21:18
    StorageLive(_3); // bb1[2]: scope 0 at foo.rs:21:25: 21:34
    _3 = [const 0u8; 1024]; // bb1[3]: scope 0 at foo.rs:21:25: 21:34
    // ty::Const
    // + ty: u8
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:26: 21:27
    // + ty: u8
    // + literal: Evaluated(Const { ty: u8, val: Scalar(Bits { size: 1, bits: 0 }) })
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).3: bool) = const true; // bb1[4]: scope 0 at foo.rs:21:21: 21:35
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 1 })
    // mir::Constant
    // + span: foo.rs:21:21: 21:35
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 1 }) })
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).1: Foo) = Foo(move _3,); // bb1[5]: scope 0 at foo.rs:21:21: 21:35
    StorageDead(_3); // bb1[6]: scope 0 at foo.rs:21:34: 21:35
    _5 = const complex::{{closure}}::foo() -> [return: bb3, unwind: bb9]; // bb1[7]: scope 1 at foo.rs:22:11: 22:16
    // ty::Const
    // + ty: fn() {complex::{{closure}}::foo}
    // + val: Scalar(Bits { size: 0, bits: 0 })
    // mir::Constant
    // + span: foo.rs:22:11: 22:14
    // + ty: fn() {complex::{{closure}}::foo}
    // + literal: Evaluated(Const { ty: fn() {complex::{{closure}}::foo}, val: Scalar(Bits { size: 0, bits: 0 }) })
    }

    bb2: { // cleanup
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).0: u32) = const 1u32; // bb2[0]: scope 0 at foo.rs:20:5: 25:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:20:5: 25:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    resume; // bb2[1]: scope 0 at foo.rs:20:5: 25:6
    }

    bb3: {
    _4 = (); // bb3[0]: scope 1 at foo.rs:22:9: 22:31
    nop; // bb3[1]: scope 1 at foo.rs:23:13: 23:20
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).3: bool) = const false; // bb3[2]: scope 1 at foo.rs:23:23: 23:28
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:23:23: 23:28
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).2: Foo) = move ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).1: Foo); // bb3[3]: scope 1 at foo.rs:23:23: 23:28
    StorageLive(_8); // bb3[4]: scope 3 at foo.rs:24:9: 24:14
    _8 = (); // bb3[5]: scope 3 at foo.rs:24:9: 24:14
    _0 = std::ops::GeneratorState<(), ()>::Yielded(move _8,); // bb3[6]: scope 3 at foo.rs:24:9: 24:14
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).0: u32) = const 3u32; // bb3[7]: scope 3 at foo.rs:24:9: 24:14
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 3 })
    // mir::Constant
    // + span: foo.rs:24:9: 24:14
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 3 }) })
    return; // bb3[8]: scope 3 at foo.rs:24:9: 24:14
    }

    bb4: { // cleanup
    goto -> bb10; // bb4[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb5: {
    _7 = (); // bb5[0]: scope 3 at foo.rs:24:9: 24:14
    StorageDead(_8); // bb5[1]: scope 3 at foo.rs:24:13: 24:14
    _10 = (); // bb5[2]: scope 0 at foo.rs:20:15: 25:6
    drop(((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).2: Foo)) -> [return: bb6, unwind: bb9]; // bb5[3]: scope 1 at foo.rs:25:5: 25:6
    }

    bb6: {
    nop; // bb6[0]: scope 1 at foo.rs:25:5: 25:6
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).3: bool) = const false; // bb6[1]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    nop; // bb6[2]: scope 0 at foo.rs:25:5: 25:6
    goto -> bb11; // bb6[3]: scope 0 at foo.rs:25:5: 25:6
    }

    bb7: {
    _0 = std::ops::GeneratorState<(), ()>::Complete(move _10,); // bb7[0]: scope 0 at foo.rs:25:6: 25:6
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).0: u32) = const 1u32; // bb7[1]: scope 0 at foo.rs:25:6: 25:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:25:6: 25:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    return; // bb7[2]: scope 0 at foo.rs:25:6: 25:6
    }

    bb8: { // cleanup
    ((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).3: bool) = const false; // bb8[0]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    drop(((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).1: Foo)) -> bb4; // bb8[1]: scope 0 at foo.rs:25:5: 25:6
    }

    bb9: { // cleanup
    switchInt(((*(_1.0: &mut [static generator@foo.rs:20:5: 25:6 {Foo, ()}])).3: bool)) -> [false: bb4, otherwise: bb8]; // bb9[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb10: { // cleanup
    goto -> bb2; // bb10[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb11: {
    goto -> bb7; // bb11[0]: scope 0 at foo.rs:25:5: 25:6
    }

    bb12: {
    StorageLive(_8); // bb12[0]: scope 0 at foo.rs:20:5: 25:6
    goto -> bb5; // bb12[1]: scope 0 at foo.rs:20:5: 25:6
    }

    bb13: {
    assert(const false, "generator resumed after completion") -> bb13; // bb13[0]: scope 0 at foo.rs:20:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:20:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    }

    bb14: {
    assert(const false, "generator resumed after panicking") -> bb14; // bb14[0]: scope 0 at foo.rs:20:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:20:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    }

    bb15: {
    unreachable; // bb15[0]: scope 0 at foo.rs:20:5: 25:6
    }
    }
    160 changes: 160 additions & 0 deletions rustc.node102generator_liveness-liveness.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,160 @@
    // MIR local liveness analysis for `complex::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:16 ~ foo[317d]::complex[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_liveness

    fn complex::{{closure}}(_1: [static generator@foo.rs:20:5: 25:6 {Foo, ()}]) -> std::ops::GeneratorState<(), ()>
    yields ()
    {
    let mut _0: std::ops::GeneratorState<(), ()>; // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    let _6: Foo; // "_second" in scope 4 at foo.rs:23:13: 23:20
    }
    }
    scope 2 {
    let _2: Foo; // "first" in scope 2 at foo.rs:21:13: 21:18
    }
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _7: ();
    let mut _8: ();
    let mut _9: bool;
    let mut _10: ();

    bb0: {
    _9 = const false; // bb0[0]: scope 0 at foo.rs:21:13: 21:18
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:13: 21:18
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    StorageLive(_2); // bb0[1]: scope 0 at foo.rs:21:13: 21:18
    StorageLive(_3); // bb0[2]: scope 0 at foo.rs:21:25: 21:34
    _3 = [const 0u8; 1024]; // bb0[3]: scope 0 at foo.rs:21:25: 21:34
    // ty::Const
    // + ty: u8
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:21:26: 21:27
    // + ty: u8
    // + literal: Evaluated(Const { ty: u8, val: Scalar(Bits { size: 1, bits: 0 }) })
    _9 = const true; // bb0[4]: scope 0 at foo.rs:21:21: 21:35
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 1 })
    // mir::Constant
    // + span: foo.rs:21:21: 21:35
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 1 }) })
    _2 = Foo(move _3,); // bb0[5]: scope 0 at foo.rs:21:21: 21:35
    StorageDead(_3); // bb0[6]: scope 0 at foo.rs:21:34: 21:35
    _5 = const complex::{{closure}}::foo() -> [return: bb2, unwind: bb12]; // bb0[7]: scope 1 at foo.rs:22:11: 22:16
    // ty::Const
    // + ty: fn() {complex::{{closure}}::foo}
    // + val: Scalar(Bits { size: 0, bits: 0 })
    // mir::Constant
    // + span: foo.rs:22:11: 22:14
    // + ty: fn() {complex::{{closure}}::foo}
    // + literal: Evaluated(Const { ty: fn() {complex::{{closure}}::foo}, val: Scalar(Bits { size: 0, bits: 0 }) })
    }
    {_1, _2, _9}

    bb1: { // cleanup
    resume; // bb1[0]: scope 0 at foo.rs:20:5: 25:6
    }
    {}

    bb2: {
    _4 = (); // bb2[0]: scope 1 at foo.rs:22:9: 22:31
    StorageLive(_6); // bb2[1]: scope 1 at foo.rs:23:13: 23:20
    _9 = const false; // bb2[2]: scope 1 at foo.rs:23:23: 23:28
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:23:23: 23:28
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    _6 = move _2; // bb2[3]: scope 1 at foo.rs:23:23: 23:28
    StorageLive(_8); // bb2[4]: scope 3 at foo.rs:24:9: 24:14
    _8 = (); // bb2[5]: scope 3 at foo.rs:24:9: 24:14
    _1 = suspend(move _8) -> [resume: bb4, drop: bb6]; // bb2[6]: scope 3 at foo.rs:24:9: 24:14
    }
    {_1, _2, _6, _9}

    bb3: { // cleanup
    drop(_1) -> bb1; // bb3[0]: scope 0 at foo.rs:25:5: 25:6
    }
    {}

    bb4: {
    _7 = (); // bb4[0]: scope 3 at foo.rs:24:9: 24:14
    StorageDead(_8); // bb4[1]: scope 3 at foo.rs:24:13: 24:14
    _10 = (); // bb4[2]: scope 0 at foo.rs:20:15: 25:6
    drop(_6) -> [return: bb9, unwind: bb12]; // bb4[3]: scope 1 at foo.rs:25:5: 25:6
    }
    {_1, _2, _9}

    bb5: { // cleanup
    drop(_1) -> bb1; // bb5[0]: scope 0 at foo.rs:25:5: 25:6
    }
    {}

    bb6: {
    drop(_6) -> [return: bb7, unwind: bb5]; // bb6[0]: scope 1 at foo.rs:25:5: 25:6
    }
    {_1}

    bb7: {
    drop(_1) -> [return: bb8, unwind: bb1]; // bb7[0]: scope 0 at foo.rs:25:5: 25:6
    }
    {}

    bb8: {
    generator_drop; // bb8[0]: scope 0 at foo.rs:20:5: 25:6
    }
    {}

    bb9: {
    StorageDead(_6); // bb9[0]: scope 1 at foo.rs:25:5: 25:6
    _9 = const false; // bb9[1]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    StorageDead(_2); // bb9[2]: scope 0 at foo.rs:25:5: 25:6
    drop(_1) -> [return: bb10, unwind: bb1]; // bb9[3]: scope 0 at foo.rs:25:5: 25:6
    }
    {}

    bb10: {
    return; // bb10[0]: scope 0 at foo.rs:25:6: 25:6
    }
    {}

    bb11: { // cleanup
    _9 = const false; // bb11[0]: scope 0 at foo.rs:25:5: 25:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:25:5: 25:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    drop(_2) -> bb3; // bb11[1]: scope 0 at foo.rs:25:5: 25:6
    }
    {_1}

    bb12: { // cleanup
    switchInt(_9) -> [false: bb3, otherwise: bb11]; // bb12[0]: scope 0 at foo.rs:25:5: 25:6
    }
    {_1, _2}
    }
    77 changes: 77 additions & 0 deletions rustc.simple-{{closure}}.-------.generator_drop.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,77 @@
    // MIR for `simple::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:13 ~ foo[317d]::simple[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_drop
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:14:23: 14:28)), pat_span: foo.rs:14:13: 14:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:14:13: 14:20, scope: scope[4] }, visibility_scope: scope[3] }] }

    fn simple::{{closure}}(_1: *mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}]) -> () {
    let mut _0: (); // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    let _2: Foo; // "first" in scope 2 at foo.rs:13:13: 13:18
    }
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();

    bb0: {
    switchInt(((*_1).0: u32)) -> [0u32: bb7, 3u32: bb11, otherwise: bb12]; // bb0[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb1: { // cleanup
    resume; // bb1[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb2: { // cleanup
    goto -> bb8; // bb2[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb3: {
    drop(((*_1).1: Foo)) -> [return: bb4, unwind: bb2]; // bb3[0]: scope 1 at foo.rs:16:5: 16:6
    }

    bb4: {
    goto -> bb9; // bb4[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb5: {
    return; // bb5[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb6: {
    return; // bb6[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb7: {
    goto -> bb10; // bb7[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb8: { // cleanup
    goto -> bb1; // bb8[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb9: {
    goto -> bb5; // bb9[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb10: { // cleanup
    goto -> bb6; // bb10[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb11: {
    StorageLive(_2); // bb11[0]: scope 0 at foo.rs:12:5: 16:6
    StorageLive(_6); // bb11[1]: scope 0 at foo.rs:12:5: 16:6
    goto -> bb3; // bb11[2]: scope 0 at foo.rs:12:5: 16:6
    }

    bb12: {
    return; // bb12[0]: scope 0 at foo.rs:12:5: 16:6
    }
    }
    138 changes: 138 additions & 0 deletions rustc.simple-{{closure}}.-------.generator_post-transform.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,138 @@
    // MIR for `simple::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:13 ~ foo[317d]::simple[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_post-transform
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:14:23: 14:28)), pat_span: foo.rs:14:13: 14:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:14:13: 14:20, scope: scope[4] }, visibility_scope: scope[3] }] }

    fn simple::{{closure}}(_1: [static generator@foo.rs:12:5: 16:6 {Foo, ()}]) -> std::ops::GeneratorState<(), ()> {
    let mut _0: std::ops::GeneratorState<(), ()>; // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    let _2: Foo; // "first" in scope 2 at foo.rs:13:13: 13:18
    }
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();

    bb0: {
    StorageLive(_2); // bb0[0]: scope 0 at foo.rs:13:13: 13:18
    StorageLive(_3); // bb0[1]: scope 0 at foo.rs:13:25: 13:34
    _3 = [const 0u8; 1024]; // bb0[2]: scope 0 at foo.rs:13:25: 13:34
    // ty::Const
    // + ty: u8
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:13:26: 13:27
    // + ty: u8
    // + literal: Evaluated(Const { ty: u8, val: Scalar(Bits { size: 1, bits: 0 }) })
    _2 = Foo(move _3,); // bb0[3]: scope 0 at foo.rs:13:21: 13:35
    StorageDead(_3); // bb0[4]: scope 0 at foo.rs:13:34: 13:35
    nop; // bb0[5]: scope 1 at foo.rs:14:13: 14:20
    (_1.1: Foo) = move _2; // bb0[6]: scope 1 at foo.rs:14:23: 14:28
    StorageLive(_6); // bb0[7]: scope 3 at foo.rs:15:9: 15:14
    _6 = (); // bb0[8]: scope 3 at foo.rs:15:9: 15:14
    _0 = std::ops::GeneratorState<(), ()>::Yielded(move _6,); // bb0[9]: scope 3 at foo.rs:15:9: 15:14
    (_1.0: u32) = const 3u32; // bb0[10]: scope 3 at foo.rs:15:9: 15:14
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 3 })
    // mir::Constant
    // + span: foo.rs:15:9: 15:14
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 3 }) })
    return; // bb0[11]: scope 3 at foo.rs:15:9: 15:14
    }

    bb1: { // cleanup
    resume; // bb1[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb2: {
    _5 = (); // bb2[0]: scope 3 at foo.rs:15:9: 15:14
    StorageDead(_6); // bb2[1]: scope 3 at foo.rs:15:13: 15:14
    _7 = (); // bb2[2]: scope 0 at foo.rs:12:15: 16:6
    drop((_1.1: Foo)) -> [return: bb8, unwind: bb7]; // bb2[3]: scope 1 at foo.rs:16:5: 16:6
    }

    bb3: { // cleanup
    goto -> bb12; // bb3[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb4: {
    drop((_1.1: Foo)) -> [return: bb5, unwind: bb3]; // bb4[0]: scope 1 at foo.rs:16:5: 16:6
    }

    bb5: {
    goto -> bb13; // bb5[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb6: {
    generator_drop; // bb6[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb7: { // cleanup
    goto -> bb15; // bb7[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb8: {
    nop; // bb8[0]: scope 1 at foo.rs:16:5: 16:6
    StorageDead(_2); // bb8[1]: scope 0 at foo.rs:16:5: 16:6
    goto -> bb16; // bb8[2]: scope 0 at foo.rs:16:5: 16:6
    }

    bb9: {
    _0 = std::ops::GeneratorState<(), ()>::Complete(move _7,); // bb9[0]: scope 0 at foo.rs:16:6: 16:6
    (_1.0: u32) = const 1u32; // bb9[1]: scope 0 at foo.rs:16:6: 16:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:16:6: 16:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    return; // bb9[2]: scope 0 at foo.rs:16:6: 16:6
    }

    bb10: {
    return; // bb10[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb11: {
    goto -> bb18; // bb11[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb12: { // cleanup
    goto -> bb1; // bb12[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb13: {
    goto -> bb6; // bb13[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb14: { // cleanup
    goto -> bb1; // bb14[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb15: { // cleanup
    goto -> bb1; // bb15[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb16: {
    goto -> bb9; // bb16[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb17: { // cleanup
    goto -> bb1; // bb17[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb18: { // cleanup
    goto -> bb10; // bb18[0]: scope 0 at foo.rs:12:5: 16:6
    }
    }
    110 changes: 110 additions & 0 deletions rustc.simple-{{closure}}.-------.generator_pre-elab.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,110 @@
    // MIR for `simple::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:13 ~ foo[317d]::simple[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_pre-elab
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:14:23: 14:28)), pat_span: foo.rs:14:13: 14:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:14:13: 14:20, scope: scope[4] }, visibility_scope: scope[3] }] }

    fn simple::{{closure}}(_1: [static generator@foo.rs:12:5: 16:6 {Foo, ()}]) -> std::ops::GeneratorState<(), ()> {
    let mut _0: std::ops::GeneratorState<(), ()>; // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    let _2: Foo; // "first" in scope 2 at foo.rs:13:13: 13:18
    }
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();

    bb0: {
    StorageLive(_2); // bb0[0]: scope 0 at foo.rs:13:13: 13:18
    StorageLive(_3); // bb0[1]: scope 0 at foo.rs:13:25: 13:34
    _3 = [const 0u8; 1024]; // bb0[2]: scope 0 at foo.rs:13:25: 13:34
    // ty::Const
    // + ty: u8
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:13:26: 13:27
    // + ty: u8
    // + literal: Evaluated(Const { ty: u8, val: Scalar(Bits { size: 1, bits: 0 }) })
    _2 = Foo(move _3,); // bb0[3]: scope 0 at foo.rs:13:21: 13:35
    StorageDead(_3); // bb0[4]: scope 0 at foo.rs:13:34: 13:35
    nop; // bb0[5]: scope 1 at foo.rs:14:13: 14:20
    (_1.1: Foo) = move _2; // bb0[6]: scope 1 at foo.rs:14:23: 14:28
    StorageLive(_6); // bb0[7]: scope 3 at foo.rs:15:9: 15:14
    _6 = (); // bb0[8]: scope 3 at foo.rs:15:9: 15:14
    _0 = std::ops::GeneratorState<(), ()>::Yielded(move _6,); // bb0[9]: scope 3 at foo.rs:15:9: 15:14
    (_1.0: u32) = const 3u32; // bb0[10]: scope 3 at foo.rs:15:9: 15:14
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 3 })
    // mir::Constant
    // + span: foo.rs:15:9: 15:14
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 3 }) })
    return; // bb0[11]: scope 3 at foo.rs:15:9: 15:14
    }

    bb1: { // cleanup
    resume; // bb1[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb2: {
    _5 = (); // bb2[0]: scope 3 at foo.rs:15:9: 15:14
    StorageDead(_6); // bb2[1]: scope 3 at foo.rs:15:13: 15:14
    _7 = (); // bb2[2]: scope 0 at foo.rs:12:15: 16:6
    drop((_1.1: Foo)) -> [return: bb8, unwind: bb7]; // bb2[3]: scope 1 at foo.rs:16:5: 16:6
    }

    bb3: { // cleanup
    drop(_1) -> bb1; // bb3[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb4: {
    drop((_1.1: Foo)) -> [return: bb5, unwind: bb3]; // bb4[0]: scope 1 at foo.rs:16:5: 16:6
    }

    bb5: {
    drop(_1) -> [return: bb6, unwind: bb1]; // bb5[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb6: {
    generator_drop; // bb6[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb7: { // cleanup
    drop(_1) -> bb1; // bb7[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb8: {
    nop; // bb8[0]: scope 1 at foo.rs:16:5: 16:6
    StorageDead(_2); // bb8[1]: scope 0 at foo.rs:16:5: 16:6
    drop(_1) -> [return: bb9, unwind: bb1]; // bb8[2]: scope 0 at foo.rs:16:5: 16:6
    }

    bb9: {
    _0 = std::ops::GeneratorState<(), ()>::Complete(move _7,); // bb9[0]: scope 0 at foo.rs:16:6: 16:6
    (_1.0: u32) = const 1u32; // bb9[1]: scope 0 at foo.rs:16:6: 16:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:16:6: 16:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    return; // bb9[2]: scope 0 at foo.rs:16:6: 16:6
    }

    bb10: {
    return; // bb10[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb11: {
    drop(_1) -> bb10; // bb11[0]: scope 0 at foo.rs:12:5: 16:6
    }
    }
    138 changes: 138 additions & 0 deletions rustc.simple-{{closure}}.-------.generator_resume.0.mir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,138 @@
    // MIR for `simple::{{closure}}`
    // source = MirSource { instance: Item(DefId(0/1:13 ~ foo[317d]::simple[0]::{{closure}}[0])), promoted: None }
    // pass_name = generator_resume
    // disambiguator = 0
    // generator_layout = GeneratorLayout { fields: [LocalDecl { mutability: Not, is_user_variable: Some(Set(Var(VarBindingForm { binding_mode: BindByValue(MutImmutable), opt_ty_info: None, opt_match_place: Some((None, foo.rs:14:23: 14:28)), pat_span: foo.rs:14:13: 14:20 }))), internal: false, is_block_tail: None, ty: Foo, user_ty: UserTypeProjections { contents: [] }, name: Some(_second), source_info: SourceInfo { span: foo.rs:14:13: 14:20, scope: scope[4] }, visibility_scope: scope[3] }] }

    fn simple::{{closure}}(_1: std::pin::Pin<&mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}]>) -> std::ops::GeneratorState<(), ()> {
    let mut _0: std::ops::GeneratorState<(), ()>; // return place
    scope 1 {
    scope 3 {
    }
    scope 4 {
    }
    }
    scope 2 {
    let _2: Foo; // "first" in scope 2 at foo.rs:13:13: 13:18
    }
    let mut _3: [u8; 1024];
    let mut _4: ();
    let mut _5: ();
    let mut _6: ();
    let mut _7: ();

    bb0: {
    switchInt(((*(_1.0: &mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}])).0: u32)) -> [0u32: bb1, 1u32: bb10, 2u32: bb11, 3u32: bb9, otherwise: bb12]; // bb0[0]: scope 0 at foo.rs:12:5: 16:6
    }

    bb1: {
    StorageLive(_2); // bb1[0]: scope 0 at foo.rs:13:13: 13:18
    StorageLive(_3); // bb1[1]: scope 0 at foo.rs:13:25: 13:34
    _3 = [const 0u8; 1024]; // bb1[2]: scope 0 at foo.rs:13:25: 13:34
    // ty::Const
    // + ty: u8
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:13:26: 13:27
    // + ty: u8
    // + literal: Evaluated(Const { ty: u8, val: Scalar(Bits { size: 1, bits: 0 }) })
    _2 = Foo(move _3,); // bb1[3]: scope 0 at foo.rs:13:21: 13:35
    StorageDead(_3); // bb1[4]: scope 0 at foo.rs:13:34: 13:35
    nop; // bb1[5]: scope 1 at foo.rs:14:13: 14:20
    ((*(_1.0: &mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}])).1: Foo) = move _2; // bb1[6]: scope 1 at foo.rs:14:23: 14:28
    StorageLive(_6); // bb1[7]: scope 3 at foo.rs:15:9: 15:14
    _6 = (); // bb1[8]: scope 3 at foo.rs:15:9: 15:14
    _0 = std::ops::GeneratorState<(), ()>::Yielded(move _6,); // bb1[9]: scope 3 at foo.rs:15:9: 15:14
    ((*(_1.0: &mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}])).0: u32) = const 3u32; // bb1[10]: scope 3 at foo.rs:15:9: 15:14
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 3 })
    // mir::Constant
    // + span: foo.rs:15:9: 15:14
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 3 }) })
    return; // bb1[11]: scope 3 at foo.rs:15:9: 15:14
    }

    bb2: { // cleanup
    ((*(_1.0: &mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}])).0: u32) = const 1u32; // bb2[0]: scope 0 at foo.rs:12:5: 16:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:12:5: 16:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    resume; // bb2[1]: scope 0 at foo.rs:12:5: 16:6
    }

    bb3: {
    _5 = (); // bb3[0]: scope 3 at foo.rs:15:9: 15:14
    StorageDead(_6); // bb3[1]: scope 3 at foo.rs:15:13: 15:14
    _7 = (); // bb3[2]: scope 0 at foo.rs:12:15: 16:6
    drop(((*(_1.0: &mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}])).1: Foo)) -> [return: bb5, unwind: bb4]; // bb3[3]: scope 1 at foo.rs:16:5: 16:6
    }

    bb4: { // cleanup
    goto -> bb7; // bb4[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb5: {
    nop; // bb5[0]: scope 1 at foo.rs:16:5: 16:6
    StorageDead(_2); // bb5[1]: scope 0 at foo.rs:16:5: 16:6
    goto -> bb8; // bb5[2]: scope 0 at foo.rs:16:5: 16:6
    }

    bb6: {
    _0 = std::ops::GeneratorState<(), ()>::Complete(move _7,); // bb6[0]: scope 0 at foo.rs:16:6: 16:6
    ((*(_1.0: &mut [static generator@foo.rs:12:5: 16:6 {Foo, ()}])).0: u32) = const 1u32; // bb6[1]: scope 0 at foo.rs:16:6: 16:6
    // ty::Const
    // + ty: u32
    // + val: Scalar(Bits { size: 4, bits: 1 })
    // mir::Constant
    // + span: foo.rs:16:6: 16:6
    // + ty: u32
    // + literal: Evaluated(Const { ty: u32, val: Scalar(Bits { size: 4, bits: 1 }) })
    return; // bb6[2]: scope 0 at foo.rs:16:6: 16:6
    }

    bb7: { // cleanup
    goto -> bb2; // bb7[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb8: {
    goto -> bb6; // bb8[0]: scope 0 at foo.rs:16:5: 16:6
    }

    bb9: {
    StorageLive(_2); // bb9[0]: scope 0 at foo.rs:12:5: 16:6
    StorageLive(_6); // bb9[1]: scope 0 at foo.rs:12:5: 16:6
    goto -> bb3; // bb9[2]: scope 0 at foo.rs:12:5: 16:6
    }

    bb10: {
    assert(const false, "generator resumed after completion") -> bb10; // bb10[0]: scope 0 at foo.rs:12:5: 16:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:12:5: 16:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    }

    bb11: {
    assert(const false, "generator resumed after panicking") -> bb11; // bb11[0]: scope 0 at foo.rs:12:5: 16:6
    // ty::Const
    // + ty: bool
    // + val: Scalar(Bits { size: 1, bits: 0 })
    // mir::Constant
    // + span: foo.rs:12:5: 16:6
    // + ty: bool
    // + literal: Evaluated(Const { ty: bool, val: Scalar(Bits { size: 1, bits: 0 }) })
    }

    bb12: {
    unreachable; // bb12[0]: scope 0 at foo.rs:12:5: 16:6
    }
    }
    1 change: 0 additions & 1 deletion tmp
    Original file line number Diff line number Diff line change
    @@ -1 +0,0 @@
    tmp
  3. Nemo157 created this gist Mar 12, 2019.
    1 change: 1 addition & 0 deletions tmp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    tmp