Skip to content

Debugger step-over runs backward #141344

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
vlad20012 opened this issue May 21, 2025 · 4 comments
Open

Debugger step-over runs backward #141344

vlad20012 opened this issue May 21, 2025 · 4 comments
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@vlad20012
Copy link
Member

Setup

main.rs:

fn main() {
    let a = 2; // 1
    let b = 3; // 3
    if b > 0 {
        let b = 10; // 2
        println!("a + b = {}", a + b);
    }
    println!("a = {}", b);
}

Reproducing in terminal:

cargo build
lldb-19 target/debug/debugger-bug

(lldb) breakpoint set --file main.rs --line 2
Breakpoint 1: where = debugger-bug`debugger_bug::main::h53ce27eca21116c8 + 7 at main.rs:2:9, address = 0x0000000000015aa7
(lldb) run
Process 551489 launched: '/home/vlad20012/RustroverProjects/debugger-bug/target/debug/debugger-bug' (x86_64)
Process 551489 stopped
* thread #1, name = 'debugger-bug', stop reason = breakpoint 1.1
    frame #0: 0x0000555555569aa7 debugger-bug`debugger_bug::main::h53ce27eca21116c8 at main.rs:2:9
   1    fn main() {
-> 2        let a = 2;
   3        let b = 3;
   4        if b > 0 {
   5            let b = 10;
   6            println!("a + b = {}", a + b);
   7        }
(lldb) step
Process 551489 stopped
* thread #1, name = 'debugger-bug', stop reason = step in
    frame #0: 0x0000555555569ab2 debugger-bug`debugger_bug::main::h53ce27eca21116c8 at main.rs:5:13
   2        let a = 2;
   3        let b = 3;
   4        if b > 0 {
-> 5            let b = 10;
   6            println!("a + b = {}", a + b);
   7        }
   8        println!("a = {}", b);
(lldb) step
Process 551489 stopped
* thread #1, name = 'debugger-bug', stop reason = step in
    frame #0: 0x0000555555569abd debugger-bug`debugger_bug::main::h53ce27eca21116c8 at main.rs:3:13
   1    fn main() {
   2        let a = 2;
-> 3        let b = 3;
   4        if b > 0 {
   5            let b = 10;
   6            println!("a + b = {}", a + b);
   7        }

Reproducing in RustRover:

Screencast.from.2025-05-21.15-04-15.mp4

Env

LLDB:

lldb version 19.1.7

Rust:

rustc 1.89.0-nightly (bc82152 2025-05-20)
or
rustc 1.87.0 (17067e9 2025-05-09)

@vlad20012 vlad20012 added the C-bug Category: This is a bug. label May 21, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 21, 2025
@vlad20012
Copy link
Member Author

vlad20012 commented May 21, 2025

The bug is not reproduced with -Zmir-enable-passes=-SingleUseConsts, so the optimization is most likely the cause.

In disassembly it's clear that the assignments were reordered:

Image

rustc -Zdump-mir=main src/main.rs:

main.main.3-2-015.SingleUseConsts.before.mir:

    bb0: {
        _1 = const 2_i32;
        _2 = const 3_i32;
        _4 = copy _2;
        _3 = Gt(move _4, const 0_i32);
        switchInt(move _3) -> [0: bb5, otherwise: bb1];
    }

    bb1: {
        _5 = const 10_i32;
        _31 = const main::promoted[1];
        _9 = copy _31;
        _8 = copy _9;
        _17 = copy _1;
        _18 = copy _5;
        _19 = AddWithOverflow(copy _17, copy _18);
        assert(!move (_19.1: bool), "attempt to compute `{} + {}`, which would overflow", move _17, move _18) -> [success: bb2, unwind continue];
    }

main.main.3-2-015.SingleUseConsts.after.mir:

    bb0: {
        nop;
        _2 = const 3_i32;
        _4 = copy _2;
        _3 = Gt(move _4, const 0_i32);
        switchInt(move _3) -> [0: bb5, otherwise: bb1];
    }

    bb1: {
        nop;
        nop;
        _9 = const main::promoted[1];
        _8 = copy _9;
        _17 = const 2_i32;
        _18 = const 10_i32;
        _19 = AddWithOverflow(copy _17, copy _18);
        assert(!move (_19.1: bool), "attempt to compute `{} + {}`, which would overflow", move _17, move _18) -> [success: bb2, unwind continue];
    }

c.c. @scottmcm #125910

@bjorn3 bjorn3 added the A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) label May 21, 2025
@jieyouxu jieyouxu added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-mir-opt Area: MIR optimizations and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. A-mir-opt Area: MIR optimizations labels May 21, 2025
@scottmcm
Copy link
Member

FWIW, I think what SingleUseConsts is doing here is entirely fine.

There isn't an assignment in the MIR, so that assembly is an artifact of how the debug info is being emitted.

@scottmcm scottmcm added A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) and removed A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) labels May 21, 2025
@vlad20012
Copy link
Member Author

vlad20012 commented May 21, 2025

сс @wesleywiser - can be related to #73210

@khuey
Copy link
Contributor

khuey commented May 21, 2025

This is a duplicate of #113819 I believe. (Or at least the same root cause)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants