But I think this one can be fixed "simply" by considering *value to be it's own place lockable (and adding more rules that make "brief" borrows in various places). Early drafts of part 2 originally did this but I removed it when I couldn't see the point.
...oddly enough, I'm beginning to think that there's a similar solution to the other problem. I think that, bizarrely, the solution may be to add support for disjoint field access. The point being, if we had separate lockables for fields, and also tracked held locks at that same level of granularity, then the borrow checker would know what *(some.arbtirary).path could modify.
It'd be interesting to see if lifetimes and the above are both district and equally legitimate ways of solving the same problems!
I have a hard time convincing myself, though! Coming up with the right rules for brief locks and deinitialization of fields sounds tricky and I'd have a hard time trusting that they are correct without actually implementing the borrow checker.
I recall coming across an RFC that was closed regarding this possibility. If I recall correctly, the RFC was closed because it was determined that disjoint borrowing doesn't buy you anything you couldn't otherwise do through appropriate mutator methods or by combining groups of fields into sub-structures and making the member that contains that structure public (or providing an accessor for that sub-structure).
Well, 'static + 'a means the same thing as 'static, but it's just a compiler bug. Really, the compiler's suggestion should simply be 'a.
I recall coming across an RFC that was closed regarding this possibility.
Rust has the functionality I'm talking about. It is simply that my borrow checker does not support it, because the rules were obscenely obnoxious to define.
let mut tuple = (1, 2);
let a = &mut tuple.0;
let b = &mut tuple.1; // the borrow checker in Part 2 will reject this
Part three is coming excruciatingly slowly, by the way. Fixing either one of the two examples I ran into requires specifying a whole lot of details that I didn't want to ever have to specify, and I basically can't trust anything I write anymore without actually implementing it.
Problem is, I've never written a static analysis tool quite like this before, so I hardly even know where to start!
I could perhaps just say what I originally wanted to say in Part 3, and leave the question of "how far can you REALLY go without lifetimes?" to somebody far more skilled than I...
This one went through so many iterations! First it was all about functions; then it tried to handle both the invariance and reborrowing examples...
...but I wasn't really satisfied with it until I finally I decided to try focusing entirely on the reborrowing example first. Suddenly, all the puzzle pieces seemed to click into one nice whole, and I even discovered a surprising aspect of &T/&mut T that I've never really honestly thought about before! (tl;dr: they're special)
V gubhtug V jnf fcrpvny ng yrnfg &G naq &zhg G trg gb or fcrpvny!
This is a great continuation, and I don't see any holes yet. Obviously, this is going to effectively end up putting the borrow information into types (to handle in/variance and function barriors cleanly), but I wonder just how far you can get without explicit lifetimes.
Actually, wait, how is in/variance even something that you have to worry about in the lockables model? Variance is about lifetime variance, so without lifetimes, where does variance come into play? Is it "changing" the locks held by a lockable? (I don't understand variance to do anything other than understand the compiler's errors it seems)
Actually, wait, how is in/variance even something that you have to worry about in the lockables model?
You are right; it's not that we need to worry about variance. It's simply that we need to worry about those same examples which are traditionally fixed by invariance. (i.e. bad_extension). I tried to be careful to always use the phrase "invariance example" rather than just "invariance"!
Indeed, the fix planned for them has nothing to do with invariance, and, like you say, will involve somehow updating the set of locks held by a value after it is created.
This one is big. Big as in big revelations... and it's also quite long! (There's a reason for this, as you'll see...) So pull up a chair, because we're finally adding lifetime annotations.
Reading previous parts (except Part 2) is not required! Now is a good a time as any to start!
Honestly, sometimes it's hard to remember whether I'm writing a blog or a textbook! There are too many cool aspects to cover and not everything can get the spotlight that I feel it deserves...