Hacker News new | ask | show | jobs
by kibwen 296 days ago
> In any language, when we hand a function a reference to an object, that function can't destroy the object, nor change its type

This isn't quite true. While Rust doesn't currently support this, people have proposed the concept of `&own` references that take ownership of the object and free it when the reference goes out of scope (consider that Rust's standard destructor signature, `fn drop(&mut)`, should probably take one of these hypothetical owning references). I addition, I believe that languages with typestate can cause types to change as a result of function calls, although I don't quite understand the details.

5 comments

Intriguing, what would be the purpose of such owning references compared to just passing ownership? Is that to have a way to reliably avoid memcopying large objects when passing them by value?
> Is that to have a way to reliably avoid memcopying large objects when passing them by value?

I believe so, yes. Currently the only way to transfer ownership is by-value, and LLVM might optimize away the memcpy, but also it might not.

I wonder what is the case when you cannot optimize away memcpy, but can work around it with an "owning reference"?
Great point =) That's true for a lot of languages (including Mojo too), so I should have said "non-owning reference" there. I'll update the post to clarify. Thanks for catching that!
I don't understand your comment. `drop` takes a *mutable* reference. But by default, references in Rust are immutable.
shared references are immutable in Rust, mut references and shared references are both references.
Kibwen is saying that there was an idea to have `fn drop(&mut x)` from Drop trait become `fn drop_own(&own x)`. Then `&own` would do mutation and drop the owner of the reference. A regular &mut reference shouldn't do that outside of `drop(&mut x)`.
Drop takes an object itself ("owned reference"), as I remember. Mutable ref allows reading/writing but not destroying or passing the ownership.

Owner = can read/write/destroy

Mutable ref = can read/write

Immutable ref = can only read, guarantered not to change

That's the destructor function, that is written by you and called by Rust before actually destroying something. The function that you want to look at is [1].

If you read the docs at your link it even says:

> This method is called implicitly when the value goes out of scope, and cannot be called explicitly (this is compiler error E0040).

> However, the mem::drop function in the prelude can be used to call the argument’s Drop implementation.

By the way the implementation of the function drop is just an empty function [2]; that's enough as local variables are destroyed on function return.

Mutable reference is a "borrow" which means you take a value from an owner and promise to return it back, and you cannot destroy a thing that you must return.

[1] https://doc.rust-lang.org/std/mem/fn.drop.html

[2] https://doc.rust-lang.org/src/core/mem/mod.rs.html#957

The drop function being talked about here is the one I pointed to, not the one you pointed to. The Drop trait is built into the language (as a lang item), std::mem::drop is just a regular old function.
The drop that you mention doesn't free memory, as I understand, it is called before actually destroying object's memory.
> I believe that languages with typestate can cause types to change as a result of function calls

Do you have any specific languages?

I've only heard of this concept in academic languages, I don't feel knowledgeable enough to recommend any specific one. In terms of mainstream languages, I think an analogous concept is the use-before-initialization analysis that languages like Rust employ, e.g. if I have a variable defined like this:

    let x: u8;
I can't actually do anything with this variable:

    foo(x); // error
Except I can apply the initialization operator:

    x = 42;
And now I can do things with this variable as usual.

But consider that the type of x hasn't changed as a result of the initialization. Beforehand it was a u8, and afterward it was still a u8, and yet something about the state of the variable changed my ability to use it in various contexts. I believe that typestate is something like this, generalized to allow variables to flow through states (like a compile-time state machine) to ensure that things happen in the correct order.

An &own reference seems like it would just be equivalent to a Box.
Box heap allocates, references do not.
> `&own` references that take ownership of the object and free it when the reference goes out of scope

How can you free something if it's not allocated

Sorry, yeah that phrasing was bad: I kinda think an "owning reference" is a contradiction in terms but I didn't come up with the idea.

What I meant was, creating a box creates a new allocation, whereas my understanding of &own would take over an existing allocation.