Accessing private struct fields breaks abstractions, which can be very harmful since it can invalidate the invariants / properties of the struct.
If the struct relies on any of these invariants while doing unsafe this would mean that breaking them would lead to serious bugs, most probably UB.
For this reason it is much easier to reason about struct members as being “as private” as they are declared to be. Non-locality of properties / invariants is just a footgun whn multiple people work on the same project.
Finally, downstream crates can still impl their own traits, and there would then be definitely no abstraction whatsoever if such impls allowed to access private struct members.
Regarding your example, you can:
-
move the impls into the module (or one of its submodules) containing the struct definition;
-
define the struct members as pub(in path::to::the::other::mod) (ideally: pub(in super) and no further); you can use pub(in crate) if you don’t care that much about scalable maintainability of your project (e.g., when quick prototyping);
-
define constructors / setters / getters so that you can access the struct members through them;
- (if the public ones are not flexible enough, remember you can define
pub(in path) associated functions and methods too)