Skip to content

lldb: print formatters format inconsistently #65076

Open
@davidtwco

Description

@davidtwco

One of rustc's debuginfo tests is failing with newer versions of lldb. I'm testing locally with a build of d43f324.

When printing an instance of std::num::NonZeroI8 (which has a trivial pretty printer in our test suite, included below):

(lldb) print/d nz_i8
(core::num::nonzero::NonZeroI8) $0 = '\v' { __0 = 11 }

The /d suffix seems to only apply to the printing of 11 but not the '\v. I can confirm this by requesting a different formatting and see it only change the 11.

As far as I can tell, it used to apply to both in previous versions (as our test expects $0 = 11 and passes with earlier versions of lldb). Using print or frame variable or any other command I've found doesn't seem to make a difference.

You should be able to reproduce it using the following:

// numeric-types.rs
use std::num::*;

fn main() {
    let nz_i8 = NonZeroI8::new(11).unwrap();
    zzz(); // #break
}

fn zzz() { }

(original)

# lldb_lookup.py
import re

class RustType(object):
    OTHER = "Other"
    STRUCT = "Struct"
    STD_NONZERO_NUMBER = "StdNonZeroNumber"

STD_NONZERO_NUMBER_REGEX = re.compile(r"^core::num::([a-z_]+::)*NonZero.+$")

STD_TYPE_TO_REGEX = {
    RustType.STD_NONZERO_NUMBER: STD_NONZERO_NUMBER_REGEX,
}

def classify_rust_type(type):
    type_class = type.GetTypeClass()
    if type_class == lldb.eTypeClassStruct:
        return classify_struct(type.name, type.fields)
    return RustType.OTHER

def classify_struct(name, fields):
    for ty, regex in STD_TYPE_TO_REGEX.items():
        if regex.match(name):
            return ty

    return RustType.STRUCT

def summary_lookup(valobj, dict):
    # type: (SBValue, dict) -> str
    """Returns the summary provider for the given value"""
    rust_type = classify_rust_type(valobj.GetType())

    if rust_type == RustType.STD_NONZERO_NUMBER:
        return StdNonZeroNumberSummaryProvider(valobj, dict)

    return ""

def StdNonZeroNumberSummaryProvider(valobj, _dict):
    # type: (SBValue, dict) -> str
    objtype = valobj.GetType()
    field = objtype.GetFieldAtIndex(0)
    element = valobj.GetChildMemberWithName(field.name)
    return element.GetValue()

(original providers and original lookup and original types)

$ rustc -g numeric-types.rs
(lldb) type summary add -F -F lldb_lookup.summary_lookup  -e -x -h '^core::num::([a-z_]+::)*NonZero.+$' --category Rust
(lldb) type category enable Rust
(lldb) breakpoint set --file 'numeric-types.rs' --line 5
(lldb) print/d nz_i8

(original)

You can also just clone the rust-lang/rust repository and run ./x.py test tests/debuginfo --test-args numeric-types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions