Here is the actual scenario that led me to think about this:
- I’m rewriting some software pieces by pieces in Rust.
- That software uses a .ini-like configuration.
- There are two crates with the “ini” keywords on crates.io: rust-ini and tini.
- The former can’t read the configuration because it considers # to start comments, but the configuration contains # in values (there’s an open issue on rust-ini about that, that’s not relevant to this discussion).
- The latter can read the configuration, but it has a very limited API, and doesn’t have any way to iterate over the whole configuration (which rust-ini has).
So here I am, with two possible crates to fulfill my needs, but neither can fulfill them completely. Now I’m faced with multiple choices:
- Fix rust-ini
- Improve tini
In either case, there are further sub-choices:
- Fork the crate, and point to my fork in Cargo.toml.
- Import the crate in my own repo.
- Submit changes upstream, wait for them to be merged in a new release.
The latter is also something that should be done in the other cases, but the other cases allow for progress on my own project without having to wait on a third party.
All of the above are complications that maybe could be helped by allowing some relaxation of e.g. the orphan rules for trait implementations.
In my specific scenario, being allowed to add an implementation of Iterator on the tini::Ini struct would (mostly) make life easier (the other half of the problem being that access to private fields in the struct is required).
I know I’ve been frustrated more than once by the limitations of trait implementation for foreign types. I do understand why those limitations are there, but I posit that while they make sense in the case of libstd and other libs that come with the compiler, they seem arbitrarily restrictive for other dependencies where your Cargo.toml has an explicit dependency on a specific version: yes, a future version of that crate may change things such that your trait implementation doesn’t work, or implement that trait itself, but a) a future version of that crate may change any other thing in a way that would break your code and b) you would only use the future version if you asked for it.
Now, I’m not suggesting that the limitations should be lifted by default, or for non-libstd, but that maybe having some syntax allowing it would, IMHO, help cases like the current scenario I’m in. I think some syntax that would say something like “pretend the following block is defined in that other module in that other crate, and I’m willing to pay the consequences” would go a long way.