-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Consider:
use std::fmt::Debug;
#[derive(Default)]
struct Plain {
a: usize
}
impl Plain {
fn f(&self) {
dbg!(self.a);
}
}
#[derive(Default)]
struct Generic<A: Default> {
a: A
}
impl<A: Debug + Default> Generic<A> {
fn f(&self) {
dbg!(&self.a);
}
fn f_with_its_own_generics<B: Debug>(&self, b: &B) {
dbg!(b);
}
}
impl Generic<usize> {
fn f_specialized(&self) {
dbg!(self.a);
}
}
impl<A: Debug> Generic<Option<A>> {
fn f_different_generics(&self) {
dbg!(&self.a);
}
}
fn main() {
let p = Plain::default();
let g1 = Generic::<usize>::default();
let g2 = Generic::<Option<usize>>::default();
unsafe { std::arch::asm!("int3"); }
p.f();
g1.f();
g1.f_specialized();
g1.f_with_its_own_generics(&"hello");
g2.f();
g2.f_different_generics();
g2.f_with_its_own_generics(&"hello");
}
rust-gdb against a debug build of the above can evaluate p.f()
and g1.f_specialized()
, but not g1.f()
, despite that function being present enough in the binary to break
on:
Program received signal SIGTRAP, Trace/breakpoint trap.
gdb_generics_repro::main () at src/main.rs:48
48 p.f();
(gdb) p p.f()
[src/main.rs:10:9] self.a = 0
$3 = ()
(gdb) p g1.f_specialized()
[src/main.rs:31:9] self.a = 0
$4 = ()
(gdb) p g1.f()
Could not find function named 'gdb_generics_repro::Generic<usize>::f'
(gdb) i functions .*Generic.*f
All functions matching regular expression ".*Generic.*f":
File src/main.rs:
20: static fn gdb_generics_repro::Generic<core::option::Option<usize>>::f<core::option::Option<usize>>(*mut gdb_generics_repro::Generic<core::option::Option<usize>>);
36: static fn gdb_generics_repro::Generic<core::option::Option<usize>>::f_different_generics<usize>(*mut gdb_generics_repro::Generic<core::option::Option<usize>>);
24: static fn gdb_generics_repro::Generic<core::option::Option<usize>>::f_with_its_own_generics<core::option::Option<usize>, &str>(*mut gdb_generics_repro::Generic<core::option::Option<usize>>, *mut &str);
20: static fn gdb_generics_repro::Generic<usize>::f<usize>(*mut gdb_generics_repro::Generic<usize>);
30: static fn gdb_generics_repro::Generic<usize>::f_specialized(*mut gdb_generics_repro::Generic<usize>);
24: static fn gdb_generics_repro::Generic<usize>::f_with_its_own_generics<usize, &str>(*mut gdb_generics_repro::Generic<usize>, *mut &str);
(gdb) b gdb_generics_repro::Generic<usize>::f<usize>
Breakpoint 4 at 0x555555569d39: file src/main.rs, line 21.
The issue is with these trailing generics after method function names, e.g. the second <usize>
in gdb_generics_repro::Generic<usize>::f<usize>
. They apparently correspond to the generic params of the function's containing impl
, and are printed as if they're generic params of the function even for functions which aren't actually generic.
Besides being necessary for b
, I see that these extra generics are necessary for lookup_symbol
triggered from a python extension. But the method lookup logic in rust-lang.c
seems to omit them:
value *
rust_structop::evaluate_funcall (struct type *expect_type,
struct expression *exp,
enum noside noside,
const std::vector<operation_up> &ops)
{
std::vector<struct value *> args (ops.size () + 1);
/* Evaluate the argument to STRUCTOP_STRUCT, then find its
type in order to look up the method. */
args[0] = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
/* We don't yet implement real Deref semantics. */
while (args[0]->type ()->code () == TYPE_CODE_PTR)
args[0] = value_ind (args[0]);
struct type *type = args[0]->type ();
if ((type->code () != TYPE_CODE_STRUCT
&& type->code () != TYPE_CODE_UNION
&& type->code () != TYPE_CODE_ENUM)
|| rust_tuple_type_p (type))
error (_("Method calls only supported on struct or enum types"));
if (type->name () == NULL)
error (_("Method call on nameless type"));
std::string name = (std::string (type->name ()) + "::"
+ std::get<1> (m_storage));
const struct block *block = get_selected_block (0);
struct block_symbol sym = lookup_symbol (name.c_str (), block,
SEARCH_FUNCTION_DOMAIN,
nullptr);
Generics are pretty common, so I suspect lots of people are hitting this and thinking rust-gdb just doesn't support method calls.
Is it maybe just a bug that impl generics started getting included in method names at some point? I can't see what ambiguity they'd be resolving, given that the generics of the underlying struct are also part of the symbol.
Note that the impl generics part of the name can differ from the struct generics part, as with f_different_generics()
above.
cc: @tromey
Meta
rustc --version --verbose
:
rustc 1.89.0-nightly (59aa1e873 2025-06-03)
binary: rustc
commit-hash: 59aa1e873028948faaf8b97e5e02d4db340ad7b1
commit-date: 2025-06-03
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.5
~/code/scrap/rust/gdb_generics_repro/src: gdb --version
GNU gdb (GDB) 16.3
Backtrace
<backtrace>