Pet peeves: dbg!(an_arc)
doesn't show that it's an Arc
, nor which instance of an Arc
it is, dbg!(an_str)
doesn't show that it's a &str
, nor which instance of &str
it is, etc. There are a few more cases like this in the stdlib. Is there any particular reason why the stdlib is unhelpful about debugging these types? These Debug
impls that relate to references/smart pointers should include the pointer value while at it, so you can tell if you got two "identical" values mixed up somewhere. This is important both where interior mutability is concerned, as interior mutability is opaque to debugging, as well as where unsafe code is concerned, because pointer operations between different allocations are UB (particularly relevant with slices).
The general assumption is that you know the type when you're looking at the Debug
formatting of some value. This is, ultimately, just an arbitrary decision made to reduce noise in the {:?}
debug repr.
If you want the typename of the root object, you can easily just make your own dbg!
(even shadowing the implicit prelude one) that also prints std::any::type_name
. For non-root objects, you should have enough type context to know if something is boxed.
Note that rust-analyzer
exists. It can show you the type of variables inside your editor.
You can implement that macro with std::any::type_name
.
For example:
macro_rules! type_dbg {
($val:expr) => {
match $val {
tmp => {
// Copy of `std::any::type_name_of_val`, which is nightly-only.
fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
std::any::type_name::<T>()
}
eprintln!(
"[{}:{}] {} : {} = {:#?}",
file!(),
line!(),
stringify!($val),
type_name_of_val(&tmp),
&tmp
);
tmp
}
}
};
}
Sorry, we may have misrepresented our point.
If the pointer value matters to debuggging, you're expected to use std::fmt::Pointer
, {:p}
.
macro_rules! dbg_ptr {
($val:expr) => {
match $val {
ref tmp => {
// Copy of `std::any::type_name_of_val`, which is nightly-only.
fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
std::any::type_name::<T>()
}
eprintln!(
"[{file}:{line}] {expr} : {ty} = [{ptr:p}] {val:#?}",
file=file!(),
line=line!(),
expr=stringify!($val),
ty=type_name_of_val(tmp),
ptr=*tmp,
val=tmp,
);
tmp
}
}
}
}
In the common case, pointer identity doesn't matter for correctness (and where it does, the borrow checker handles it) so it's fine to leave it out and opt-in.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.