Partial self borrowing syntax

Yeah, but you don't actually want to be forced to make your fields public. In any case, at this point we are walking right into a whole field of research about how best to specify which APIs can be composed with what -- i.e., you might like to be able to say things like "the method foo can be called in parallel with bar", without having to say what state they affect.

One way to do this that I personally pursued as part of my PhD is to partition the state abstractly, so that you can say "the method foo uses only the group of fields called "foo-fields", and bar uses the group of fields called bar-fields, and these are disjoint", without actually revealing your fields. But there have been many other approaches (and probably I was just reinventing someone else's prior work, at this point I don't recall too well the full catalog).

I've been happy that with Rust we've largely sidestepped this whole problem. I've usually found that if "abstract groups of fields" are needed, you can usually achieve the same effect by defining two fields whose types are structs with private fields:

  • foo: FooFields (and putting the method foo on there); and,
  • bar: BarFields (and putting the method bar on there

This sort of says the same thing but without needing complex language features. But it makes it annoying because you can't do self.foo() you must do self.foo.foo(). And sometimes these divisions are not so simple and clear (for example, maybe foo and bar are disjoint, but baz is only disjoint from bar but not from foo, and so forth...).

I wonder if there is a way to overcome some of this annoyingness (e.g., by "mirroring" the methods of foo from self such that self.foo() is syntactic sugar for self.foo.foo() or something).

Similarly, if I have to do some complex contract, one thing I occasionally (though rarely) do in my own code is to define a mirror structure that borrows fields. So imagine I have:

struct TheOwner {
    map: HashMap,
    vec: Vec
}

and I have some algorithm that writes to map but reads from vec. It might be defined on a struct:

impl TheOwner {
    fn algorithm(&mut self) {
        (TheAlgorithm { map: &mut self.map, vec: &self.vec }).go();
    }
}

struct TheAlgorithm<'algorithm> {
    map: &'algorithm mut HashMap,
    vec: &'algorithm Vec,
}

impl<'algorithm> TheAlgorithm<'algorithm> {
    fn go(&mut self) { ... }
}

This is annoying to define, but very flexible, and achieves the same effect as the inout, in categorizations.