Allow method calls without borrowing entire struct

For prior/related discussion:

  • Essentially the same problem happens with closure captures, but it’s arguably a much simpler case because we could fix it just by changing language rules without adding any new syntax. https://github.com/rust-lang/rfcs/pull/2229 is the RFC for doing just that.

  • In the context of methods borrowing self, I’ve seen this idea semi-consistently referred to as “partial self borrowing”, which I think is likely the best name we’re going to get for it.

  • Partial self borrowing syntax is an old thread, but it has multiple comments from @nikomatsakis and @withoutboats covering why partial borrows are a lot harder than they look.

To summarize the significant concerns/problems I found by skimming existing threads/issues:

  • First, note that this feature is totally redundant for public fields, since the client code can already do “partial borrows” just by accessing the fields themselves. So we can assume this is strictly about private fields.
  • How does partial borrowing work with traits? The fields in traits proposal would only help for public fields, so we’d probably need something like “borrow regions” in traits, which seems like a pretty heavy feature when the only benefit is making a few more method call sequences borrow-legal.
  • Exposing private fields in public method signatures seems like leaking implementation details, which is undesirable in principle. It’s likely that many use cases for this feature should consider simply making more fields public.
  • Partial self borrows create a new kind of API compatibility hazard, because two public methods that had disjoint partial self borrows may stop being disjoint if the private fields they use get merged into one field. So if we added this feature, anytime you actually used it on two of your methods, your public API would be implicitly making a guarantee that the sets of fields borrowed by those two methods will always remain disjoint.

So, now that I’m aware of these complications, I’m not sure the feature really pulls its weight. I’m struggling to think of a use case where turning the “borrow regions” into actual public fields (possibly of wrapper types that hide exactly how many fields implement each “region”) is not a viable solution, and you can reasonably commit to those borrow regions remaining disjoint in all future compatible versions.

5 Likes