Hacker News new | past | comments | ask | show | jobs | submit login

This is a complex topic, but what it boils down to is that the function signature is the API. If you borrow the whole thing, you borrow the whole thing, not disjoint parts of it.

This is also why it's okay in the body of a single function; that doesn't impact a boundary.

We'll see what happens in the future.




My preferred solution to this is to make partial borrows part of the method definition syntax to make it clear this is part of the external contract of your API. Also I lean towards mimicking the arbitrary self type syntax and land on something along the lines of

  impl Foo {
      fn bar(self: Foo { ref a, mut ref b, .. }) {}
  }
Where that signature tells the borrow checker that those two fields are the only ones being accessed. Nowadays this method would have to be &mut self, which heavily restrict more complex compositions, as mentioned in this thread.


On one hand this looks/feels absolutely useful and kind of "must have" feature, yet the boilerplate seems excessive. But at the same time it's absolutely something that should be described somewhere as metadata for a function. It seems to me this should be something that the compiler figures out and mostly elides, like lifetimes. (But this should be present as part of API, should be easily discoverable, should be there at compile time when linking against crates, etc.)


The problem with having the compiler figure it out is that the signature now becomes dependent on implementation details that can't be seen from the signature, and could be accidentally changed. This information must be an explicit part of the signature, so that it's properly visible and spells out what the function can do without having to read the body.

That said, I think putting it in the argument list like that is a terrible idea. It would add far too much clutter. What if it was put into the where section, sort of like this:

  impl Foo {
      fn bar(&mut self, other_param: &Data)
        where self: borrows{ a, b, .. },
              other_param: borrows{ a, b, ..},
      {
        // Function body
      }
  }
In one sense, it sort of fits because it's providing a "bounds" of sorts on how the reference can be used, similar to the way a trait bound would for a type. If no reference binding is provided it would default to borrowing all the fields, which is the current behaviour.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: