I wrote the following code: ``` use fst::{Set}; use fst::automaton::Levenshtein; fn main() -> Result<(), Box<dyn std::error::Error>> { let keys = vec!["hej"]; let set = Set::from_iter(keys)?; let lev = Levenshtein::new("foo", 1)?; println!("{:#?}", set); println!("{:#?}", lev); Ok(()) } ``` This code crashes when attempting to run this line: ``` let lev = Levenshtein::new("foo", 1)?; ``` Here is the `Cargo.toml`: ``` [package] name = "playground" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] fst = { version = "0.4.7", features = ["levenshtein"] } ``` How to reproduce: 1. `cargo new playground` 2. enter project's root directory 3. `cargo add fst --features=levenshtein` 4. `nvim .` (note: I have NerdTree extension in my Neovim) 5. Navigate into `main.rs` file via NerdTree 6. Replace the `main.rs` content with: ``` use fst::{Set}; use fst::automaton::Levenshtein; fn main() -> Result<(), Box<dyn std::error::Error>> { let keys = vec!["hej"]; let set = Set::from_iter(keys)?; let lev = Levenshtein::new("foo", 1)?; println!("{:#?}", set); println!("{:#?}", lev); Ok(()) ``` 7. `:w` in neovim 8. `:! cargo build` in neovim (note that bash is in project's root folder while neovim is simultaneously in `main.rs` at this point) 9. Open another terminal in project's root folder 10. In the new terminal, run `gdb target/debug/playground` (alternatively: `rust-gdb target/debug/playground`) 11. In gdb, run the following commands, one line at a time (note that I have [GDB Dashboard](https://github.com/cyrus-and/gdb-dashboard) implemented into my GDB): ``` list b 8 b 10 list b 11 b 12 r c ``` It crashes as soon as you enter `c`. The following specified what "crash" means and shows the output that I see: ``` Breakpoint 2, playground::main () at src/main.rs:10 10 println!("{:#?}", set); ../../gdb/gdbtypes.h:1064: internal-error: field: Assertion `idx >= 0 && idx < num_fields ()' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. ----- Backtrace ----- 0x5654d0133b6b ??? 0x5654d0471d44 ??? 0x5654d0534ce3 ??? 0x5654d00b3ea1 ??? 0x5654d0483e23 ??? 0x5654d03b74bc ??? 0x5654d047f0db ??? 0x5654d0484935 ??? 0x5654d0485b6b ??? 0x5654d03b70ab ??? 0x5654d047f0db ??? 0x5654d03b6cd0 ??? 0x5654d03b70ef ??? 0x5654d047f0db ??? 0x5654d036ed08 ??? 0x7f96c5548418 ??? 0x7f96c54f9c9f ??? 0x7f96c54f4b83 ??? 0x7f96c5529420 ??? 0x7f96c54e4b33 ??? 0x5654d03632a6 ??? 0x5654d022a526 ??? 0x5654d047f164 ??? 0x5654d03b6cd0 ??? 0x5654d03b70ef ??? 0x5654d047f0db ??? 0x5654d03b6cd0 ??? 0x5654d03b70ef ??? 0x5654d047f0db ??? 0x5654d036ed08 ??? 0x7f96c5548418 ??? 0x7f96c54f9c9f ??? 0x7f96c54f4b83 ??? 0x7f96c5500bb8 ??? 0x7f96c54efd75 ??? 0x7f96c5500bb8 ??? 0x7f96c54efd75 ??? 0x7f96c5500bb8 ??? 0x7f96c54f48de ??? 0x7f96c5500bb8 ??? 0x7f96c54f48de ??? 0x7f96c5500bb8 ??? 0x7f96c54f01a9 ??? 0x7f96c550be45 ??? 0x7f96c54f0eb5 ??? 0x7f96c54ee9bf ??? 0x7f96c550bf6c ??? 0x7f96c5500357 ??? 0x7f96c559dcc0 ??? 0x5654d05b11ba ??? 0x5654d03617f2 ??? 0x5654d02bc432 ??? 0x5654d02b3f52 ??? 0x5654d0535955 ??? 0x5654d0535d06 ??? 0x5654d02f3d24 ??? 0x5654d009fc04 ??? 0x7f96c4c3a28f ??? 0x7f96c4c3a349 ??? 0x5654d00a61e4 ??? 0xffffffffffffffff ??? --------------------- ../../gdb/gdbtypes.h:1064: internal-error: field: Assertion `idx >= 0 && idx < num_fields ()' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) ```
This works for me. I tried the gdb 12 release branch and also git master. Can you try reproducing with '-nx' -- that is, avoid your add-ons?
(In reply to Tom Tromey from comment #1) > This works for me. I tried the gdb 12 release branch and also git master. > > Can you try reproducing with '-nx' -- that is, avoid your add-ons? Oh, it works for me now that I used `-nx`. Thanks
This doesn't mean there isn't a gdb bug. Maybe gdb-dashboard is running other commands behind the scenes. It would be good to find out.
(In reply to Tom Tromey from comment #3) > This doesn't mean there isn't a gdb bug. > Maybe gdb-dashboard is running other commands behind the scenes. > It would be good to find out. Any suggestions on specific steps I may try out?
(In reply to amir from comment #4) > Any suggestions on specific steps I may try out? I don't know much about gdb-dashboard, so I don't know what to suggest. Based on the assertion, I'd say maybe try "info local" at the second breakpoint. Otherwise maybe see if gdb-dashboard has some kind of verbose mode or the like.
Any new info on this?
Created attachment 15198 [details] Patch for this issue, or an issue similar to it I experienced this in 13.2. I believe it's related to the null pointer optimization, or at least the case I encountered was. ``` use std::num::NonZeroUsize; use std::hint::black_box; pub fn main() { foo(black_box(NonZeroUsize::new(5)), black_box(NonZeroUsize::new(5))) } #[inline(never)] pub fn foo(x: Option<NonZeroUsize>, y: Option<NonZeroUsize>) { black_box(x.unwrap().checked_add(y.unwrap().into())); } ``` Put this in `tmp.rs`. Compile with `rustc tmp.rs -Copt-level=1 -Cdebuginfo=full` Run `gdb tmp::foo` `break foo` `run` `info args` Observe assertion fail: ``` x = core::option::Option<core::num::nonzero::NonZeroUsize>::Some( ../../gdb/gdbtypes.h:985: internal-error: field: Assertion `idx >= 0 && idx < num_fields ()' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. ``` This issue is related to this portion of code in `rust_lang::print_enum`: ``` 461 type = resolve_dynamic_type (type, view, value_address (val)); ... [snip] 472 int variant_fieldno = rust_enum_variant (type); 473 val = value_field (val, variant_fieldno); 474 struct type *variant_type = type->field (variant_fieldno).type (); ``` https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/rust-lang.c;h=74808ad0716e4d67f6af859f05ebff2b55d5e276;hb=662243de0e14a4945555a480dca33c0e677976eb#l461 The type from `resolve_dynamic_type` makes only the variant field of the active discriminant in active. However, the type of `val` has *all* variant fields enabled, thus making this index meaningless for that. I created a patch for this, which is somewhat hacky--any maintainers here, feel free to change it up a bit; I am a Rust developer by nature and don't know much about idiomatic C/++ and in general, what the GDB codebase looks like. Please let me know if you'd like me to test/update this patch to the v14 codebase.
Woops, I apologize, I accidentally left a debugging `printf` in there. Give me a moment and I'll upload the real patch
Comment on attachment 15198 [details] Patch for this issue, or an issue similar to it >From 07bb370168aab780c4780435ad3d9257ad8a474b Mon Sep 17 00:00:00 2001 >From: ThePuzzlemaker <tpzker@thepuzzlemaker.info> >Date: Sat, 28 Oct 2023 13:28:33 -0500 >Subject: [PATCH] Fix assertion fail from `rust_lang::print_enum` > >This commit fixes an assertion fail in `rust_lang::print_enum` related >to the handling of field numbers for variant types. >--- > gdb/rust-lang.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c >index 74808ad0716..9acd2e1d2fa 100644 >--- a/gdb/rust-lang.c >+++ b/gdb/rust-lang.c >@@ -470,8 +470,18 @@ rust_language::print_enum (struct value *val, struct ui_file *stream, > } > > int variant_fieldno = rust_enum_variant (type); >- val = value_field (val, variant_fieldno); > struct type *variant_type = type->field (variant_fieldno).type (); >+ /* HACK: variant_fieldno is indexed in 'type', which has the field >+ disabled for other variants. The type of 'val' does not. Thus, >+ iterate through the fields and find the one that matches. */ >+ for (int i = 0; i < value_type (val)->num_fields (); i++) { >+ value* new_val = value_field (val, i); >+ if (types_equal (value_type (new_val), variant_type)) { >+ val = new_val; >+ break; >+ } >+ } >+ gdb_assert(types_equal(value_type (val), variant_type)); > > int nfields = variant_type->num_fields (); > >-- >2.42.0
(In reply to The Puzzlemaker from comment #9) > Comment on attachment 15198 [details] > Patch for this issue, or an issue similar to it > > >From 07bb370168aab780c4780435ad3d9257ad8a474b Mon Sep 17 00:00:00 2001 > >From: ThePuzzlemaker <tpzker@thepuzzlemaker.info> > >Date: Sat, 28 Oct 2023 13:28:33 -0500 > >Subject: [PATCH] Fix assertion fail from `rust_lang::print_enum` > > > >This commit fixes an assertion fail in `rust_lang::print_enum` related > >to the handling of field numbers for variant types. > >--- > > gdb/rust-lang.c | 12 +++++++++++- > > 1 file changed, 11 insertions(+), 1 deletion(-) > > > >diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c > >index 74808ad0716..9acd2e1d2fa 100644 > >--- a/gdb/rust-lang.c > >+++ b/gdb/rust-lang.c > >@@ -470,8 +470,18 @@ rust_language::print_enum (struct value *val, struct ui_file *stream, > > } > > > > int variant_fieldno = rust_enum_variant (type); > >- val = value_field (val, variant_fieldno); This code looks different on trunk. IIRC I fixed a bug like this a while ago. git says 2020 though, which seems wrong if you're using 13.
(In reply to The Puzzlemaker from comment #7) > `break foo` > `run` > `info args` This works for me with my 14.x build from git: (gdb) info args x = core::option::Option<core::num::nonzero::NonZeroUsize>::Some(core::num::nonzero::NonZeroUsize ( 5 )) y = core::option::Option<core::num::nonzero::NonZeroUsize>::Some(core::num::nonzero::NonZeroUsize ( 5 ))
This is in fact fixed in 14.x git.
It seems it was 2023 actually. https://sourceware.org/git/?p=binutils-gdb.git;a=commit;f=gdb/rust-lang.c;h=debd0556e519c3d258299cf5f14a44cc01c795da
Thanks for your help. @amir, it'd be great if you could test and see if this issue still occurs with GDB 14.x
I think this is fixed.