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.<p>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<p><pre><code> #[derive(Reflectable)]
struct Foo {
pub i: i32,
x: i32
}
</code></pre>
such that this expands to something like<p><pre><code> struct Foo {
pub i: i32,
x: i32
}
impl Foo {
fn private_mirror() -> Mirror {
/* construct mirror for all fields */
}
}
impl Reflectable for Foo {
fn mirror() -> Mirror {
/* construct mirror for public fields */
}
}
</code></pre>
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.
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.<p>I think the API with safe public reflection and unsafe private reflection is easy to motivate.<p>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.<p>I know enough Bevy and Rust to know that Bevy does have their own Reflection library (<a href="https://docs.rs/bevy_reflect/latest/bevy_reflect/" rel="nofollow">https://docs.rs/bevy_reflect/latest/bevy_reflect/</a>), 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.
Not clear on the problem.<p>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.<p>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.<p>The author doesn't make a strong case for reflection for other purposes.<p>[1] <a href="https://docs.rs/serde/latest/serde/trait.Serialize.html" rel="nofollow">https://docs.rs/serde/latest/serde/trait.Serialize.html</a>
I prototyped <a href="https://github.com/emberian/serde-reflect">https://github.com/emberian/serde-reflect</a> 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 <i>should</i> 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.<p>Modern languages should <i>enable</i> what older languages couldn‘t. They shouldn‘t get in my way needlessly.