On Friday, 27 May 2016 at 11:50:42 UTC, Marc Schütz wrote:
On Friday, 27 May 2016 at 10:04:14 UTC, Nick Treleaven wrote:
On Thursday, 26 May 2016 at 08:29:41 UTC, Marc Schütz wrote:

RCArray!int arr = [7];
ref r = arr[0];
arr = [9];        // this releases the old array
r++;              // use after free
...
statically prevent the above from compiling using:

RCArray(T) {
    ...
    ref opIndex(size_t) return;

Local refs cannot be assigned from a function returning ref if that function has any parameters marked with the return attribute. If there is no attribute, local refs + function returning ref is OK.

Huh? `return` means that the returned reference is owned by the RCArray struct and must therefore not outlive it. If the RCArray is a local variable (or parameter), the local ref is always declared after it (because it must be initialized immediately), and will have a shorter scope than the RCArray. Therefore, such an assignment is always accepted.

What about if the RCArray (of ref count 1) is assigned to a different one after the local ref is initialised? That is what we're discussing -it's your example above(!)

It can be solved in one of two ways: Either by making the owner (`arr`) non-mutable during the existence of the references, thereby forbidding the call to `bar()` (I would prefer this one, as it's cleaner and can be used for many more things, e.g. the byLine problem)

I don't see directly how this affects byLine.front, that does not return a reference.

It returns a reference in the wider sense, namely a slice to a private buffer that gets overwritten by each call to `byLine`. Currently, DIP25 only applies to `ref`s in the narrow sense, but I'm assuming it will be generalized to include pointer, slices, class references, AAs and hidden context pointers.

Making the ByLine range constant as long as there's a reference to its buffer would prevent surprises like this:

    auto lines = stdin.byLine.array;
// => all elements of `lines` are the same, should have used `byLineCopy`

So your solution would statically prevent popFront because front has escaped. I think we should just prevent front from escaping.


Reply via email to