Rollup merge of #145218 - nilptr:nilptr/feat/lldb-enum-pretty-printer, r=Mark-Simulacrum

[Debuginfo] improve enum value formatting in LLDB for better readability

> TL;DR: When debugging with CodeLLDB, I noticed enum values were often hard to read because LLDB lists every possible variant, resulting in a verbose and cluttered view, even though only one variant is actually valid. Interestingly, raw enum types display nicely. After some investigation, I found that `&enum` values get classified as `Other`, so it falls back to `DefaultSyntheticProvider`, which causes this verbose output.

## What does this PR do?

This PR contains 2 commits:

1. change the enum value formatting from showing 2 separate fields (`value` for attached data and `$discr$` for the discriminator) to a concise `<readable variant name>: <attached data>` format
2. dereference pointer types in `classify_rust_type` so that it can return more accurate type for reference type

## Self-test proof

Before:

<img width="1706" height="799" alt="before" src="https://github.com/user-attachments/assets/b66c7e22-990a-4da5-9036-34e3f9f62367" />

After:

<img width="1541" height="678" alt="after" src="https://github.com/user-attachments/assets/36db32e2-f822-4883-8f17-cb8067e509f6" />
This commit is contained in:
Jacob Pratt 2025-08-22 22:00:49 -04:00 committed by GitHub
commit 5cfdbd6c08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 23 additions and 21 deletions

View file

@ -10,6 +10,9 @@ def is_hashbrown_hashmap(hash_map: lldb.SBValue) -> bool:
def classify_rust_type(type: lldb.SBType) -> str:
if type.IsPointerType():
type = type.GetPointeeType()
type_class = type.GetTypeClass()
if type_class == lldb.eTypeClassStruct:
return classify_struct(type.name, type.fields)

View file

@ -1,4 +1,5 @@
from __future__ import annotations
import re
import sys
from typing import List, TYPE_CHECKING
@ -410,6 +411,16 @@ class MSVCStrSyntheticProvider:
return "&str"
def _getVariantName(variant) -> str:
"""
Since the enum variant's type name is in the form `TheEnumName::TheVariantName$Variant`,
we can extract `TheVariantName` from it for display purpose.
"""
s = variant.GetType().GetName()
match = re.search(r"::([^:]+)\$Variant$", s)
return match.group(1) if match else ""
class ClangEncodedEnumProvider:
"""Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
@ -424,37 +435,25 @@ class ClangEncodedEnumProvider:
return True
def num_children(self) -> int:
if self.is_default:
return 1
return 2
return 1
def get_child_index(self, name: str) -> int:
if name == ClangEncodedEnumProvider.VALUE_MEMBER_NAME:
return 0
if name == ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME:
return 1
def get_child_index(self, _name: str) -> int:
return -1
def get_child_at_index(self, index: int) -> SBValue:
if index == 0:
return self.variant.GetChildMemberWithName(
value = self.variant.GetChildMemberWithName(
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
)
if index == 1:
return self.variant.GetChildMemberWithName(
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
return value.CreateChildAtOffset(
_getVariantName(self.variant), 0, value.GetType()
)
return None
def update(self):
all_variants = self.valobj.GetChildAtIndex(0)
index = self._getCurrentVariantIndex(all_variants)
self.variant = all_variants.GetChildAtIndex(index)
self.is_default = (
self.variant.GetIndexOfChildWithName(
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
)
== -1
)
def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:
default_index = 0

View file

@ -22,11 +22,11 @@
// lldb-command:run
// lldb-command:v *the_a_ref
// lldb-check:(borrowed_enum::ABC) *the_a_ref = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 }
// lldb-check:(borrowed_enum::ABC) *the_a_ref = { TheA = { x = 0 y = 8970181431921507452 } }
// lldb-command:v *the_b_ref
// lldb-check:(borrowed_enum::ABC) *the_b_ref = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 }
// lldb-check:(borrowed_enum::ABC) *the_b_ref = { TheB = { 0 = 0 1 = 286331153 2 = 286331153 } }
// lldb-command:v *univariant_ref
// lldb-check:(borrowed_enum::Univariant) *univariant_ref = { value = { 0 = 4820353753753434 } }
// lldb-check:(borrowed_enum::Univariant) *univariant_ref = { TheOnlyCase = { 0 = 4820353753753434 } }
#![allow(unused_variables)]