Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust-gdb cannot pretty print for Option<T> where T: non C-style enum #51347

Closed
foriequal0 opened this issue Jun 4, 2018 · 6 comments
Closed
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.)

Comments

@foriequal0
Copy link

I've tried this code:

// a.rs
use std::option::Option;

enum Enum {A, B}
enum Union { A(usize), B(usize) }
enum Mixed { A(usize), B }
enum Field { A { field: usize }, B { field: usize } }

fn main() {
    let enum_a = Enum::A;
    let enum_b = Enum::B;
    let enum_some_a = Option::Some(Enum::A);
    let enum_some_b = Option::Some(Enum::B);
    let enum_none: Option<Enum> = Option::None;
    
    let union_a = Union::A(42);
    let union_b = Union::B(84);
    let union_some_a = Option::Some(Union::A(42));
    let union_some_b = Option::Some(Union::B(84));
    let union_none: Option<Union> = Option::None;

    let mixed_a = Mixed::A(42);
    let mixed_b = Mixed::B;
    let mixed_some_a = Option::Some(Mixed::A(42));
    let mixed_some_b = Option::Some(Mixed::B);
    let mixed_none: Option<Mixed> = Option::None;

    let field_a = Field::A { field: 42 };
    let field_b = Field::B { field: 84 };
    let field_some_a = Option::Some(Field::A { field: 42 });
    let field_some_b = Option::Some(Field::B { field: 84 });
    let field_none: Option<Field> = Option::None;

    let number = 42;
    let number_some = Option::Some(42);
    let number_none: Option<i32> = Option::None;

    println!("yay");
}
rustc -g a.rs -o a
rust-gdb a
# b 37
# run
# info locals

Expected:
Everything should be pretty printed.

This happened:

Breakpoint 1 at 0x62ce: file a.rs, line 38.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, a::main () at a.rs:38
38	    println!("yay");
number_none = core::option::Option::None
number_some = Some = {42}
number = 42
field_none = <error reading variable>
field_some_b = <error reading variable>
field_some_a = <error reading variable>
field_b = B = {field = 84}
field_a = A = {field = 42}
mixed_none = <error reading variable>
mixed_some_b = <error reading variable>
mixed_some_a = <error reading variable>
mixed_b = a::Mixed::B
mixed_a = A = {42}
enum_none = Some = {(unknown: 2)}
enum_some_b = Some = {a::Enum::B}
enum_some_a = None
enum_b = a::Enum::B
enum_a = a::Enum::A
union_none = <error reading variable>
union_some_b = <error reading variable>
union_some_a = <error reading variable>
union_b = B = {84}
union_a = A = {42}

rust-gdb failed to pretty print every variable whose type is like Option<T: non C-style enum>, although pretty printing variables of T itself is fine.
Most weird cases are enum_* variables. enum_some_b is printed correctly, but enum_some_a and enum_none are printed incorrectly, not failed like other cases.
#[repr(C)] doesn't make any difference to result.
It seems to be fine for other data structures like struct, struct <T>

Meta:
I'm using Ubuntu 18.04.

rustc 1.28.0-nightly (990d8aa74 2018-05-25)
binary: rustc
commit-hash: 990d8aa743b1dda3cc0f68fe09524486261812c6
commit-date: 2018-05-25
host: x86_64-unknown-linux-gnu
release: 1.28.0-nightly
LLVM version: 6.0

You can find this bug on Windows 10.

rustc 1.28.0-nightly (990d8aa74 2018-05-25)
binary: rustc
commit-hash: 990d8aa743b1dda3cc0f68fe09524486261812c6
commit-date: 2018-05-25
host: x86_64-pc-windows-gnu
release: 1.28.0-nightly
LLVM version: 6.0
@nagisa
Copy link
Member

nagisa commented Jun 5, 2018

Use a recent version gdb (8.0, 8.1) directly, without rust-gdb.

@nagisa
Copy link
Member

nagisa commented Jun 5, 2018

Having said that, the output from gdb 8.1 is not ideal either:

Breakpoint 1, test::main () at test.rs:38
38	    println!("yay");
number_none = core::option::Option::None
number_some = core::option::Option::Some(42)
number = 42
field_none = <error reading variable>
field_some_b = <error reading variable>
field_some_a = <error reading variable>
field_b = test::Field::B{field: 84}
field_a = test::Field::A{field: 42}
mixed_none = <error reading variable>
mixed_some_b = <error reading variable>
mixed_some_a = <error reading variable>
mixed_b = test::Mixed::B
mixed_a = test::Mixed::A(42)
union_none = <error reading variable>
union_some_b = <error reading variable>
union_some_a = <error reading variable>
union_b = test::Union::B(84)
union_a = test::Union::A(42)
enum_none = core::option::Option<test::Enum>::Some((unknown: 2))
enum_some_b = core::option::Option<test::Enum>::Some(test::Enum::B)
enum_some_a = core::option::Option<test::Enum>::None
enum_b = test::Enum::B
enum_a = test::Enum::A

Seems to suggest an issue is more general than gdb.

@nagisa nagisa added the A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) label Jun 5, 2018
@foriequal0
Copy link
Author

This stack trace might help.
I got this trace on gdb shell of Clion(with Rust plugin) debugger while I'm trying to print the variable.

(most recent call last):
  File "<HOME>\.rustup\toolchains\nightly-x86_64-pc-windows-gnu\lib\rustlib\etc/gdb_rust_pretty_printing.py", line 166, in rust_pretty_printer_lookup_function
    if encoded_enum_info.is_null_variant():
  File "<HOME>\.rustup\toolchains\nightly-x86_64-pc-windows-gnu\lib\rustlib\etc/debugger_pretty_printers_common.py", line 295, in is_null_variant
    return discriminant_val.as_integer() == 0
  File "<HOME>\.rustup\toolchains\nightly-x86_64-pc-windows-gnu\lib\rustlib\etc/gdb_rust_pretty_printing.py", line 83, in as_integer
    return int(self.gdb_val)
gdb.error: Cannot convert value to int.

@tromey
Copy link
Contributor

tromey commented Jun 13, 2018

I believe this is a dup of #32920.

Well, to be maybe a bit more precise, the newer enum optimizations are not reflected in the DWARF. Formerly the NonZero optimization was handled by emitting a specially named field, but this approach wasn't updated for the newer niche-filling approaches. The patch I have for #32920 does fix this bug:

(gdb) info local
number_none = core::option::Option<i32>::None
number_some = core::option::Option<i32>::Some(42)
number = 42
field_none = core::option::Option<a::Field>::None
field_some_b = core::option::Option<a::Field>::Some(a::Field::B{field: 84})
field_some_a = core::option::Option<a::Field>::Some(a::Field::A{field: 42})
field_b = a::Field::B{field: 84}
field_a = a::Field::A{field: 42}
mixed_none = core::option::Option<a::Mixed>::None
mixed_some_b = core::option::Option<a::Mixed>::Some(a::Mixed::B)
mixed_some_a = core::option::Option<a::Mixed>::Some(a::Mixed::A(42))
mixed_b = a::Mixed::B
mixed_a = a::Mixed::A(42)
union_none = core::option::Option<a::Union>::None
union_some_b = core::option::Option<a::Union>::Some(a::Union::B(84))
union_some_a = core::option::Option<a::Union>::Some(a::Union::A(42))
union_b = a::Union::B(84)
union_a = a::Union::A(42)
enum_none = core::option::Option<a::Enum>::None
enum_some_b = core::option::Option<a::Enum>::Some(a::Enum::B)
enum_some_a = core::option::Option<a::Enum>::Some(a::Enum::A)
enum_b = a::Enum::B
enum_a = a::Enum::A

I haven't yet submitted a PR with that patch because it breaks most debugging of enums for lldb. The Rust lldb plugin does mostly work for this (I did just find a bug with it, bleah), so I think once lldb ends up in rustup I could go ahead with the patch.

Meanwhile I suppose this bug could be closed as a dup.

@tromey
Copy link
Contributor

tromey commented Jun 13, 2018

@foriequal0
Copy link
Author

I'll close this issue since I understand that this is a dup.
I really hope to see your fixes are available soon.
Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.)
Projects
None yet
Development

No branches or pull requests

3 participants