about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2025-08-22 22:00:49 -0400
committerGitHub <noreply@github.com>2025-08-22 22:00:49 -0400
commit5cfdbd6c08681249cab4794366d2ade92e1f7c03 (patch)
tree91acafcb6830099ef353408f048a999ec49f6df0
parent2dbd411d229ee382b1cf2ec3af84cd581d56d521 (diff)
parent6be749b619e5c74133a27ffa9f2485179b64068f (diff)
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" />
-rw-r--r--src/etc/lldb_lookup.py3
-rw-r--r--src/etc/lldb_providers.py35
-rw-r--r--tests/debuginfo/borrowed-enum.rs6
3 files changed, 23 insertions, 21 deletions
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py
index f4ea904b7f5..f43d2c6a725 100644
--- a/src/etc/lldb_lookup.py
+++ b/src/etc/lldb_lookup.py
@@ -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)
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 98426e42423..65f18baa937 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -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
diff --git a/tests/debuginfo/borrowed-enum.rs b/tests/debuginfo/borrowed-enum.rs
index 517b439ff15..893dd777bcd 100644
--- a/tests/debuginfo/borrowed-enum.rs
+++ b/tests/debuginfo/borrowed-enum.rs
@@ -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)]