Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit dca1e7a

Browse files
committedFeb 2, 2022
Auto merge of #93154 - michaelwoerister:fix-generic-closure-and-generator-debuginfo, r=wesleywiser
debuginfo: Make sure that type names for closure and generator environments are unique in debuginfo. Before this change, closure/generator environments coming from different instantiations of the same generic function were all assigned the same name even though they were distinct types with potentially different data layout. Now we append the generic arguments of the originating function to the type name. This commit also emits `{closure_env#0}` as the name of these types in order to disambiguate them from the accompanying closure function (which keeps being called `{closure#0}`). Previously both were assigned the same name. NOTE: Changing debuginfo names like this can break pretty printers and other debugger plugins. I think it's OK in this particular case because the names we are changing were ambiguous anyway. In general though it would be great to have a process for doing changes like these.
2 parents 250384e + fd7557b commit dca1e7a

File tree

14 files changed

+287
-121
lines changed

14 files changed

+287
-121
lines changed
 

‎compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_data_structures::sync::Lrc;
2525
use rustc_hir::def_id::{DefId, DefIdMap};
2626
use rustc_index::vec::IndexVec;
2727
use rustc_middle::mir;
28-
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
28+
use rustc_middle::ty::layout::LayoutOf;
2929
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
3030
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
3131
use rustc_session::config::{self, DebugInfo};
@@ -318,9 +318,11 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
318318
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
319319
maybe_definition_llfn: Option<&'ll Value>,
320320
) -> &'ll DIScope {
321+
let tcx = self.tcx;
322+
321323
let def_id = instance.def_id();
322324
let containing_scope = get_containing_scope(self, instance);
323-
let span = self.tcx.def_span(def_id);
325+
let span = tcx.def_span(def_id);
324326
let loc = self.lookup_debug_loc(span.lo());
325327
let file_metadata = file_metadata(self, &loc.file);
326328

@@ -330,16 +332,24 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
330332
};
331333

332334
let mut name = String::new();
333-
type_names::push_item_name(self.tcx(), def_id, false, &mut name);
335+
type_names::push_item_name(tcx, def_id, false, &mut name);
334336

335337
// Find the enclosing function, in case this is a closure.
336-
let enclosing_fn_def_id = self.tcx().typeck_root_def_id(def_id);
338+
let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
339+
340+
// We look up the generics of the enclosing function and truncate the substs
341+
// to their length in order to cut off extra stuff that might be in there for
342+
// closures or generators.
343+
let generics = tcx.generics_of(enclosing_fn_def_id);
344+
let substs = instance.substs.truncate_to(tcx, generics);
345+
346+
type_names::push_generic_params(
347+
tcx,
348+
tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs),
349+
&mut name,
350+
);
337351

338-
// Get_template_parameters() will append a `<...>` clause to the function
339-
// name if necessary.
340-
let generics = self.tcx().generics_of(enclosing_fn_def_id);
341-
let substs = instance.substs.truncate_to(self.tcx(), generics);
342-
let template_parameters = get_template_parameters(self, generics, substs, &mut name);
352+
let template_parameters = get_template_parameters(self, generics, substs);
343353

344354
let linkage_name = &mangled_name_of_instance(self, instance).name;
345355
// Omit the linkage_name if it is the same as subprogram name.
@@ -361,7 +371,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
361371
if self.sess().opts.optimize != config::OptLevel::No {
362372
spflags |= DISPFlags::SPFlagOptimized;
363373
}
364-
if let Some((id, _)) = self.tcx.entry_fn(()) {
374+
if let Some((id, _)) = tcx.entry_fn(()) {
365375
if id == def_id {
366376
spflags |= DISPFlags::SPFlagMainSubprogram;
367377
}
@@ -440,14 +450,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
440450
cx: &CodegenCx<'ll, 'tcx>,
441451
generics: &ty::Generics,
442452
substs: SubstsRef<'tcx>,
443-
name_to_append_suffix_to: &mut String,
444453
) -> &'ll DIArray {
445-
type_names::push_generic_params(
446-
cx.tcx,
447-
cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs),
448-
name_to_append_suffix_to,
449-
);
450-
451454
if substs.types().next().is_none() {
452455
return create_DIArray(DIB(cx), &[]);
453456
}

‎compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

Lines changed: 74 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313

1414
use rustc_data_structures::fx::FxHashSet;
1515
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
16-
use rustc_hir as hir;
1716
use rustc_hir::def_id::DefId;
1817
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
18+
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
1919
use rustc_middle::ty::layout::IntegerExt;
2020
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
2121
use rustc_middle::ty::{self, AdtDef, ExistentialProjection, Ty, TyCtxt};
@@ -102,14 +102,14 @@ fn push_debuginfo_type_name<'tcx>(
102102
ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
103103
if cpp_like_debuginfo {
104104
match mutbl {
105-
hir::Mutability::Not => output.push_str("ptr_const$<"),
106-
hir::Mutability::Mut => output.push_str("ptr_mut$<"),
105+
Mutability::Not => output.push_str("ptr_const$<"),
106+
Mutability::Mut => output.push_str("ptr_mut$<"),
107107
}
108108
} else {
109109
output.push('*');
110110
match mutbl {
111-
hir::Mutability::Not => output.push_str("const "),
112-
hir::Mutability::Mut => output.push_str("mut "),
111+
Mutability::Not => output.push_str("const "),
112+
Mutability::Mut => output.push_str("mut "),
113113
}
114114
}
115115

@@ -131,8 +131,8 @@ fn push_debuginfo_type_name<'tcx>(
131131
output.push_str(mutbl.prefix_str());
132132
} else if !is_slice_or_str {
133133
match mutbl {
134-
hir::Mutability::Not => output.push_str("ref$<"),
135-
hir::Mutability::Mut => output.push_str("ref_mut$<"),
134+
Mutability::Not => output.push_str("ref$<"),
135+
Mutability::Mut => output.push_str("ref_mut$<"),
136136
}
137137
}
138138

@@ -345,14 +345,39 @@ fn push_debuginfo_type_name<'tcx>(
345345
// processing
346346
visited.remove(t);
347347
}
348-
ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => {
349-
let key = tcx.def_key(def_id);
348+
ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
349+
// Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
350+
// "{async_fn_env#0}<T1, T2, ...>", etc.
351+
let def_key = tcx.def_key(def_id);
352+
350353
if qualified {
351-
let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
354+
let parent_def_id = DefId { index: def_key.parent.unwrap(), ..def_id };
352355
push_item_name(tcx, parent_def_id, true, output);
353356
output.push_str("::");
354357
}
355-
push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output);
358+
359+
let mut label = String::with_capacity(20);
360+
write!(&mut label, "{}_env", generator_kind_label(tcx.generator_kind(def_id))).unwrap();
361+
362+
push_disambiguated_special_name(
363+
&label,
364+
def_key.disambiguated_data.disambiguator,
365+
cpp_like_debuginfo,
366+
output,
367+
);
368+
369+
// We also need to add the generic arguments of the async fn/generator or
370+
// the enclosing function (for closures or async blocks), so that we end
371+
// up with a unique name for every instantiation.
372+
373+
// Find the generics of the enclosing function, as defined in the source code.
374+
let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
375+
let generics = tcx.generics_of(enclosing_fn_def_id);
376+
377+
// Truncate the substs to the length of the above generics. This will cut off
378+
// anything closure- or generator-specific.
379+
let substs = substs.truncate_to(tcx, generics);
380+
push_generic_params_internal(tcx, substs, output, visited);
356381
}
357382
// Type parameters from polymorphized functions.
358383
ty::Param(_) => {
@@ -509,6 +534,29 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &
509534
push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output);
510535
}
511536

537+
fn generator_kind_label(generator_kind: Option<GeneratorKind>) -> &'static str {
538+
match generator_kind {
539+
Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) => "async_block",
540+
Some(GeneratorKind::Async(AsyncGeneratorKind::Closure)) => "async_closure",
541+
Some(GeneratorKind::Async(AsyncGeneratorKind::Fn)) => "async_fn",
542+
Some(GeneratorKind::Gen) => "generator",
543+
None => "closure",
544+
}
545+
}
546+
547+
fn push_disambiguated_special_name(
548+
label: &str,
549+
disambiguator: u32,
550+
cpp_like_debuginfo: bool,
551+
output: &mut String,
552+
) {
553+
if cpp_like_debuginfo {
554+
write!(output, "{}${}", label, disambiguator).unwrap();
555+
} else {
556+
write!(output, "{{{}#{}}}", label, disambiguator).unwrap();
557+
}
558+
}
559+
512560
fn push_unqualified_item_name(
513561
tcx: TyCtxt<'_>,
514562
def_id: DefId,
@@ -519,42 +567,32 @@ fn push_unqualified_item_name(
519567
DefPathData::CrateRoot => {
520568
output.push_str(tcx.crate_name(def_id.krate).as_str());
521569
}
522-
DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
523-
let key = match tcx.generator_kind(def_id).unwrap() {
524-
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "async_block",
525-
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "async_closure",
526-
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "async_fn",
527-
hir::GeneratorKind::Gen => "generator",
528-
};
529-
// Generators look like closures, but we want to treat them differently
530-
// in the debug info.
531-
if cpp_like_debuginfo(tcx) {
532-
write!(output, "{}${}", key, disambiguated_data.disambiguator).unwrap();
533-
} else {
534-
write!(output, "{{{}#{}}}", key, disambiguated_data.disambiguator).unwrap();
535-
}
570+
DefPathData::ClosureExpr => {
571+
let label = generator_kind_label(tcx.generator_kind(def_id));
572+
573+
push_disambiguated_special_name(
574+
label,
575+
disambiguated_data.disambiguator,
576+
cpp_like_debuginfo(tcx),
577+
output,
578+
);
536579
}
537580
_ => match disambiguated_data.data.name() {
538581
DefPathDataName::Named(name) => {
539582
output.push_str(name.as_str());
540583
}
541584
DefPathDataName::Anon { namespace } => {
542-
if cpp_like_debuginfo(tcx) {
543-
write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap();
544-
} else {
545-
write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator)
546-
.unwrap();
547-
}
585+
push_disambiguated_special_name(
586+
namespace.as_str(),
587+
disambiguated_data.disambiguator,
588+
cpp_like_debuginfo(tcx),
589+
output,
590+
);
548591
}
549592
},
550593
};
551594
}
552595

553-
// Pushes the generic parameters in the given `InternalSubsts` to the output string.
554-
// This ignores region parameters, since they can't reliably be
555-
// reconstructed for items from non-local crates. For local crates, this
556-
// would be possible but with inlining and LTO we have to use the least
557-
// common denominator - otherwise we would run into conflicts.
558596
fn push_generic_params_internal<'tcx>(
559597
tcx: TyCtxt<'tcx>,
560598
substs: SubstsRef<'tcx>,

‎src/test/codegen/async-fn-debug-msvc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async fn async_fn_test() {
1717
// FIXME: No way to reliably check the filename.
1818

1919
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
20-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "async_fn$0"
20+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "async_fn_env$0"
2121
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
2222
// For brevity, we only check the struct name and members of the last variant.
2323
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,

‎src/test/codegen/async-fn-debug.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async fn async_fn_test() {
1717
// FIXME: No way to reliably check the filename.
1818

1919
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
20-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn#0}", scope: [[ASYNC_FN]]
20+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[ASYNC_FN]]
2121
// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]],
2222
// CHECK-NOT: flags: DIFlagArtificial
2323
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]

‎src/test/codegen/debug-vtable.rs

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
1-
// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Ccodegen-units=1
2-
// ignore-tidy-linelength
3-
41
// This test checks the debuginfo for the expected 3 vtables is generated for correct names and number
52
// of entries.
63

7-
// NONMSVC-LABEL: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable}"
8-
// MSVC-LABEL: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable$"
4+
// Use the v0 symbol mangling scheme to codegen order independent of rustc version.
5+
// Unnamed items like shims are generated in lexicographical order of their symbol name and in the
6+
// legacy mangling scheme rustc version and generic parameters are both hashed into a single part
7+
// of the name, thus randomizing item order with respect to rustc version.
8+
9+
// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0
10+
// ignore-tidy-linelength
11+
12+
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable}"
13+
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable$"
914
// NONMSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()",
1015
// MSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$<tuple$<> >",
1116
// CHECK: !DISubrange(count: 5
1217

13-
// NONMSVC-LABEL: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable}"
14-
// MSVC-LABEL: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable$"
18+
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable}"
19+
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable$"
1520
// CHECK: !DISubrange(count: 4
1621

17-
// NONMSVC-LABEL: !DIGlobalVariable(name: "<debug_vtable::Foo as _>::{vtable}"
18-
// MSVC-LABEL: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, _>::vtable$"
22+
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as _>::{vtable}"
23+
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, _>::vtable$"
1924
// CHECK: !DISubrange(count: 3
2025

21-
// NONMSVC-LABEL: !DIGlobalVariable(name: "<debug_vtable::bar::{closure#0} as core::ops::function::FnOnce<(core::option::Option<&dyn core::ops::function::Fn<(), Output=()>>)>>::{vtable}"
22-
// MSVC-LABEL: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure$0, core::ops::function::FnOnce<tuple$<enum$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$"
26+
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::bar::{closure_env#0} as core::ops::function::FnOnce<(core::option::Option<&dyn core::ops::function::Fn<(), Output=()>>)>>::{vtable}"
27+
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure_env$0, core::ops::function::FnOnce<tuple$<enum$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$"
28+
29+
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::generic_closure::{closure_env#0}<bool> as core::ops::function::FnOnce<()>>::{vtable}"
30+
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::generic_closure::closure_env$0<bool>, core::ops::function::FnOnce<tuple$<> > >::vtable$
31+
32+
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::generic_closure::{closure_env#0}<u32> as core::ops::function::FnOnce<()>>::{vtable}"
33+
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::generic_closure::closure_env$0<u32>, core::ops::function::FnOnce<tuple$<> > >::vtable$
2334

2435
#![crate_type = "lib"]
2536

@@ -31,16 +42,22 @@ pub trait SomeTrait {
3142
}
3243

3344
impl SomeTrait for Foo {
34-
fn method1(&self) -> u32 { 1 }
35-
fn method2(&self) -> u32 { 2 }
45+
fn method1(&self) -> u32 {
46+
1
47+
}
48+
fn method2(&self) -> u32 {
49+
2
50+
}
3651
}
3752

3853
pub trait SomeTraitWithGenerics<T, U> {
3954
fn method1(&self) -> (T, U);
4055
}
4156

4257
impl SomeTraitWithGenerics<u64, i8> for Foo {
43-
fn method1(&self) -> (u64, i8) { (1, 2) }
58+
fn method1(&self) -> (u64, i8) {
59+
(1, 2)
60+
}
4461
}
4562

4663
pub fn foo(x: &Foo) -> (u32, (u64, i8), &dyn Send) {
@@ -55,3 +72,11 @@ pub fn foo(x: &Foo) -> (u32, (u64, i8), &dyn Send) {
5572
pub fn bar() -> Box<dyn FnOnce(Option<&dyn Fn()>)> {
5673
Box::new(|_x: Option<&dyn Fn()>| {})
5774
}
75+
76+
fn generic_closure<T: 'static>(x: T) -> Box<dyn FnOnce() -> T> {
77+
Box::new(move || x)
78+
}
79+
80+
pub fn instantiate_generic_closures() -> (Box<dyn FnOnce() -> u32>, Box<dyn FnOnce() -> bool>) {
81+
(generic_closure(1u32), generic_closure(false))
82+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// This test checks that we get proper type names for closure environments and
2+
// async-fn environments in debuginfo, especially making sure that generic arguments
3+
// of the enclosing functions don't get lost.
4+
//
5+
// Unfortunately, the order that debuginfo gets emitted into LLVM IR becomes a bit hard
6+
// to predict once async fns are involved.
7+
//
8+
// Note that the test does not check async-fns when targeting MSVC because debuginfo for
9+
// those does not follow the enum-fallback encoding yet and thus is incomplete.
10+
11+
// ignore-tidy-linelength
12+
13+
// Use the v0 symbol mangling scheme to codegen order independent of rustc version.
14+
// Unnamed items like shims are generated in lexicographical order of their symbol name and in the
15+
// legacy mangling scheme rustc version and generic parameters are both hashed into a single part
16+
// of the name, thus randomizing item order with respect to rustc version.
17+
18+
// compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0
19+
20+
21+
// CHECK: [[non_generic_closure_NAMESPACE:!.*]] = !DINamespace(name: "non_generic_closure"
22+
// CHECK: [[function_containing_closure_NAMESPACE:!.*]] = !DINamespace(name: "function_containing_closure"
23+
// CHECK: [[generic_async_function_NAMESPACE:!.*]] = !DINamespace(name: "generic_async_function"
24+
// CHECK: [[generic_async_block_NAMESPACE:!.*]] = !DINamespace(name: "generic_async_block"
25+
26+
// non_generic_closure()
27+
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[non_generic_closure_NAMESPACE]]
28+
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: [[non_generic_closure_NAMESPACE]]
29+
30+
// function_containing_closure<u32>()
31+
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: [[function_containing_closure_NAMESPACE]]
32+
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: [[function_containing_closure_NAMESPACE]]
33+
34+
// generic_async_function<Foo>()
35+
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[generic_async_function_NAMESPACE]]
36+
37+
// generic_async_function<u32>()
38+
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: [[generic_async_function_NAMESPACE]]
39+
40+
// generic_async_block<Foo>()
41+
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[generic_async_block_NAMESPACE]]
42+
43+
// generic_async_block<u32>()
44+
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: [[generic_async_block_NAMESPACE]]
45+
46+
// function_containing_closure<Foo>()
47+
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[function_containing_closure_NAMESPACE]]
48+
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: [[function_containing_closure_NAMESPACE]]
49+
50+
51+
#![crate_type = "lib"]
52+
use std::future::Future;
53+
54+
pub struct Foo;
55+
56+
pub fn non_generic_closure(x: Foo) -> Box<dyn FnOnce() -> Foo> {
57+
// This static only exists to trigger generating the namespace debuginfo for
58+
// `function_containing_closure` at a predictable, early point, which makes
59+
// writing the FileCheck tests above simpler.
60+
static _X: u8 = 0;
61+
return Box::new(move || x);
62+
}
63+
64+
fn function_containing_closure<T: 'static>(x: T) -> impl FnOnce() -> T {
65+
static _X: u8 = 0; // Same as above
66+
67+
return move || x;
68+
}
69+
70+
async fn generic_async_function<T: 'static>(x: T) -> T {
71+
static _X: u8 = 0; // Same as above
72+
x
73+
}
74+
75+
fn generic_async_block<T: 'static>(x: T) -> impl Future<Output=T> {
76+
static _X: u8 = 0; // Same as above
77+
async move {
78+
x
79+
}
80+
}
81+
82+
pub fn instantiate_generics() {
83+
let _closure_u32 = function_containing_closure(7u32);
84+
let _closure_foo = function_containing_closure(Foo);
85+
86+
let _async_fn_u32 = generic_async_function(42u32);
87+
let _async_fn_foo = generic_async_function(Foo);
88+
89+
let _async_block_u32 = generic_async_block(64u32);
90+
let _async_block_foo = generic_async_block(Foo);
91+
}

‎src/test/codegen/generator-debug-msvc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
2121
// FIXME: No way to reliably check the filename.
2222

2323
// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
24-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0"
24+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator_env$0"
2525
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
2626
// For brevity, we only check the struct name and members of the last variant.
2727
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,

‎src/test/codegen/generator-debug.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
2121
// FIXME: No way to reliably check the filename.
2222

2323
// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
24-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[GEN_FN]]
24+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator_env#0}", scope: [[GEN_FN]]
2525
// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]],
2626
// CHECK-NOT: flags: DIFlagArtificial
2727
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]

‎src/test/debuginfo/captured-fields-1.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,44 @@
44

55
// gdb-command:run
66
// gdb-command:print test
7-
// gdbr-check:$1 = captured_fields_1::main::{closure#0} {_ref__my_ref__my_field1: 0x[...]}
7+
// gdbr-check:$1 = captured_fields_1::main::{closure_env#0} {_ref__my_ref__my_field1: 0x[...]}
88
// gdb-command:continue
99
// gdb-command:print test
10-
// gdbr-check:$2 = captured_fields_1::main::{closure#1} {_ref__my_ref__my_field2: 0x[...]}
10+
// gdbr-check:$2 = captured_fields_1::main::{closure_env#1} {_ref__my_ref__my_field2: 0x[...]}
1111
// gdb-command:continue
1212
// gdb-command:print test
13-
// gdbr-check:$3 = captured_fields_1::main::{closure#2} {_ref__my_ref: 0x[...]}
13+
// gdbr-check:$3 = captured_fields_1::main::{closure_env#2} {_ref__my_ref: 0x[...]}
1414
// gdb-command:continue
1515
// gdb-command:print test
16-
// gdbr-check:$4 = captured_fields_1::main::{closure#3} {my_ref: 0x[...]}
16+
// gdbr-check:$4 = captured_fields_1::main::{closure_env#3} {my_ref: 0x[...]}
1717
// gdb-command:continue
1818
// gdb-command:print test
19-
// gdbr-check:$5 = captured_fields_1::main::{closure#4} {my_var__my_field2: 22}
19+
// gdbr-check:$5 = captured_fields_1::main::{closure_env#4} {my_var__my_field2: 22}
2020
// gdb-command:continue
2121
// gdb-command:print test
22-
// gdbr-check:$6 = captured_fields_1::main::{closure#5} {my_var: captured_fields_1::MyStruct {my_field1: 11, my_field2: 22}}
22+
// gdbr-check:$6 = captured_fields_1::main::{closure_env#5} {my_var: captured_fields_1::MyStruct {my_field1: 11, my_field2: 22}}
2323
// gdb-command:continue
2424

2525
// === LLDB TESTS ==================================================================================
2626

2727
// lldb-command:run
2828
// lldb-command:print test
29-
// lldbg-check:(captured_fields_1::main::{closure#0}) $0 = { _ref__my_ref__my_field1 = 0x[...] }
29+
// lldbg-check:(captured_fields_1::main::{closure_env#0}) $0 = { _ref__my_ref__my_field1 = 0x[...] }
3030
// lldb-command:continue
3131
// lldb-command:print test
32-
// lldbg-check:(captured_fields_1::main::{closure#1}) $1 = { _ref__my_ref__my_field2 = 0x[...] }
32+
// lldbg-check:(captured_fields_1::main::{closure_env#1}) $1 = { _ref__my_ref__my_field2 = 0x[...] }
3333
// lldb-command:continue
3434
// lldb-command:print test
35-
// lldbg-check:(captured_fields_1::main::{closure#2}) $2 = { _ref__my_ref = 0x[...] }
35+
// lldbg-check:(captured_fields_1::main::{closure_env#2}) $2 = { _ref__my_ref = 0x[...] }
3636
// lldb-command:continue
3737
// lldb-command:print test
38-
// lldbg-check:(captured_fields_1::main::{closure#3}) $3 = { my_ref = 0x[...] }
38+
// lldbg-check:(captured_fields_1::main::{closure_env#3}) $3 = { my_ref = 0x[...] }
3939
// lldb-command:continue
4040
// lldb-command:print test
41-
// lldbg-check:(captured_fields_1::main::{closure#4}) $4 = { my_var__my_field2 = 22 }
41+
// lldbg-check:(captured_fields_1::main::{closure_env#4}) $4 = { my_var__my_field2 = 22 }
4242
// lldb-command:continue
4343
// lldb-command:print test
44-
// lldbg-check:(captured_fields_1::main::{closure#5}) $5 = { my_var = { my_field1 = 11 my_field2 = 22 } }
44+
// lldbg-check:(captured_fields_1::main::{closure_env#5}) $5 = { my_var = { my_field1 = 11 my_field2 = 22 } }
4545
// lldb-command:continue
4646

4747
#![feature(capture_disjoint_fields)]
@@ -53,10 +53,7 @@ struct MyStruct {
5353
}
5454

5555
fn main() {
56-
let mut my_var = MyStruct {
57-
my_field1: 11,
58-
my_field2: 22,
59-
};
56+
let mut my_var = MyStruct { my_field1: 11, my_field2: 22 };
6057
let my_ref = &mut my_var;
6158

6259
let test = || {

‎src/test/debuginfo/function-names.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727

2828
// Closure
2929
// gdb-command:info functions -q function_names::.*::{closure.*
30-
// gdb-check:[...]static fn function_names::generic_func::{closure#0}<i32>(*mut function_names::generic_func::{closure#0});
31-
// gdb-check:[...]static fn function_names::main::{closure#0}(*mut function_names::main::{closure#0});
32-
// gdb-check:[...]static fn function_names::{impl#2}::impl_function::{closure#0}<i32, i32>(*mut function_names::{impl#2}::impl_function::{closure#0});
30+
// gdb-check:[...]static fn function_names::generic_func::{closure#0}<i32>(*mut function_names::generic_func::{closure_env#0}<i32>);
31+
// gdb-check:[...]static fn function_names::main::{closure#0}(*mut function_names::main::{closure_env#0});
32+
// gdb-check:[...]static fn function_names::{impl#2}::impl_function::{closure#0}<i32, i32>(*mut function_names::{impl#2}::impl_function::{closure_env#0}<i32, i32>);
3333

3434
// Generator
3535
// Generators don't seem to appear in GDB's symbol table.
@@ -86,9 +86,9 @@
8686
#![feature(adt_const_params, generators, generator_trait)]
8787
#![allow(incomplete_features)]
8888

89-
use Mod1::TestTrait2;
9089
use std::ops::Generator;
9190
use std::pin::Pin;
91+
use Mod1::TestTrait2;
9292

9393
fn main() {
9494
// Implementations
@@ -107,16 +107,19 @@ fn main() {
107107
let _ = generic_func(42i32);
108108

109109
// Closure
110-
let closure = || { TestStruct1 };
110+
let closure = || TestStruct1;
111111
closure();
112112

113113
// Generator
114-
let mut generator = || { yield; return; };
114+
let mut generator = || {
115+
yield;
116+
return;
117+
};
115118
Pin::new(&mut generator).resume(());
116119

117120
// Const generic functions
118121
const_generic_fn_bool::<false>();
119-
const_generic_fn_non_int::<{()}>();
122+
const_generic_fn_non_int::<{ () }>();
120123
const_generic_fn_signed_int::<-7>();
121124
const_generic_fn_unsigned_int::<14>();
122125
}
@@ -158,7 +161,7 @@ struct GenericStruct<T1, T2>(std::marker::PhantomData<(T1, T2)>);
158161
impl<T1, T2> GenericStruct<T1, T2> {
159162
pub fn impl_function() {
160163
// Closure in a generic implementation
161-
let closure = || { TestStruct1 };
164+
let closure = || TestStruct1;
162165
closure();
163166
}
164167
}
@@ -190,7 +193,7 @@ impl<T, const N: usize> TestTrait1 for GenericStruct<[T; N], f32> {
190193
// Generic function
191194
fn generic_func<T>(value: T) -> T {
192195
// Closure in a generic function
193-
let closure = || { TestStruct1 };
196+
let closure = || TestStruct1;
194197
closure();
195198

196199
value

‎src/test/debuginfo/generator-objects.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,31 @@
1111

1212
// gdb-command:run
1313
// gdb-command:print b
14-
// gdb-check:$1 = generator_objects::main::{generator#0}::Unresumed{_ref__a: 0x[...]}
14+
// gdb-check:$1 = generator_objects::main::{generator_env#0}::Unresumed{_ref__a: 0x[...]}
1515
// gdb-command:continue
1616
// gdb-command:print b
17-
// gdb-check:$2 = generator_objects::main::{generator#0}::Suspend0{c: 6, d: 7, _ref__a: 0x[...]}
17+
// gdb-check:$2 = generator_objects::main::{generator_env#0}::Suspend0{c: 6, d: 7, _ref__a: 0x[...]}
1818
// gdb-command:continue
1919
// gdb-command:print b
20-
// gdb-check:$3 = generator_objects::main::{generator#0}::Suspend1{c: 7, d: 8, _ref__a: 0x[...]}
20+
// gdb-check:$3 = generator_objects::main::{generator_env#0}::Suspend1{c: 7, d: 8, _ref__a: 0x[...]}
2121
// gdb-command:continue
2222
// gdb-command:print b
23-
// gdb-check:$4 = generator_objects::main::{generator#0}::Returned{_ref__a: 0x[...]}
23+
// gdb-check:$4 = generator_objects::main::{generator_env#0}::Returned{_ref__a: 0x[...]}
2424

2525
// === LLDB TESTS ==================================================================================
2626

2727
// lldb-command:run
2828
// lldb-command:print b
29-
// lldbg-check:(generator_objects::main::{generator#0}) $0 =
29+
// lldbg-check:(generator_objects::main::{generator_env#0}) $0 =
3030
// lldb-command:continue
3131
// lldb-command:print b
32-
// lldbg-check:(generator_objects::main::{generator#0}) $1 =
32+
// lldbg-check:(generator_objects::main::{generator_env#0}) $1 =
3333
// lldb-command:continue
3434
// lldb-command:print b
35-
// lldbg-check:(generator_objects::main::{generator#0}) $2 =
35+
// lldbg-check:(generator_objects::main::{generator_env#0}) $2 =
3636
// lldb-command:continue
3737
// lldb-command:print b
38-
// lldbg-check:(generator_objects::main::{generator#0}) $3 =
38+
// lldbg-check:(generator_objects::main::{generator_env#0}) $3 =
3939

4040
#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
4141
#![omit_gdb_pretty_printer_section]
@@ -66,4 +66,6 @@ fn main() {
6666
_zzz(); // #break
6767
}
6868

69-
fn _zzz() {()}
69+
fn _zzz() {
70+
()
71+
}

‎src/test/debuginfo/issue-57822.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@
1111
// gdb-command:run
1212

1313
// gdb-command:print g
14-
// gdb-check:$1 = issue_57822::main::{closure#1} {f: issue_57822::main::{closure#0} {x: 1}}
14+
// gdb-check:$1 = issue_57822::main::{closure_env#1} {f: issue_57822::main::{closure_env#0} {x: 1}}
1515

1616
// gdb-command:print b
17-
// gdb-check:$2 = issue_57822::main::{generator#3}::Unresumed{a: issue_57822::main::{generator#2}::Unresumed{y: 2}}
17+
// gdb-check:$2 = issue_57822::main::{generator_env#3}::Unresumed{a: issue_57822::main::{generator_env#2}::Unresumed{y: 2}}
1818

1919
// === LLDB TESTS ==================================================================================
2020

2121
// lldb-command:run
2222

2323
// lldb-command:print g
24-
// lldbg-check:(issue_57822::main::{closure#1}) $0 = { f = { x = 1 } }
24+
// lldbg-check:(issue_57822::main::{closure_env#1}) $0 = { f = { x = 1 } }
2525

2626
// lldb-command:print b
27-
// lldbg-check:(issue_57822::main::{generator#3}) $1 =
27+
// lldbg-check:(issue_57822::main::{generator_env#3}) $1 =
2828

2929
#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
3030
#![omit_gdb_pretty_printer_section]
@@ -50,4 +50,6 @@ fn main() {
5050
zzz(); // #break
5151
}
5252

53-
fn zzz() { () }
53+
fn zzz() {
54+
()
55+
}

‎src/test/debuginfo/type-names.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@
122122
// gdb-command:whatis has_associated_type_trait
123123
// gdb-check:type = &(dyn type_names::Trait3<u32, AssocType=isize> + core::marker::Send)
124124

125-
126125
// BARE FUNCTIONS
127126
// gdb-command:whatis rust_fn
128127
// gdb-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
@@ -153,10 +152,10 @@
153152

154153
// CLOSURES
155154
// gdb-command:whatis closure1
156-
// gdb-check:type = (type_names::main::{closure#0}, usize)
155+
// gdb-check:type = (type_names::main::{closure_env#0}, usize)
157156

158157
// gdb-command:whatis closure2
159-
// gdb-check:type = (type_names::main::{closure#1}, usize)
158+
// gdb-check:type = (type_names::main::{closure_env#1}, usize)
160159

161160
// FOREIGN TYPES
162161
// gdb-command:whatis foreign1
@@ -254,8 +253,8 @@
254253

255254
// CLOSURES
256255
// cdb-command:dv /t closure*
257-
// cdb-check:struct tuple$<type_names::main::closure$1,usize> closure2 = [...]
258-
// cdb-check:struct tuple$<type_names::main::closure$0,usize> closure1 = [...]
256+
// cdb-check:struct tuple$<type_names::main::closure_env$1,usize> closure2 = [...]
257+
// cdb-check:struct tuple$<type_names::main::closure_env$0,usize> closure1 = [...]
259258

260259
// FOREIGN TYPES
261260
// cdb-command:dv /t foreign*
@@ -279,7 +278,9 @@ enum Enum1 {
279278
Variant2(isize),
280279
}
281280

282-
extern { type ForeignType1; }
281+
extern "C" {
282+
type ForeignType1;
283+
}
283284

284285
mod mod1 {
285286
pub use self::Enum2::{Variant1, Variant2};
@@ -300,7 +301,9 @@ mod mod1 {
300301
}
301302
}
302303

303-
extern { pub type ForeignType2; }
304+
extern "C" {
305+
pub type ForeignType2;
306+
}
304307
}
305308

306309
trait Trait1 {
@@ -311,7 +314,9 @@ trait Trait2<T1, T2> {
311314
}
312315
trait Trait3<T> {
313316
type AssocType;
314-
fn dummy(&self) -> T { panic!() }
317+
fn dummy(&self) -> T {
318+
panic!()
319+
}
315320
}
316321

317322
impl Trait1 for isize {}
@@ -441,8 +446,8 @@ fn main() {
441446
let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize);
442447

443448
// Foreign Types
444-
let foreign1 = unsafe{ 0 as *const ForeignType1 };
445-
let foreign2 = unsafe{ 0 as *const mod1::ForeignType2 };
449+
let foreign1 = unsafe { 0 as *const ForeignType1 };
450+
let foreign2 = unsafe { 0 as *const mod1::ForeignType2 };
446451

447452
zzz(); // #break
448453
}

‎src/test/debuginfo/var-captured-in-nested-closure.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
// cdb-command: dx closure_local
109109
// cdb-check:closure_local : 8 [Type: [...]]
110110
// cdb-command: dx nested_closure
111-
// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::closure$0::closure$0]
111+
// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::closure$0::closure_env$0]
112112

113113
// cdb-command: g
114114

0 commit comments

Comments
 (0)
Please sign in to comment.