News for hackers. Stuff that matters.
Re:Rust for C++ programmers – part 5: borrowed references by eq- on Tuesday May 06, 2014 @12:13PM (#7705346)
I wonder if there's a (simple syntactical) way to unlink the constness of unique pointers and their targets. It's not a huge obstruction, but seems like an unnecessary restriction not found in the near-equivalent C++ construction.
Re:Rust for C++ programmers – part 5: borrowed references by pcwalton on Tuesday May 06, 2014 @12:32PM (#7705467)
Yes, you can do it, with Cell and RefCell, though the former is restricted to POD types and the latter comes with some minor runtime overhead.

Inherited mutability is not an unnecessary restriction from the point of view of memory safety. It's critical to Rust's ability to prevent iterator invalidation and related bugs at compile time. The fact that C++ doesn't do it is the source of many of its memory safety problems, such as dangling references and iterator invalidation.

Re:Rust for C++ programmers – part 5: borrowed references by pohl on Tuesday May 06, 2014 @12:54PM (#7705626)
the former is restricted to POD types

I had to look this acronym up. In case anybody else needs a definition:

https://en.wikipedia.org/wiki/Plain_Old_Data_Structures

Re:Rust for C++ programmers – part 5: borrowed references by gilgoomesh on Tuesday May 06, 2014 @09:39PM (#7708179)
Within context (the article is for C++ programmers) POD is a commonly used acronym.

If you're a C++ programmer and don't know about POD types (data types with zero implicit C++ behaviors), you should brush up on your fundamentals – it's essential to understand when and why C++ behaviors (i.e. behaviors above and beyond plain C) are invoked implicitly.

Re:Rust for C++ programmers – part 5: borrowed references by Peaker on Tuesday May 06, 2014 @04:39PM (#7706944)
I was a bit surprised by the reverse:

  let x = 5
  let mut y = &x
If I understood correctly, x is immutable, but can still be mutated via (*y)?
Re:Rust for C++ programmers – part 5: borrowed references by pcwalton on Tuesday May 06, 2014 @04:40PM (#7706953)
No, that results in an error. Mutability doesn't inherit through references (`&`).
Re:Rust for C++ programmers – part 5: borrowed references by coderjames on Wednesday May 07, 2014 @10:58AM (#7710501)
[disclaimer: still learning Rust]

I believe it actually means that y can be made to reference something other than x.

  let x = 5
  let mut y = &x
  let i = 13
  y = &i
This is similar to C++'s const-pointers and pointers-to-consts, where either a pointer cannot be made to point at something different or the pointer cannot be used to change what it points at.
Re:Rust for C++ programmers – part 5: borrowed references by FreeFull on Wednesday May 07, 2014 @11:18AM (#7710630)
That actually lets you change what y points at, but you can't mutate x through y. If you want to mutate x, you need something like

    let y = &mut x;
which will result in an error due to x not being mutable.
Re:Rust for C++ programmers – part 5: borrowed references by steveklabnik on Tuesday May 06, 2014 @12:26PM (#7705423)
I'm not sure what you mean about unique pointers and const-ness. Can you explain? You can make unique pointers mutable:

    fn main() {
        let mut x = ~5;
        *x = *x + 1;
        println!("{:d}", *x);
    }
Or did you mean something else?
Re:Rust for C++ programmers – part 5: borrowed references by ndeine on Tuesday May 06, 2014 @01:13PM (#7705754)
He means immutability when he says "const-ness". There are four possibilities for mutability of a single pointer:

1. The pointer is mutable, but its contents are immutable.

2. The pointer is immutable, but its contents are mutable.

3. The pointer is immutable and the contents are immutable.

4. The pointer is mutable and its contents are mutable.

Right now for owned pointers Rust gives us (3) and (4), but no obvious way to achieve (1) and (2). Although you might argue that the borrowing semantics give us these powers, just not directly with owned pointers - which we shouldn't be using directly if we're asking for that control, we should be lending them out in a well-controlled manner.

Re:Rust for C++ programmers – part 5: borrowed references by pcwalton on Tuesday May 06, 2014 @01:20PM (#7705816)
You can use privacy for (1); admittedly it's a little hokey, but I feel it's not worth the added complexity to add field-level immutability directly into the language since you can use other language features to effectively achieve it. `std::cell::Cell` and `std::cell::RefCell` give you (2).
Re:Rust for C++ programmers – part 5: borrowed references by azth on Tuesday May 06, 2014 @05:03PM (#7707074)
> `std::cell::Cell` and `std::cell::RefCell` give you (2).

What advantages does (2) provide? Isn't it a potential source of errors?

Re:Rust for C++ programmers – part 5: borrowed references by pcwalton on Tuesday May 06, 2014 @06:33PM (#7707544)
It is, but sometimes you have to do it for practicality. Usually this comes up when people use `Rc<T>`, as that only supports immutable types (so any mutability you want needs to be in the form of `Cell`/`RefCell`).
Re:Rust for C++ programmers – part 5: borrowed references by azth on Tuesday May 06, 2014 @07:20PM (#7707755)
Would it be better to combine both types (e.g. a MutRc<T> type), and get rid of Cell/RefCell?
Re:Rust for C++ programmers – part 5: borrowed references by pcwalton on Tuesday May 06, 2014 @07:49PM (#7707854)
I don't think so, because then you'd get an overconservative iterator invalidation checker. For example:

    struct Foo {
        a: Vec<int>,
        b: Vec<int>,
    }

    let foo = Rc::new(RefCell::new(Foo::new(...)));
    for x in foo.borrow_mut().a.mut_iter() {
        for y in foo.borrow_mut().b.mut_iter() {
            // ^^^ FAILURE: a is already borrowed mutably
        }
    }
The failure happens because the RefCell is checking to make sure there are no two `&mut` references at the same time to `Foo`, to prevent iterator invalidation. But this is silly, because it only needs to prevent access to `a` while you're iterating over it, not both `a` and `b`. Changing the definition of `Foo` to this fixes the problem:

    struct Foo {
        a: RefCell<Vec<int>>,
        b: RefCell<Vec<int>>,
    }
Re:Rust for C++ programmers – part 5: borrowed references by azth on Tuesday May 06, 2014 @09:57PM (#7708220)
Makes sense. Though Cells would really stand out in the code as a potential for race conditions (unless you get a run time failure?). Thanks for the insight.
Re:Rust for C++ programmers – part 5: borrowed references by pcwalton on Wednesday May 07, 2014 @12:53AM (#7708657)
There is a special bound--Share--that is required on thread-safe data structures and forbids Cell/RefCell. The thread-safe equivalents of Cell and RefCell are Atomic and Mutex, respectively.
Re:Rust for C++ programmers – part 5: borrowed references by steveklabnik on Tuesday May 06, 2014 @01:15PM (#7705777)
Ahh, thank you. And yes, that's what I'd argue.
Re:Rust for C++ programmers – part 5: borrowed references by ben0x539 on Tuesday May 06, 2014 @12:29PM (#7705449)
I'm usually pretty happy that ~T works just like T in terms of ownership and mutability and move-semantics and whatnot. When would you want to unlink that?