Great writeup! The defmt logging crate uses a linker script to extract debug symbols so that you get nicely formatted stack traces on embedded systems. It works on linux, macos and windows. I wonder if the same technique can be applied to this project. It needs a runner though so may not be the right approach.<p><a href="https://github.com/knurling-rs/defmt" rel="nofollow">https://github.com/knurling-rs/defmt</a>
I've used very similar method, at work, to provide C++ "reflection" between my own system and a system from another team.<p>Basically, the other system is a dynamic library which sends and receives C structures from my application. Those structures are then mapped into a buffer that is supposed to have the same size and there are pointers with metadata pointing into the buffer that are supposed to be exactly like the struct elements. Those structures can have arbitrary complexity, and are passed around through type erasure (essentially char*).<p>I wrote a "reflection" code for the other team, which runs when they register the struct instance to be sent, checks if there's a matching PDB [0] around, reads it, and outputs a json including the metadata needed, which can then be used to define the structures' metadata on our side correctly.<p>This is all in C/C++ since in some contexts we have soft real-time requirements, else I would have used any of the many RPC frameworks available.<p>This has been working for several years now.<p>This is not a generic solution but it's good enough for in-house communication between 2 systems that are maintained by different parts of the organization, where the API between them, that like I said is based on passing around char* buffers, has been more or less set in stone a long time ago. Conway's law [1] and all that. Sigh.<p>[0] We are a Windows shop although the same thing should work with DWARF info, same as the OP library works. In fact he says "It may never work on Windows, which does not use DWARF to encode debug info" but I can say that the same approach does work on Windows, for C++ at least. The PDB format might be a tad undocumented, but its documentation has been improved in the last decade or so since I started working on my library. Writing some small test programs is enough to understand how to access it, if all you need is meta info on C-style structures. Other stuff is more... challenging. But it wasn't necessary for my use-case.<p>[1] <a href="https://en.wikipedia.org/wiki/Conway%27s_law" rel="nofollow">https://en.wikipedia.org/wiki/Conway%27s_law</a>
Does using DWARF info imply that this will break when you strip the resulting executable? I often strip my Rust binaries because it practically halves the application size, which can become quite a lot in a language where you're statically linking everything.<p>Regardless, quite an ingenious use of standard ELF features, I didn't think this would be possible in Rust without adding some kind of VM around reflection code.
<i>"When you call .reflect on a dyn Reflect value, deflect figures out its concrete type in four steps:"</i><p>* <i>invokes local_type_id to get the memory address of your value’s static implementation of local_type_id</i><p>* <i>maps that memory address to an offset in your application’s binary</i><p>* <i>searches your application’s debug info for the entry describing the function at that offset</i><p>* <i>parses that debugging information entry (DIE) to determine the type of local_type_id’s &self parameter</i>.<p>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.<p>My experience with Rust has been that debugging of safe code is just not a problem. Print statements and logging are enough.
This is a beautiful (hacky) demo of something that I didn't think was possible in Rust (yet). I hope other applications don't accidentally start using it just to discover that it doesn't work in release mode.<p>Very impressive work!
Can’t we rely more on Rust’s Pattern Matching and it’s strong type system?<p>Reflection seems more helpful when the programming language is little unsounded.
My version of Greenspun's Tenth [1] is that any sufficiently complex static language contains an adhoc, informally specified, bug ridden and slow version of a dynamic "any" type.<p>Thx OP for providing an example.<p>[1] <a href="https://en.wikipedia.org/wiki/Greenspun's_tenth_rule" rel="nofollow">https://en.wikipedia.org/wiki/Greenspun's_tenth_rule</a>