Skip to content

Debugger step-over runs backward #141344

New issue

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

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

Already on GitHub? Sign in 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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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