4 ms·
> Putting “here’s the fields I’m borrowing in the body” into the signature, in order to conform with the Golden Rule, looks very odd. Do you mean something lik
by roarcher 4y ago
> Putting “here’s the fields I’m borrowing in the body” into the signature, in order to conform with the Golden Rule, looks very odd.
Do you mean something like this (using destructuring in arguments)?
struct Point {
x: i32,
y: i32,
}
impl Point {
pub fn x_mut(self { &mut x, .. }) -> &mut i32 {
&mut self.x
}
pub fn y_mut(self { &mut y, .. }) -> &mut i32 {
&mut self.y
}
impl Point {
pub fn calculate(&mut self) -> i32 {
let x = self.x_mut();
let y = self.y_mut();
*x * *y
}
}
}
I'd agree that it looks odd, but not very odd. Certainly there are odder syntaxes in Rust ;)
- steveklabnik 4y agoThat syntax is not valid Rust, though you're right it's sorta similar to destructuring. I wasn't thinking of it specifically, but of some of the sorta-proposed syntaxes by various folks in blog posts or on internals. And yeah, it's not insurmountable of an issue.
- roarcher 4y agoOh I know, it's just an idea of a possible syntax. Something like that might look a little funny but it doesn't seem too terrible to me. Anyway, thanks for the work you do on Rust! It's always my first choice of language when I have one.
- steveklabnik 4y agoYou're welcome, though I don't do any of that any more.
- bobbylarrybobby 4y agoYou can already kind of do this with `pub fn x_mut(Self { x, .. }: &mut Self) -> &mut i32`, but 1. Your function is no longer callable like p.x_mut(); you have to go through `Point::x_mut(p)` (seems kind of dumb that the first argument has to literally be called `self` and can't just be of type `Self`) 2. The compiler doesn't actually use the fact that you're ignoring the unspecified fields of `Self`, although it seems like that analysis should be trivial, given that rust already understands that `calculate(&mut point.x, &mut point.y)` isn't overlapping?
- roarcher 4y agoNow that I'm actually putting this code into an editor to try your suggestion, I'm noticing the embarrassing nested `impl Point`, which is sadly no longer editable. Oh, well. Test your code, kids. Is this what you had in mind? struct Point { x: i32, y: i32, } impl Point { pub fn x_mut(Self { x, .. }: &mut Self) -> &mut i32 { x } pub fn y_mut(Self { y, .. }: &mut Self) -> &mut i32 { y } pub fn calculate(&mut self) -> i32 { let x = Self::x_mut(self); let y = Self::y_mut(self); *x * *y } } The `self` on the second line of the `calculate` function still gets flagged with "cannot borrow `*self` as mutable more than once at a time", which I think is what you were talking about in your second point. I had no idea that the syntax above was actually valid in argument lists. Learned something new about Rust today.
- bobbylarrybobby 4y agoYep, that's the code I meant. And yeah I know it doesn't work, but it should! We've already done the partial borrow analysis for the compiler! Unfortunately the destructuring is only sugar and doesn't change what the borrow checker sees: two functions that each take a `&mut Self`.