If I learned right now that Rust had a reflection API then Iâd assume that itâs fundamentally unsafe when it comes to handling non public fields. For exactly the reasons the article lists.
I think the API with safe public reflection and unsafe private reflection is easy to motivate.
The author doesnât really provide any reason why itâs a bad idea other than âpeople might abuse itâ. The SemVer argument I donât understand: the versioning is for the public API. Nobody promises that somelib 1.0.0 and 1.0.1 behave remotely the same if I peek behind the curtain.
> Reflection interacts with the safety features of Rust in a somewhat counter-intuitive way. Those interactions force any reflection API to obey certain rules.
I know enough Bevy and Rust to know that Bevy does have their own Reflection library (https://docs.rs/bevy_reflect/latest/bevy_reflect/), but I don't know the internals of it, anyone happens to know that who can compare it to what the author is ideaing about? As a Bevy user and library author, the Reflect API Bevy uses is simple enough at least.
Isn't reflection at odds with "zero-cost abstraction" principle?
Not clear on the problem.
In Rust, each struct type, to be serialized, must have a serialization and deserialization function of its own. There's a macro to generate these by calling the appropriate serialization or deserialization function for each field.
For the common types, there's a set of standard serialize and deserialize functions. Here's the list.[1] Those handle the special cases around Vec, Mutex, and such.
The author doesn't make a strong case for reflection for other purposes.
I prototyped https://github.com/emberian/serde-reflect if anyone is interested
I get what the article is saying. I enjoy Rust, as I enjoy dabbling in other more esoteric programming languages, like Zig. But one thing I miss from the days of early programming is the hacker spirit, in a way. As it master, I should be able to force my machine into giving me access of private fields. I want to be able to poke holes in stuff, to break things and at times, I want the ability to do something stupid just because I want to see what would happen. I feel the same for overly strict compilers. The number one thing I hate about Zig is the compiler treating me like a child when I have unreferenced variables.
Modern languages should enable what older languages couldnât. They shouldnât get in my way needlessly.
It seems a bit weird to me to dedicate all this space to talking about access to private fields and respecting field access rules, and not even suggest the idea that a reflection API should actually provide different levels of information depending on where you're invoking it from. Which is to say, if I'm writing code inside the module that defines a type, then I should be able to reflect on that type's private fields as my code can otherwise access those private fields. And if I'm writing code from outside the module then I shouldn't be able to reflect on those private fields.
One way to accomplish this would be to have reflection add a private method to a reflectable type that returns a mirror that includes information on the private fields. This does require the capability to reflect to be opt-in (and I think this article is assuming that reflection is globally enabled on all types rather than being opt-in), but reflection could plausibly be done as something like
such that this expands to something like This way code from within the module can call `private_mirror()` to get a mirror to pass to reflection APIs (and Mirror could implement Reflectable to return itself like how Iterator implements IntoIterator) in order to do things like implement serialization.