@Jurily brought up an interesting idea that I feel got a little overlooked: the ability to (transiently) forgo public/private field protection. Now, I make almost all my struct fields public for pretty much exactly the reason that some user might want to be crafty in a way I didn’t expect, but for classes where that’s not true, I wouldn’t mind the ability to explicitly and obviously opt out of those protections from the compiler, and annotate specific lines in a way that allows me to access private members.
I’ve encountered situations where I’ve wanted to use this multiple times - although I’m usually too much of a cowboy for my own good, I still think it would be nice to have.
For example, recently I wanted to modify the behavior of getopts to use BSD-like rather than GNU-like parsing (i.e. all options must come before free arguments rather than allowing them to be interspersed*). In the modified crate, it would be nice to use the same data types as the original, rather than identical copies, so that external code could operate on them without caring whether the modified or original parser is in use. But this isn’t possible, because getopts::Matches has private fields so I can’t create instances of it from outside the crate. Even though privacy implies there is no stability guarantee for the struct’s layout, it seems unlikely in practice to change anytime soon, so a privacy override would probably work fine for me if it were available (and if it didn’t, it’d be my own fault).
- Now that I think about it, it might be easier just to insert “–” at an appropriate location, then call into the original. But the general point stands.
Allowing access to private properties could ruin backwards compatibility attempts. You can usually feel free to change around private properties and expect not to break anyone downstream.
To me, that’s an onus you reasonably take on when you touch private members. An analogy for me is that I can take unsafe pointers from underneath a ref, and lifetime and one-mutable-reference-only semantics will continue to be enforced for refs, essentially unaware of the sketchy things I’m doing with pointers, essentially assuming that they’re still the only things touching the data they refer to. In the same way (to me), library authors should absolutely continue to treat private members as things that only they know about, essentially unaware of the sketchy things I’m doing with their private members.
This may have been the inspiration, I just remembered it.
I don’t think it’s really needed. This seems like something that will be abused, as opposed to the unsafe code that would be needed to do the same thing otherwise.
If we ever do item-level hygiene, it’s possible that you may not be able to refer the names of private fields at all, so this isn’t future-proof in that respect.
Is this something that is supposed to be useful to allow third parties to use your library in a more flexible way? For example, you’d write a library and then the developer that uses it could opt out of protection? Or is it the library creator that would opt out to avoid repitition of
Would you prefer
I would prefer sanity. Could your usecases be covered by public unsafe fields?
My use case is replacing C as the lowest common denominator for base systems and ultra-portable libraries. In my mind, that’s the only niche Rust can thrive, and only if we’re on par with C in every aspect, including a stable ABI other languages can build on and doing things that are normally crazy but make sense in context.
The more mature stuff like
Vec already expose all their fields through unsafe functions, it’s not necessarily a worse choice to get rid of all the boilerplate. Sure, the users will have to respect all the invariants, but that’s why
unsafe exists in the first place.
C code often uses PIMPL, which hides these details even more.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.