You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While experimenting with gdb I found I couldn't really predict what statements I might step to. Consider this test program:
fn main () {
let a = ();
let b : [i32; 0] = [];
let mut c = 27;
let d = c = 99;
let e = "hi bob";
let f = b"hi bob";
let g = b'9';
let h = ["whatever"; 8];
let i = [1,2,3,4];
let j = (23, "hi");
let k = 2..3;
let l = &i[k];
let m: *const() = &a;
}
If I break step::main and run in gdb, stepping stops on many of these lines, but not all of them:
Breakpoint 1, step::main () at step.rs:4
4 let mut c = 27;
(gdb) n
5 let d = c = 99;
(gdb)
7 let f = b"hi bob";
(gdb)
8 let g = b'9';
(gdb)
12 let k = 2..3;
(gdb)
13 let l = &i[k];
(gdb)
14 let m: *const() = &a;
(gdb)
15 }
Latest rust (cb1f649) steps through every line now, although it will step through 'l' twice in my machine. Also it won't break in either 'a' or 'b', but I'm guessing this is intended (?).
Also it won't break in either 'a' or 'b', but I'm guessing this is intended (?).
It's not explicit but I think that's part of the original bug -- breaking in this main skips the first two lines, while stepping to many of the remaining lines.
Alright, then the two remaining issues would be to fix that (which was already present in April) and to figure out why it's going through 'l' twice now.
About not breaking in the first two lines: I can reproduce this in a C program like:
void main()
{
int a;
int b;
int c = 0;
}
gdb won't break in 'a' or 'b' either, no matter if this is compiled with GCC or clang. Looking at the IR if I compile this with clang it shares with the rust program the fact that there are actually no instructions generated, while the 'c' declaration has a 'store'. I'm guessing this is what makes gdb break in there in the end.
So not sure if we want to actually fix this, but if we do it is an issue shared with other languages. I'll look into the double step now.
gdb won't break in 'a' or 'b' either, no matter if this is compiled with GCC or clang
I wouldn't expect it in this case, as these are just declarations.
Whether Rust code should stop on a simple initialization-by-constant doesn't matter so much to me -- I just think the results should be consistent. That is, either it ought to stop at each of those lines, or none of them. (Though now that I write that, stopping at none of them might be weird.)
Oh, I see now. I guess the issue is that the code looks similar but the generated IR is different, for 'a' and 'b' LLVM has enough with the alloca's, but for other variables it generates stores, etc. I guess one option might be to generate some dummy instruction to make debuggers stop there, but I'll also have a look at this then.
Visited during wg-debugging triage. Currently, the stepping behavior behaves consistently for all lines except for the ZSTs a and b. We've decided to create a new issue for that specifically and therefore this ticket just needs a test and can then be closed.
nightly-2023-04-23-x86_64-unknown-linux-gnu unchanged - rustc 1.71.0-nightly (b628260df 2023-04-22)
Breakpoint 1, basic_stepping::main () at /tmp/basic-stepping.rs:37
37 let d = c = 99;
38 let e = "hi bob";
nightly-2023-04-24-x86_64-unknown-linux-gnu unchanged - rustc 1.71.0-nightly (7f94b314c 2023-04-23)
Breakpoint 1, basic_stepping::main () at /tmp/basic-stepping.rs:37
37 let d = c = 99;
41 let h = ["whatever"; 8];
Note that lines are consecutive with nightly-2023-04-23 but not with nightly-2023-04-24.
173845c Remove the size of locals heuristic in MIR inlining b8c67d8 Fortify test. 4e8b642 Turn on ConstDebugInfo pass. 4ad04ad Set debug location to debug operand spill. da5d01d Remove unused synstructure dep f77541a Update chrono/spdx-rs 3344232 Run check_match and check_liveness when MIR is built instead of having an explicit phase for them 5bb58a6 Make check_match and check_liveness take a LocalDefId 1ce80e2 Allow LocalDefId as the argument to def_path_str e18d1f8 Leave it to the query system to invoke the typeck query instead of invoking it eagerly. f74fe8b Limit read size in File::read_to_end loop 99962a8 Refactor SyntaxContext::ctxt logic. 2e98368 make sysroot finding compatible with multiarch systems
Probably 4e8b642 or 4ad04ad but none of those revert cleanly any longer.
Update 2025-10-07
I have bisected it further. It regressed with 4e8b642. I also updated the reproducer above.
Activity
michaelwoerister commentedon Apr 19, 2016
This will hopefully get some more attention again once we switch to MIR for code generation.
xanlpz commentedon Feb 27, 2017
Latest rust (cb1f649) steps through every line now, although it will step through 'l' twice in my machine. Also it won't break in either 'a' or 'b', but I'm guessing this is intended (?).
tromey commentedon Feb 27, 2017
It's not explicit but I think that's part of the original bug -- breaking in this main skips the first two lines, while stepping to many of the remaining lines.
xanlpz commentedon Feb 27, 2017
Alright, then the two remaining issues would be to fix that (which was already present in April) and to figure out why it's going through 'l' twice now.
xanlpz commentedon Mar 1, 2017
About not breaking in the first two lines: I can reproduce this in a C program like:
gdb won't break in 'a' or 'b' either, no matter if this is compiled with GCC or clang. Looking at the IR if I compile this with clang it shares with the rust program the fact that there are actually no instructions generated, while the 'c' declaration has a 'store'. I'm guessing this is what makes gdb break in there in the end.
So not sure if we want to actually fix this, but if we do it is an issue shared with other languages. I'll look into the double step now.
tromey commentedon Mar 1, 2017
I wouldn't expect it in this case, as these are just declarations.
Whether Rust code should stop on a simple initialization-by-constant doesn't matter so much to me -- I just think the results should be consistent. That is, either it ought to stop at each of those lines, or none of them. (Though now that I write that, stopping at none of them might be weird.)
xanlpz commentedon Mar 1, 2017
Oh, I see now. I guess the issue is that the code looks similar but the generated IR is different, for 'a' and 'b' LLVM has enough with the alloca's, but for other variables it generates stores, etc. I guess one option might be to generate some dummy instruction to make debuggers stop there, but I'll also have a look at this then.
tromey commentedon Mar 1, 2017
Thanks, that makes sense to me; I hadn't really thought about that. TBH I doubt it is worth pessimizing code to make this work.
wesleywiser commentedon May 16, 2022
Visited during wg-debugging triage. Currently, the stepping behavior behaves consistently for all lines except for the ZSTs
aandb. We've decided to create a new issue for that specifically and therefore this ticket just needs a test and can then be closed.Enselic commentedon Jul 26, 2025
Unfortunately this regressed in nightly-2023-04-24. A test to prevent further regressions is added in #144497.
The following uses the test in that PR.
Note that lines are consecutive with nightly-2023-04-23 but not with nightly-2023-04-24.
Here is the list of candidates:
173845c Remove the size of locals heuristic in MIR inlining
b8c67d8 Fortify test.
4e8b642 Turn on ConstDebugInfo pass.
4ad04ad Set debug location to debug operand spill.
da5d01d Remove unused
synstructuredepf77541a Update chrono/spdx-rs
3344232 Run
check_matchandcheck_livenesswhen MIR is built instead of having an explicit phase for them5bb58a6 Make
check_matchandcheck_livenesstake aLocalDefId1ce80e2 Allow
LocalDefIdas the argument todef_path_stre18d1f8 Leave it to the query system to invoke the typeck query instead of invoking it eagerly.
f74fe8b Limit read size in
File::read_to_endloop99962a8 Refactor
SyntaxContext::ctxtlogic.2e98368 make sysroot finding compatible with multiarch systems
Probably 4e8b642 or 4ad04ad but none of those revert cleanly any longer.Update 2025-10-07
I have bisected it further. It regressed with 4e8b642. I also updated the reproducer above.
16 remaining items
Enselic commentedon Mar 16, 2026
mir_opt_level > 1forSingleUseConstsMIR pass #151426.Auto merge of #153877 - Enselic:basic-stepping-aarch64, r=mati865
Rollup merge of rust-lang#153941 - Enselic:fully-steppable, r=saethlin
Rollup merge of rust-lang#153941 - Enselic:fully-steppable, r=saethlin
Rollup merge of rust-lang#153941 - Enselic:fully-steppable, r=saethlin
Rollup merge of rust-lang#153941 - Enselic:fully-steppable, r=saethlin
Unrolled build for #153941
Rollup merge of #153941 - Enselic:fully-steppable, r=saethlin
Rollup merge of #153941 - Enselic:fully-steppable, r=saethlin
Rollup merge of rust-lang#155769 - Enselic:ping-enselic, r=Urgau
Rollup merge of rust-lang#155769 - Enselic:ping-enselic, r=Urgau
Rollup merge of rust-lang#155769 - Enselic:ping-enselic, r=Urgau
Unrolled build for #155769
Rollup merge of #153941 - Enselic:fully-steppable, r=saethlin