Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: Setting a breakpoint on in rust-gdb results in gdb stopping before 's stack slot is initialized, and gdb dereferences it to print wrong values based on : Note the incorrect different values of as I step past initialization. The breakpoint should trigger just after that , not before it. The other functions in that program indeed do it correctly. Oddly, it seems like the operator is necessary for my repro, though maybe that has something to do with the hidden var. (Note that vs is necessary to actually avoid accidental correct values of due to stack reuse, so the other functions can't print wrong as written. But I'm just looking at where the breakpoint hits in disassembly.) Here's relevant llvm-dwarfdump from this binary, with a pointing at at the () rather than the : This looks pretty related to and Like , the repro hits on 1.71 but not 1.70. I'm filing separately because, unlike it, disabling SingleUseConsts doesn't seem to fix the breakpoint. I'm not 100% sure I'm disabling it right - you can see my command above. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details
I'm not familiar with github's notification rules, so pinging
Thanks for the tag, I wouldn't have seen this otherwise. From , we can see that the "prologue end" marker that tells the debugger where to stop is indeed placed on the mov I suspect this is due to the desugaring of the ? operator since the column number provided is 29.
label +A-debuginfo
Sure enough, ConstDebugInfo is in there.
I guess you probably saw, but does suggest that the bisect is somehow misleading.
Yes, getting the values wrong at function entry is especially bad because it messes up conditional breakpoints.
Disabling the pass doesn't do anything here because the is created by when it removes . Otherwise this is identical to . The easiest way to fix this would be for DILocation to carry a "this is not a statement" flag that overrides LLVM's usual line based inference of statement markers. I'll run it by the LLVM folks and see what they say.
Actually, in this particular case, because the const is a ZST I think we can do better today without LLVM changes.
Thanks for reporting this. The linked PR will fix this particular degenerate case.

Discussion:
fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation) { self.location = Some(dbg_loc); } <ins> fn clear_dbg_loc(&mut self) { self.location = None; } </ins> } /// Generate the `debug_context` in an MIR Body.

#![doc = include_str!("doc.md")] use std::cell::{OnceCell, RefCell}; <del> use std::iter; </del> use std::ops::Range; <ins> use std::{iter, ptr}; </ins> use libc::c_uint; use rustc_codegen_ssa::debuginfo::type_names;

} } <ins> fn clear_dbg_loc(&mut self) { unsafe { llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, ptr::null()); } } </ins> fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { gdb::insert_reference_to_gdb_debug_scripts_section_global(self) }

pub fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>); // Metadata <del> pub fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: &'a Metadata); </del> <ins> pub fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: *const Metadata); </ins> // Terminators pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value;

self.set_debug_loc(bx, var.source_info); let base = Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx); <ins> bx.clear_dbg_loc(); </ins> bx.dbg_var_addr( dbg_var,

fragment: Option<Range<Size>>, ); fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation); <ins> fn clear_dbg_loc(&mut self); </ins> fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); fn set_var_name(&mut self, value: Self::Value, name: &str); }

<ins> //@ min-lldb-version: 310 //@ compile-flags:-g // === GDB TESTS =================================================================================== // gdb-command:break zst_interferes_with_prologue::Foo::var_return_opt_try // gdb-command:run // gdb-command:print self // gdb-command:next // gdb-command:print self // gdb-command:print $1 == $2 // gdb-check:true // === LLDB TESTS ================================================================================== // lldb-command:b "zst_interferes_with_prologue::Foo::var_return_opt_try" // lldb-command:run // lldb-command:expr self // lldb-command:next // lldb-command:expr self // lldb-command:print $0 == $1 // lldb-check:true struct Foo { a: usize, } impl Foo { #[inline(never)] fn get_a(&self) -> Option<usize> { Some(self.a) } #[inline(never)] fn var_return(&self) -> usize { let r = self.get_a().unwrap(); r } #[inline(never)] fn var_return_opt_unwrap(&self) -> Option<usize> { let r = self.get_a().unwrap(); Some(r) } #[inline(never)] fn var_return_opt_match(&self) -> Option<usize> { let r = match self.get_a() { None => return None, Some(a) => a, }; Some(r) } #[inline(never)] fn var_return_opt_try(&self) -> Option<usize> { let r = self.get_a()?; Some(r) } } fn main() { let f1 = Foo{ a: 1 }; let f2 = Foo{ a: 1 }; f1.var_return(); f1.var_return_opt_unwrap(); f1.var_return_opt_match(); f2.var_return_opt_try(); } </ins>