Skip to content

Commit f818167

Browse files
authored
Rollup merge of rust-lang#85292 - wesleywiser:enum_debuginfo, r=michaelwoerister
Improve debugging experience for enums on windows-msvc This PR makes significant improvements over the status quo of debugging enums on the windows-msvc platform with either WinDbg or Visual Studio in three ways: 1. Improves the debugger experience for directly tagged enums. 2. Fixes a bug which caused the debugger to sometimes show the wrong debug info for niche layout enums. For example, `Option<&u32>` could sometimes use the debug info for `Option<&f64>` instead leading to nonsensical variable values in the debugger. 3. Significantly improves the debugger experience for niche-layout enums. Let's look at a few examples: ```rust pub enum CStyleEnum { Base = 2, Exponent = 16, } pub enum NicheLayoutEnum { Tag1, Data { my_data: CStyleEnum }, Tag2, Tag3, Tag4, } pub enum OtherEnum<T> { Case1(T), Case2(T), } fn main() { let a = Some(CStyleEnum::Base); let b = Option::<CStyleEnum>::None; let c = NicheLayoutEnum::Tag1; let d = NicheLayoutEnum::Data { my_data: CStyleEnum::Exponent }; let e = NicheLayoutEnum::Tag2; let f = Some(&1u32); let g = Option::<&'static u32>::None; let h = Some(&2u64); let i = Option::<&'static u64>::None; let j = Some(12u32); let k = Option::<u32>::None; let l = Some(12.34f64); let m = Option::<f64>::None; let n = CStyleEnum::Base; let o = CStyleEnum::Exponent; let p = Some("IAMA optional string!".to_string()); let q = OtherEnum::Case1(42u32); } ``` This is what WinDbg Preview shows using the latest rustc nightly: ![image](https://user-images.githubusercontent.com/831192/118285353-57c10780-b49f-11eb-97aa-db3abfc09508.png) Most of the variables don't show a meaningful value expect for a few cases that we have targeted natvis definitions covering. Even worse, drilling into many of these variables shows information that can be difficult to interpret without an understanding of the layout of Rust types: ![image](https://user-images.githubusercontent.com/831192/118285609-a1a9ed80-b49f-11eb-9c29-b14576984647.png) With the changes in this PR, we're able to write two natvis definitions that cover all enum cases generally. After building with these changes, WinDbg now shows this instead: ![image](https://user-images.githubusercontent.com/831192/118287730-be472500-b4a1-11eb-8cad-8f6a91c7516b.png) Drilling into the same variables, we can see much more useful information: ![image](https://user-images.githubusercontent.com/831192/118287888-e20a6b00-b4a1-11eb-927f-32cf33a31c16.png) Fixes rust-lang#84670 Fixes rust-lang#84671
2 parents 66eaa42 + 94c45ef commit f818167

File tree

9 files changed

+376
-142
lines changed

9 files changed

+376
-142
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+149-102
Large diffs are not rendered by default.

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,7 @@ extern "C" {
20382038

20392039
pub fn LLVMRustDIBuilderCreateUnionType(
20402040
Builder: &DIBuilder<'a>,
2041-
Scope: &'a DIScope,
2041+
Scope: Option<&'a DIScope>,
20422042
Name: *const c_char,
20432043
NameLen: size_t,
20442044
File: &'a DIFile,

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+56-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_hir as hir;
55
use rustc_hir::def_id::DefId;
6-
use rustc_middle::ty::{self, subst::SubstsRef, Ty, TyCtxt};
6+
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt};
7+
use rustc_target::abi::{TagEncoding, Variants};
78

89
use std::fmt::Write;
910

@@ -45,8 +46,12 @@ pub fn push_debuginfo_type_name<'tcx>(
4546
ty::Float(float_ty) => output.push_str(float_ty.name_str()),
4647
ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
4748
ty::Adt(def, substs) => {
48-
push_item_name(tcx, def.did, qualified, output);
49-
push_type_params(tcx, substs, output, visited);
49+
if def.is_enum() && cpp_like_names {
50+
msvc_enum_fallback(tcx, t, def, substs, output, visited);
51+
} else {
52+
push_item_name(tcx, def.did, qualified, output);
53+
push_type_params(tcx, substs, output, visited);
54+
}
5055
}
5156
ty::Tuple(component_types) => {
5257
if cpp_like_names {
@@ -233,6 +238,54 @@ pub fn push_debuginfo_type_name<'tcx>(
233238
}
234239
}
235240

241+
/// MSVC names enums differently than other platforms so that the debugging visualization
242+
// format (natvis) is able to understand enums and render the active variant correctly in the
243+
// debugger. For more information, look in `src/etc/natvis/intrinsic.natvis` and
244+
// `EnumMemberDescriptionFactor::create_member_descriptions`.
245+
fn msvc_enum_fallback(
246+
tcx: TyCtxt<'tcx>,
247+
ty: Ty<'tcx>,
248+
def: &AdtDef,
249+
substs: SubstsRef<'tcx>,
250+
output: &mut String,
251+
visited: &mut FxHashSet<Ty<'tcx>>,
252+
) {
253+
let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error");
254+
255+
if let Variants::Multiple {
256+
tag_encoding: TagEncoding::Niche { dataful_variant, .. },
257+
tag,
258+
variants,
259+
..
260+
} = &layout.variants
261+
{
262+
let dataful_variant_layout = &variants[*dataful_variant];
263+
264+
// calculate the range of values for the dataful variant
265+
let dataful_discriminant_range =
266+
&dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
267+
268+
let min = dataful_discriminant_range.start();
269+
let min = tag.value.size(&tcx).truncate(*min);
270+
271+
let max = dataful_discriminant_range.end();
272+
let max = tag.value.size(&tcx).truncate(*max);
273+
274+
output.push_str("enum$<");
275+
push_item_name(tcx, def.did, true, output);
276+
push_type_params(tcx, substs, output, visited);
277+
278+
let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
279+
280+
output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name));
281+
} else {
282+
output.push_str("enum$<");
283+
push_item_name(tcx, def.did, true, output);
284+
push_type_params(tcx, substs, output, visited);
285+
output.push('>');
286+
}
287+
}
288+
236289
fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
237290
if qualified {
238291
output.push_str(&tcx.crate_name(def_id.krate).as_str());

src/etc/natvis/intrinsic.natvis

+53
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,57 @@
149149
<Synthetic Name="[...]"><DisplayString>...</DisplayString></Synthetic>
150150
</Expand>
151151
</Type>
152+
<Type Name="enum$&lt;*&gt;">
153+
<Intrinsic Name="tag" Expression="variant0.variant$" />
154+
<DisplayString Condition="tag() == 0">{tag(),en}</DisplayString>
155+
<DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString>
156+
<DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString>
157+
<DisplayString Condition="tag() == 3" Optional="true">{tag(),en}</DisplayString>
158+
<DisplayString Condition="tag() == 4" Optional="true">{tag(),en}</DisplayString>
159+
<DisplayString Condition="tag() == 5" Optional="true">{tag(),en}</DisplayString>
160+
<DisplayString Condition="tag() == 6" Optional="true">{tag(),en}</DisplayString>
161+
<DisplayString Condition="tag() == 7" Optional="true">{tag(),en}</DisplayString>
162+
<DisplayString Condition="tag() == 8" Optional="true">{tag(),en}</DisplayString>
163+
<DisplayString Condition="tag() == 9" Optional="true">{tag(),en}</DisplayString>
164+
<DisplayString Condition="tag() == 10" Optional="true">{tag(),en}</DisplayString>
165+
<DisplayString Condition="tag() == 11" Optional="true">{tag(),en}</DisplayString>
166+
<DisplayString Condition="tag() == 12" Optional="true">{tag(),en}</DisplayString>
167+
<DisplayString Condition="tag() == 13" Optional="true">{tag(),en}</DisplayString>
168+
<DisplayString Condition="tag() == 14" Optional="true">{tag(),en}</DisplayString>
169+
<DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString>
170+
171+
<Expand>
172+
<ExpandedItem Condition="tag() == 0">variant0</ExpandedItem>
173+
<ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem>
174+
<ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem>
175+
<ExpandedItem Condition="tag() == 3" Optional="true">variant3</ExpandedItem>
176+
<ExpandedItem Condition="tag() == 4" Optional="true">variant4</ExpandedItem>
177+
<ExpandedItem Condition="tag() == 5" Optional="true">variant5</ExpandedItem>
178+
<ExpandedItem Condition="tag() == 6" Optional="true">variant6</ExpandedItem>
179+
<ExpandedItem Condition="tag() == 7" Optional="true">variant7</ExpandedItem>
180+
<ExpandedItem Condition="tag() == 8" Optional="true">variant8</ExpandedItem>
181+
<ExpandedItem Condition="tag() == 9" Optional="true">variant9</ExpandedItem>
182+
<ExpandedItem Condition="tag() == 10" Optional="true">variant10</ExpandedItem>
183+
<ExpandedItem Condition="tag() == 11" Optional="true">variant11</ExpandedItem>
184+
<ExpandedItem Condition="tag() == 12" Optional="true">variant12</ExpandedItem>
185+
<ExpandedItem Condition="tag() == 13" Optional="true">variant13</ExpandedItem>
186+
<ExpandedItem Condition="tag() == 14" Optional="true">variant14</ExpandedItem>
187+
<ExpandedItem Condition="tag() == 15" Optional="true">variant15</ExpandedItem>
188+
</Expand>
189+
</Type>
190+
191+
<!-- $T1 is the name of the enum, $T2 is the low value of the dataful variant tag,
192+
$T3 is the high value of the dataful variant tag, $T4 is the name of the dataful variant -->
193+
<Type Name="enum$&lt;*, *, *, *&gt;">
194+
<Intrinsic Name="tag" Expression="discriminant" />
195+
<Intrinsic Name="is_dataful" Expression="tag() &gt;= $T2 &amp;&amp; tag() &lt;= $T3" />
196+
<DisplayString Condition="is_dataful()">{"$T4",sb}({dataful_variant})</DisplayString>
197+
<DisplayString Condition="!is_dataful()">{discriminant,en}</DisplayString>
198+
<Expand>
199+
<ExpandedItem Condition="is_dataful()">dataful_variant</ExpandedItem>
200+
<Synthetic Condition="is_dataful()" Name="[variant]">
201+
<DisplayString>{"$T4",sb}</DisplayString>
202+
</Synthetic>
203+
</Expand>
204+
</Type>
152205
</AutoVisualizer>

src/etc/natvis/libcore.natvis

-17
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@
1414
</Expand>
1515
</Type>
1616

17-
<Type Name="core::option::Option&lt;*&gt;">
18-
<DisplayString Condition="RUST$ENUM$DISR == 0x0">None</DisplayString>
19-
<DisplayString Condition="RUST$ENUM$DISR == 0x1">Some({__0})</DisplayString>
20-
<Expand>
21-
<Item Name="[value]" ExcludeView="simple" Condition="RUST$ENUM$DISR == 1">__0</Item>
22-
</Expand>
23-
</Type>
24-
2517
<Type Name="core::option::Option&lt;*&gt;" Priority="MediumLow">
2618
<DisplayString Condition="*(void**)this == nullptr">None</DisplayString>
2719
<DisplayString>Some({($T1 *)this})</DisplayString>
@@ -30,15 +22,6 @@
3022
</Expand>
3123
</Type>
3224

33-
<Type Name="core::result::Result&lt;*&gt;">
34-
<DisplayString Condition="RUST$ENUM$DISR == 0x0">Ok({__0})</DisplayString>
35-
<DisplayString Condition="RUST$ENUM$DISR == 0x1">Err({(*($T2*) &amp;__0)})</DisplayString>
36-
<Expand>
37-
<Item Name="[value]" Condition="RUST$ENUM$DISR == 0x0">__0</Item>
38-
<Item Name="[value]" Condition="RUST$ENUM$DISR == 0x1">(*($T2*) &amp;__0)</Item>
39-
</Expand>
40-
</Type>
41-
4225
<Type Name="core::ptr::non_null::NonNull&lt;*&gt;">
4326
<DisplayString>{(void*) pointer}</DisplayString>
4427
<Expand>

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,33 @@ 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: "generator-0", scope: [[ASYNC_FN]]
21-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
20+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
21+
// 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,
2424
// CHECK-NOT: flags: DIFlagArtificial
2525
// CHECK-SAME: )
26-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
26+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]],
2727
// CHECK-SAME: file: [[FILE]], line: 15,
2828
// CHECK-NOT: flags: DIFlagArtificial
2929
// CHECK-SAME: )
30-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
30+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]],
3131
// CHECK-SAME: file: [[FILE]], line: 15,
3232
// CHECK-NOT: flags: DIFlagArtificial
3333
// CHECK-SAME: )
34-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
34+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]],
3535
// CHECK-SAME: file: [[FILE]], line: 12,
3636
// CHECK-NOT: flags: DIFlagArtificial
3737
// CHECK-SAME: )
38-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
38+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
3939
// CHECK-SAME: file: [[FILE]], line: 14,
4040
// CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
4141
// CHECK-NOT: flags: DIFlagArtificial
4242
// CHECK-SAME: )
43-
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]],
43+
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
4444
// CHECK-NOT: flags: DIFlagArtificial
4545
// CHECK-SAME: )
46-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]],
46+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
4747
// CHECK-SAME: flags: DIFlagArtificial
4848
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
4949
// CHECK-NOT: flags: DIFlagArtificial

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,33 @@ 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", scope: [[GEN_FN]]
25-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
24+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
25+
// 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,
2828
// CHECK-NOT: flags: DIFlagArtificial
2929
// CHECK-SAME: )
30-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
30+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]],
3131
// CHECK-SAME: file: [[FILE]], line: 18,
3232
// CHECK-NOT: flags: DIFlagArtificial
3333
// CHECK-SAME: )
34-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
34+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]],
3535
// CHECK-SAME: file: [[FILE]], line: 18,
3636
// CHECK-NOT: flags: DIFlagArtificial
3737
// CHECK-SAME: )
38-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
38+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]],
3939
// CHECK-SAME: file: [[FILE]], line: 15,
4040
// CHECK-NOT: flags: DIFlagArtificial
4141
// CHECK-SAME: )
42-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
42+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
4343
// CHECK-SAME: file: [[FILE]], line: 17,
4444
// CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
4545
// CHECK-NOT: flags: DIFlagArtificial
4646
// CHECK-SAME: )
47-
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN_FN]],
47+
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
4848
// CHECK-NOT: flags: DIFlagArtificial
4949
// CHECK-SAME: )
50-
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]],
50+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
5151
// CHECK-SAME: flags: DIFlagArtificial
5252
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
5353
// CHECK-NOT: flags: DIFlagArtificial
+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// only-cdb
2+
// ignore-tidy-linelength
3+
// compile-flags:-g
4+
5+
// cdb-command: g
6+
7+
// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb
8+
// so the best we can do is to make sure we are generating the right debuginfo
9+
10+
// cdb-command: dx -r2 a,!
11+
// cdb-check:a,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
12+
// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
13+
// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
14+
// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
15+
16+
// cdb-command: dx -r2 b,!
17+
// cdb-check:b,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
18+
// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
19+
// cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
20+
// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
21+
22+
// cdb-command: dx -r2 c,!
23+
// cdb-check:c,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
24+
// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
25+
// cdb-check: [+0x000] my_data : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
26+
// cdb-check: [+0x000] discriminant : Tag1 (0x11) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
27+
28+
// cdb-command: dx -r2 d,!
29+
// cdb-check:d,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
30+
// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
31+
// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
32+
// cdb-check: [+0x000] discriminant : 0x10 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
33+
34+
// cdb-command: dx -r2 e,!
35+
// cdb-check:e,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
36+
// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
37+
// cdb-check: [+0x000] my_data : 0x13 [Type: msvc_pretty_enums::CStyleEnum]
38+
// cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
39+
40+
// cdb-command: dx -r2 f,!
41+
// cdb-check:f,! [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
42+
// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
43+
// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *]
44+
// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
45+
46+
// cdb-command: dx -r2 g,!
47+
// cdb-check:g,! [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
48+
// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
49+
// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *]
50+
// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
51+
52+
// cdb-command: dx h
53+
// cdb-check:h : Some [Type: enum$<core::option::Option<u32>>]
54+
// cdb-check: [+0x000] variant$ : Some (0x1) [Type: core::option::Option]
55+
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
56+
57+
// cdb-command: dx i
58+
// cdb-check:i : None [Type: enum$<core::option::Option<u32>>]
59+
// cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option]
60+
61+
// cdb-command: dx j
62+
// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
63+
64+
// cdb-command: dx -r2 k,!
65+
// cdb-check:k,! [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
66+
// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Some]
67+
// cdb-check: [+0x000] __0 [Type: alloc::string::String]
68+
// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$]
69+
70+
pub enum CStyleEnum {
71+
Low = 2,
72+
High = 16,
73+
}
74+
75+
pub enum NicheLayoutEnum {
76+
Tag1,
77+
Data { my_data: CStyleEnum },
78+
Tag2,
79+
}
80+
81+
fn main() {
82+
let a = Some(CStyleEnum::Low);
83+
let b = Option::<CStyleEnum>::None;
84+
let c = NicheLayoutEnum::Tag1;
85+
let d = NicheLayoutEnum::Data { my_data: CStyleEnum::High };
86+
let e = NicheLayoutEnum::Tag2;
87+
let f = Some(&1u32);
88+
let g = Option::<&'static u32>::None;
89+
let h = Some(12u32);
90+
let i = Option::<u32>::None;
91+
let j = CStyleEnum::High;
92+
let k = Some("IAMA optional string!".to_string());
93+
94+
zzz(); // #break
95+
}
96+
97+
fn zzz() { () }

src/test/debuginfo/pretty-std.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// ignore-freebsd: gdb package too new
22
// only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155
33
// ignore-android: FIXME(#10381)
4+
// ignore-tidy-linelength
45
// compile-flags:-g
56
// min-gdb-version: 7.7
67
// min-lldb-version: 310
@@ -111,11 +112,11 @@
111112
// NOTE: OsString doesn't have a .natvis entry yet.
112113

113114
// cdb-command: dx some
114-
// cdb-check:some : Some(8) [Type: [...]::Option<i16>]
115+
// cdb-check:some : Some [Type: enum$<core::option::Option<i16>>]
115116
// cdb-command: dx none
116-
// cdb-check:none : None [Type: [...]::Option<i64>]
117+
// cdb-check:none : None [Type: enum$<core::option::Option<i64>>]
117118
// cdb-command: dx some_string
118-
// cdb-check:some_string : Some("IAMA optional string!") [[...]::Option<[...]::String>]
119+
// cdb-check:some_string [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
119120

120121
#![allow(unused_variables)]
121122
use std::ffi::OsString;

0 commit comments

Comments
 (0)