Hacker News new | ask | show | jobs
by Animats 1281 days ago
"When you call .reflect on a dyn Reflect value, deflect figures out its concrete type in four steps:"

* invokes local_type_id to get the memory address of your value’s static implementation of local_type_id

* maps that memory address to an offset in your application’s binary

* searches your application’s debug info for the entry describing the function at that offset

* parses that debugging information entry (DIE) to determine the type of local_type_id’s &self parameter.

This is a rather strange thing to bolt onto a language. I could see this as an external tool. The use case seems to be programs which used "async" so much they can't figure out the resulting state machine. External debug tools to view and examine the async state machine might be helpful.

My experience with Rust has been that debugging of safe code is just not a problem. Print statements and logging are enough.

3 comments

> This is a rather strange thing to bolt onto a language. I could see this as an external tool.

It is an external tool. This is a crate, not a part of the compiler.

Are you saying there aren’t any legitimate uses for runtime reflection? Because I think Java and .Net, even Go have proved that wrong over the years.

This seems like a valuable library. It’s impressive that it can be so powerful in a compiled language. C and C++ are much older but don’t have anything quite like this.

A lot of what you'd use reflection for in GC languages is done with macros/code generation at compile time in Rust. For example, rather than using reflection to map objects to something like JSON to serialize, Rust has a library called serde (https://serde.rs/) that lets you annotate structs and enums and generate conversions at compile time that you can use. I wouldn't go so far as saying that there's no possible legitimate use of reflection, but I do wonder how much could be happening in Java and C# and Go that's so dynamic that you wouldn't be able to reason about it in advance. I think most of what reflection is used for in those languages _could_ be done at compile time, but it would both require a way to express it (via macros, codegen, or something like that) and be worth the extra compile time in order to save runtime. Rust's ethos is to try to optimize as much as possible for runtime efficiency even at the expensive of compile time, and while there can be (and often are!) ways to opt out of this for a given feature, it's almost never the default.
I’ve used Rust extensively the last couple years. I understand that. A lot of what people do with reflection in Go could be done more efficiently with code generation - but more easily with reflection. I’m sure the same is true in Rust, to a lesser extent. There are times when runtime reflection would be really nice to have.
> This is a rather strange thing to bolt onto a language.

It can just be an extremely fun and cute demo, without practical application.

It can also be something that looks cool and doesn't necessarily ever get past "kinda works", but piques the interest of the core dev team and they take steps to make it work even better, resulting in the ultimate "deprecation" of this sort of thing by virtue of it being even better integrated into the core.

I don't have the context to judge the probability of that in this specific case (lots of technical nitty-gritty comes in to this sort of thing), but I've certainly seen similar things happen in other communities.

how about adding this to debuggers for better object-views? (could it be possible to provide near-js/python/java level of obj view?)
Thus is already using DWARF debug infos. Using this for debugging would be a long way around to arrive where you started

You can already script gdb to provide rich views of any data structure.

DWARF is a standard for data to support debuggers, so this crate does effectively the opposite: it uses info normally only available during debugging to provide reflection.