←back to thread

451 points birdculture | 3 comments | | HN request time: 0.221s | source
Show context
Animats ◴[] No.43979394[source]
It's like reading "A Discipline of Programming", by Dijkstra. That morality play approach was needed back then, because nobody knew how to think about this stuff.

Most explanations of ownership in Rust are far too wordy. See [1]. The core concepts are mostly there, but hidden under all the examples.

    - Each data object in Rust has exactly one owner.
      - Ownership can be transferred in ways that preserve the one-owner rule.
      - If you need multiple ownership, the real owner has to be a reference-counted cell. 
        Those cells can be cloned (duplicated.)
      - If the owner goes away, so do the things it owns.

    - You can borrow access to a data object using a reference. 
      - There's a big distinction between owning and referencing.
      - References can be passed around and stored, but cannot outlive the object.
        (That would be a "dangling pointer" error).
      - This is strictly enforced at compile time by the borrow checker.
That explains the model. Once that's understood, all the details can be tied back to those rules.

[1] https://doc.rust-lang.org/book/ch04-01-what-is-ownership.htm...

replies(17): >>43979460 #>>43979907 #>>43980199 #>>43981064 #>>43981313 #>>43981587 #>>43981720 #>>43982074 #>>43982249 #>>43982619 #>>43982747 #>>43983156 #>>43984730 #>>43988460 #>>43990363 #>>43996196 #>>44008391 #
frankie_t ◴[] No.43982619[source]
Maybe it's my learning limitations, but I find it hard to follow explanations like these. I had similar feelings about encapsulation explanations: it would say I can hide information without going into much detail. Why, from whom? How is it hiding if I can _see it on my screen_.

Similarly here, I can't understand for example _who_ is the owner. Is it a stack frame? Why would a stack frame want to move ownership to its callee, when by the nature of LIFO the callee stack will always be destroyed first, so there is no danger in hanging to it until callee returns. Is it for optimization, so that we can get rid of the object sooner? Could owner be something else than a stack frame? Why can mutable reference be only handed out once? If I'm only using a single thread, one function is guaranteed to finish before the other starts, so what is the harm in handing mutable references to both? Just slap my hands when I'm actually using multiple threads.

Of course, there are reasons for all of these things and they probably are not even that hard to understand. Somehow, every time I want to get into Rust I start chasing these things and give up a bit later.

replies(7): >>43983021 #>>43983228 #>>43983276 #>>43983536 #>>43985111 #>>43988282 #>>43991211 #
kibwen ◴[] No.43983021[source]
> Why can mutable reference be only handed out once?

Here's a single-threaded program which would exhibit dangling pointers if Rust allowed handing out multiple references (mutable or otherwise) to data that's being mutated:

    let mut v = Vec::new();
    v.push(42);
    
    // Address of first element: 0x6533c883fb10
    println!("{:p}", &v[0]);
    
    // Put something after v on the heap
    // so it can't be grown in-place
    let v2 = v.clone();
    
    v.push(43);
    v.push(44);
    v.push(45);
    // Exceed capacity and trigger reallocation
    v.push(46);
    
    // New address of first element: 0x6533c883fb50
    println!("{:p}", &v[0]);
replies(2): >>43988334 #>>43989574 #
1. Someone ◴[] No.43989574[source]
> // Put something after v on the heap

> // so it can't be grown in-place

> let v2 = v.clone();

I doubt rust guarantees that “Put something after v on the heap” behavior.

The whole idea of a heap is that you give up control over where allocations happen in exchange for an easy way to allocate, free and reuse memory.

replies(2): >>43989757 #>>43993920 #
2. steveklabnik ◴[] No.43989757[source]
That’s correct.
3. kibwen ◴[] No.43993920[source]
It certainly doesn't guarantee it, this is just what's needed to induce a relocation in this particular instance. But this makes Rust's ownership tracking even more important, because it would be trivial for this to "accidentally work" in something like C++, only for it to explode as soon as any future change either perturbs the heap or pushes enough items to the vec that a relocation is suddenly triggered.