6 ms·
> The point is that Rust's borrow checker can't reason about lifetimes very well over function boundaries. It can reason about coarse things that are expressabl
by dunkelheit 7y ago
> The point is that Rust's borrow checker can't reason about lifetimes very well over function boundaries. It can reason about coarse things that are expressable in the type language, but everything more nuanced than that, such as reasoning about how control flow affects the lifetimes is limited to inside function bodies.
BTW this is a big pain point for me (unrelated to async). Code like this:
let ref = &mut self.field;
self.helper_mutating_another_field();
do_something(ref);
gets rejected because self.helper_mutating_another_field() will mutably borrow the whole struct. The workaround is either to inline the helper or factor out a smaller substruct so that helper can borrow that which doesn't always look good.
Of course it is preferable that all information needed for the caller to check if the call is correct is contained in the function signature but it truly is frustrating to see the function body right there, know that it doesn't violate borrowing rules and still get the code calling it rejected.
- steveklabnik 7y agoIt's really tricky; there's a tension here between just making your code work, and not making it brittle to further modification.
- entropicdrifter 7y agoCouldn't you just pass in the (other) borrowed field as an argument for the function? If you need it to work without adding the argument when called outside of the class, you could overload it with a version that borrows the field and passes it to the version that takes the field as an argument, right? I'm newish to Rust, so this is just an intuitive guess. Please let me know if I'm wrong.
- Rusky 7y agoYes, that's the usual workaround.
- dunkelheit 7y agoYes, it works, but feels unnatural. I also don't like the possibility (quite remote, I admit) that the function gets called with a field from another instance.
- esotericn 7y agoThe latter case should be impossible if the method is private?
- saghm 7y agoIn Rust, privacy isn't enforced like that. Private just means that things outside the module can't access them. There's no concept of privacy at the instance level.
- esotericn 7y agoYes. So don't make any methods that could potentially be passed incorrect arguments public.
- saghm 7y agoThat still doesn't preclude the possibility that within the module the function gets called with a field from another instance. I think the idea is that by making it a method that just takes a reference to self, it's impossible to accidentally mutate a field on a different instance, while taking a reference to the field itself doesn't prevent the programmer from accidentally calling it with the wrong instance of the field.
- rom1v 7y agoYes, encapsulation sometimes conflicts with the borrowing rules. After all, this is not so surprising: enforcing the borrowing rules requires to follow every concrete access to resources, while encapsulation aims to abstract them away.