Skip to content

StorageLive and StorageDead annotations in generators are wrong #44179

Closed
@oli-obk

Description

@oli-obk

The generator

|| {
        if { yield; false } {
            yield;
            loop {}
        }
        yield
    }

produces the following MIR:

fn main::{{closure}}(_1: &mut [generator@src/main.rs:20:15: 26:6 ((), bool)]) -> std::ops::GeneratorState<(), ()> {
    let mut _0: std::ops::GeneratorState<(), ()>; // return pointer
    let mut _2: ();
    let mut _3: bool;
    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)) -> [2u32: bb2, 0u32: bb1, 3u32: bb5, 4u32: bb7, 1u32: bb11, 5u32: bb9, otherwise: bb9]; // scope 0 at src/main.rs:20:15: 26:6
    }

    bb1: {
        StorageLive(_3);                 // scope 0 at src/main.rs:21:12: 21:28
        StorageLive(_5);                 // scope 0 at src/main.rs:21:14: 21:19
        _5 = ();                         // scope 0 at src/main.rs:21:14: 21:19
        ((*_1).0: u32) = const 2u32;     // scope 0 at src/main.rs:21:14: 21:19
        _0 = std::ops::GeneratorState<(), ()>::Yielded(_5,); // scope 0 at src/main.rs:21:14: 21:19
        return;                          // scope 0 at src/main.rs:21:14: 21:19
    }

    bb2: {
        _4 = ();                         // scope 0 at src/main.rs:21:14: 21:19
        StorageDead(_5);                 // scope 0 at src/main.rs:21:19: 21:19
        _3 = const false;                // scope 0 at src/main.rs:21:21: 21:26
        switchInt(_3) -> [0u8: bb4, otherwise: bb3]; // scope 0 at src/main.rs:21:9: 24:10
    }

    bb3: {
        StorageLive(_7);                 // scope 0 at src/main.rs:22:13: 22:18
        _7 = ();                         // scope 0 at src/main.rs:22:13: 22:18
        ((*_1).0: u32) = const 3u32;     // scope 0 at src/main.rs:22:13: 22:18
        _0 = std::ops::GeneratorState<(), ()>::Yielded(_7,); // scope 0 at src/main.rs:22:13: 22:18
        return;                          // scope 0 at src/main.rs:22:13: 22:18
    }

    bb4: {
        _2 = ();                         // scope 0 at src/main.rs:21:9: 24:10
        StorageDead(_3);                 // scope 0 at src/main.rs:24:10: 24:10
        StorageLive(_9);                 // scope 0 at src/main.rs:25:9: 25:14
        _9 = ();                         // scope 0 at src/main.rs:25:9: 25:14
        ((*_1).0: u32) = const 4u32;     // scope 0 at src/main.rs:25:9: 25:14
        _0 = std::ops::GeneratorState<(), ()>::Yielded(_9,); // scope 0 at src/main.rs:25:9: 25:14
        return;                          // scope 0 at src/main.rs:25:9: 25:14
    }

    bb5: {
        _6 = ();                         // scope 0 at src/main.rs:22:13: 22:18
        StorageDead(_7);                 // scope 0 at src/main.rs:22:18: 22:18
        goto -> bb6;                     // scope 0 at src/main.rs:23:13: 23:20
    }

    bb6: {
        _8 = ();                         // scope 0 at src/main.rs:23:18: 23:20
        goto -> bb6;                     // scope 0 at src/main.rs:23:13: 23:20
    }

    bb7: {
        _10 = ();                        // scope 0 at src/main.rs:25:9: 25:14
        StorageDead(_9);                 // scope 0 at src/main.rs:25:14: 25:14
        goto -> bb10;                    // scope 0 at src/main.rs:26:6: 26:6
    }

    bb8: {
        ((*_1).0: u32) = const 5u32;     // scope 0 at src/main.rs:26:6: 26:6
        _0 = std::ops::GeneratorState<(), ()>::Complete(_10,); // scope 0 at src/main.rs:26:6: 26:6
        return;                          // scope 0 at src/main.rs:26:6: 26:6
    }

    bb9: {
        assert(const false, "generator resumed after completion") -> bb9; // scope 0 at src/main.rs:20:15: 26:6
    }

    bb10: {
        goto -> bb8;                     // scope 0 at src/main.rs:26:6: 26:6
    }

    bb11: {
        assert(const false, "generator resumed after panicking") -> bb9; // scope 0 at src/main.rs:20:15: 26:6
    }
}

Note the assignment to _3 in bb2, which is not preceded by a StorageLive in this invocation of the generator.

Full example in the playground: https://play.rust-lang.org/?gist=680d18fb9f9bdc91ab969fdbd8bb72a2&version=nightly

cc @Zoxc

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-coroutinesArea: CoroutinesC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions