diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index f48dba9663a52..8ad6487e0967a 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -15,7 +15,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; -use rustc_session::config::{DebugInfo, OptLevel}; +use rustc_session::config::OptLevel; use rustc_span::source_map::Spanned; use tracing::{debug, instrument, trace, trace_span}; @@ -982,16 +982,7 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( // Insert all of the (mapped) parts of the callee body into the caller. caller_body.local_decls.extend(callee_body.drain_vars_and_temps()); caller_body.source_scopes.append(&mut callee_body.source_scopes); - if tcx - .sess - .opts - .unstable_opts - .inline_mir_preserve_debug - .unwrap_or(tcx.sess.opts.debuginfo != DebugInfo::None) - { - // Note that we need to preserve these in the standard library so that - // people working on rust can build with or without debuginfo while - // still getting consistent results from the mir-opt tests. + if tcx.sess.keep_var_debug_info() { caller_body.var_debug_info.append(&mut callee_body.var_debug_info); } caller_body.basic_blocks_mut().append(callee_body.basic_blocks_mut()); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ad58c3c8f7d8b..64030e135a5cb 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -765,6 +765,18 @@ impl Session { .unwrap_or(self.target.default_dwarf_version) } + /// Whether to maintain `Body.var_debug_info` that keeps track where variables were declared + pub fn keep_var_debug_info(&self) -> bool { + // -Zinline-mir-preserve-debug is enabled when building the standard library, so that + // people working on rust can build with or without debuginfo while + // still getting consistent results from the mir-opt tests. + self.opts + .unstable_opts + .inline_mir_preserve_debug + // only "full" promises any variable-level information + .unwrap_or(self.opts.debuginfo == DebugInfo::Full) + } + pub fn stack_protector(&self) -> StackProtector { if self.target.options.supports_stack_protector { self.opts.unstable_opts.stack_protector diff --git a/tests/mir-opt/inline_var_debug_info_kept.rs b/tests/mir-opt/inline_var_debug_info_kept.rs new file mode 100644 index 0000000000000..e2f00fc6ee929 --- /dev/null +++ b/tests/mir-opt/inline_var_debug_info_kept.rs @@ -0,0 +1,50 @@ +//@ test-mir-pass: Inline +//@ revisions: PRESERVE FULL NONE LIMITED +//@ [PRESERVE]compile-flags: -O -C debuginfo=0 -Zinline-mir-preserve-debug +//@ [FULL]compile-flags: -O -C debuginfo=2 +//@ [NONE]compile-flags: -O -C debuginfo=0 +//@ [LIMITED]compile-flags: -O -C debuginfo=1 + +#[inline(always)] +fn inline_fn1(arg1: i32) -> i32 { + let local1 = arg1 + 1; + let _local2 = 10; + arg1 + local1 +} + +#[inline(always)] +fn inline_fn2(binding: i32) -> i32 { + { + let binding = inline_fn1(binding); + binding + } +} + +#[inline(never)] +fn test() -> i32 { + // CHECK-LABEL: fn test + inline_fn2(1) + // CHECK-LABEL: (inlined inline_fn2) + + // PRESERVE: debug binding => + // FULL: debug binding => + // NONE-NOT: debug binding => + // LIMITED-NOT: debug binding => + + // CHECK-LABEL: (inlined inline_fn1) + + // PRESERVE: debug arg1 => + // FULL: debug arg1 => + // NONE-NOT: debug arg1 => + // LIMITED-NOT: debug arg1 => + + // PRESERVE: debug local1 => + // FULL: debug local1 => + // NONE-NOT: debug local1 => + // LIMITED-NOT: debug local1 => + + // PRESERVE: debug _local2 => + // FULL: debug _local2 => + // NONE-NOT: debug _local2 => + // LIMITED-NOT: debug _local2 => +}