Skip to content

SimplifyComparisonIntegral introduces access to a dead local variable #158231

Description

@tmiasko
#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;

#[custom_mir(dialect = "runtime")]
pub fn f(a: bool) {
    mir! {
        let b: u32;
        let c: bool;
        {
            StorageLive(b);
            Goto(bb1)
        }
        bb1 = {
            b = a as u32;
            c = b == 42;
            StorageDead(b);
            StorageLive(b);
            match Move(c) {
                true => bb1,
                _    => bb2,
            }
        }
        bb2 = {
            StorageDead(b);
            Return()
        }
    }
}

rustc a.rs --crate-type=lib -Zmir-opt-level=0 -Zmir-enable-passes=+SimplifyComparisonIntegral -Zunpretty=mir

fn f(_1: bool) -> () {
    let mut _0: ();
    let mut _2: u32;
    let mut _3: bool;

    bb0: {
        StorageLive(_2);
        goto -> bb1;
    }

    bb1: {
        StorageDead(_2);
        _2 = copy _1 as u32 (IntToInt); // undefined behavior: _2 is dead
        nop;
        nop;
        StorageLive(_2);
        switchInt(copy _2) -> [42: bb1, otherwise: bb2];
    }

    bb2: {
        StorageDead(_2);
        StorageDead(_2);
        return;
    }
}

Meta

rustc --version --verbose:

rustc 1.98.0-nightly (8b6558a02 2026-06-20)

Activity

  1. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    A-mir-optArea: MIR optimizations
    I-miscompileIssue: Correct Rust code lowers to incorrect machine code
    on Jun 21, 2026
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jun 21, 2026
  3. hanna-kruppe commented on Jun 21, 2026

    @hanna-kruppe
    Contributor

    From what I can tell, the pass's logic for shuffling StorageDeads around tries to identify StorageDeads that would interfere with extending the lifetime of the comparison result, and sink them into successor blocks (i.e., after the switchInt). In this case, the block is its own successor, so the StorageDead gets hoisted unintentionally. Presumably this problem can occur for any block involved in a loop.

  4. hanna-kruppe commented on Jun 21, 2026

    @hanna-kruppe
    Contributor

    I think the StorageLive(_2) in bb1 is also problematic, since StorageLive is defined to free the local and re-allocate it with. Probably the whole StorageLive/StorageDead handling needs to be overhauled completely.

  5. removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jun 22, 2026
  6. qaijuang commented on Jul 13, 2026

    @qaijuang
    Contributor

    @rustbot claim

  7. removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jul 19, 2026
  8. rustbot commented on Jul 19, 2026

    @rustbot
    Collaborator

    Assigning P-high (discussion on Zulip).

  9. added 2 commits that reference this issue on Jul 28, 2026
    38f7339
    bf0e3ce
  10. added a commit that references this issue on Jul 28, 2026
    990bfa8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-mir-optArea: MIR optimizationsC-bugCategory: This is a bug.I-miscompileIssue: Correct Rust code lowers to incorrect machine codeP-highHigh priorityT-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