October 28, 2019
On 28.10.19 04:42, Walter Bright wrote:
> Thank you for posting this. I think it's the 4th scheme so far for D! We certainly have an embarrassment of riches.
> ...

Well, there are ideas. I just hope whatever ends up in the language is actually sound, doesn't cripple GC-based code and interoperates well with GC-based code.

> Personally, I've been making progress on a prototype of my scheme.

Great.

> It bears a lot of resemblance to yours.

So it is something other than @live?
October 28, 2019
On 10/28/2019 11:39 AM, Timon Gehr wrote:
> So it is something other than @live?

The prototype, no. I hope to release a prototype soon that works only with pointers in order to try out the data flow analysis and see how it goes. The pieces needed to make that work would be what any DFA system would need.

For example, root/bitarray is woefully inadequate.

Having a prototype gives us all something to play with and get comfortable with what works and what doesn't. I don't expect to be able to come up with a fully formed design without iteration.

The nice thing about @live is it will turn the system on for that function only, meaning it can co-exist with the rest of D code without risking disrupting it.
October 28, 2019
On 28.10.19 21:31, Walter Bright wrote:
> On 10/28/2019 11:39 AM, Timon Gehr wrote:
>> So it is something other than @live?
> 
> The prototype, no. I hope to release a prototype soon that works only with pointers in order to try out the data flow analysis and see how it goes. The pieces needed to make that work would be what any DFA system would need.
> 
> For example, root/bitarray is woefully inadequate.
> 
> Having a prototype gives us all something to play with and get comfortable with what works and what doesn't. I don't expect to be able to come up with a fully formed design without iteration.
> 
> The nice thing about @live is it will turn the system on for that function only, meaning it can co-exist with the rest of D code without risking disrupting it.

Fair enough.
October 28, 2019
On 28.10.19 00:10, ag0aep6g wrote:
> I think `@system` would be a better fit for restricting access.

Yes, probably.
October 28, 2019
On 28.10.19 00:40, rikki cattermole wrote:
> On 28/10/2019 11:36 AM, Timon Gehr wrote:
>> - The problem with `@trusted` is that it has no defense against `@safe` code destroying its invariants or accessing raw pointers that are only meant to be manipulated by `@trusted` code. There should therefore be a way to mark data as `@trusted` (or equivalent), such that `@safe` code can not access it.
> 
> This seems artificially restrictive for this proposal.
> However, we could instead split this off into its own DIP allowing attributes to act like visibility modifiers for variables.
> 
> I may not be convinced that this is required, but following it through to completion would be a good idea if its done at all.
> ...

Well, either we change the language or we change the way @safe is advertised. (You need to audit @trusted functions vs you need to audit each module that contains any @trusted function.)
October 29, 2019
On 28.10.19 02:26, jmh530 wrote:
> On Sunday, 27 October 2019 at 22:36:30 UTC, Timon Gehr wrote:
>> [snip]
>>
>> The main drawback of this proposal is that it doesn't separate control of lifetime and control of aliasing, doing so would however require adding another type qualifier and does not have precedent in Rust.
> 
> I'm a little confused by this. What type qualifier would need to be added and having what properties?

In the current language, `scope` only restricts lifetime. In particular, it is used to ensure addresses do not escape. What's missing is a way to ensure that there is either some number of `immutable` or exactly one mutable reference to your data, so with separate qualifiers you'd add a qualifier for that, leaving `scope` as-is. This would leave open the possibility to express functions that take multiple scoped references to the same location.

E.g., one major problem I see with following DIP 1021 to its logical conclusion is that you won't be able to easily express some standard idioms anymore, like swapping two entries of an array:

swap(a[i],a[j]); // error, a[i] and a[j] might alias

In a language where `scope` and `ref` do not _imply_ absence of mutable aliasing, you can still implement the `swap` function such that the code above compiles. I imagine the most annoying way the compiler error above will surface is if your algorithm actually guarantees that the two swapped values are different, but the compiler frontend cannot prove that this is the case.

Note that I don't necessarily like the direction that D is going with DIP 1021. I wrote the OP because Walter asked me to share my thoughts on borrowing and ownership on the newsgroup and I wanted to present something that is concrete enough (if I make proposals that are too abstract, Walter does not parse them) and compatible with the accepted DIP 1021.

For someone who is happy with writing @safe code using D's built-in GC, such restrictions will be quite off-putting.

However, Rust is in the same boat, see: https://stackoverflow.com/questions/28294735/how-to-swap-elements-of-array
For built-in slices, they work around the problem using a Go-esque type system restriction workaround, i.e., they express references as integers representing indices, and of course that only addresses this specific case.
October 29, 2019
On Monday, 28 October 2019 at 23:01:03 UTC, Timon Gehr wrote:
> [snip]

Thanks. That is clear.
October 29, 2019
On Monday, 28 October 2019 at 23:01:03 UTC, Timon Gehr wrote:
> Note that I don't necessarily like the direction that D is going with DIP 1021. I wrote the OP because Walter asked me to share my thoughts on borrowing and ownership on the newsgroup and I wanted to present something that is concrete enough (if I make proposals that are too abstract, Walter does not parse them) and compatible with the accepted DIP 1021.

It would be great to hear a different direction than the one with DIP 1021. But I understand that own time is precious, and now that DIP 1021 is here, it might be better to invest time to a more broadly discussed approach. (As Walter say, there is abundance of views, at least 4, and it would be great if the authors of the views talk to each other to shape a single direction for the good of D.)
October 29, 2019
On Monday, 28 October 2019 at 23:01:03 UTC, Timon Gehr wrote:
> [snip]
>
> In the current language, `scope` only restricts lifetime. In particular, it is used to ensure addresses do not escape. What's missing is a way to ensure that there is either some number of `immutable` or exactly one mutable reference to your data, so with separate qualifiers you'd add a qualifier for that, leaving `scope` as-is. This would leave open the possibility to express functions that take multiple scoped references to the same location.


I have some follow up comments after thinking about your reply.

One key thing about Rust's borrow checker is that even when you make a mutable borrow of mutable data, then you cannot modify the original data while the borrow is in effect. So for instance, the follow code does not compile in Rust

fn main() {
    let mut x = 1;
    let y = &mut x;
    x += 1;
    *y += 1;
    println!("{}", x);
}

You need to remove the line that `x += 1` for it to compile. The D version runs with no issues:

import std.stdio : writeln;

void main() {
    int x = 1;
    int* y = &x;
    x += 1;
    *y += 1;
    writeln(x);
}

So this "single mutable reference" that you discuss is not the same thing as saying there must be no more than one pointer to some variable. It's really that there is only one way to access some variable (perhaps similar to iso in Pony?). If you have a mutable pointer to the variable, then you cannot access it directly while the pointer is active.

Similarly, when Rust has an immutable borrow on mutable data, then it not only prevents mutable borrows of the same data but it also also prevents modifying the data directly. However, a D const pointer would still allow a variable to be changed through direct access if the data is mutable or through some other mutable pointer. Even if you dis-allow mutable pointers when there is a const pointer, a variable with const pointers to it would still be able to be changed through direct access.

So in this sense, not only would you need some type qualifier to ensure that you can either have one mutable pointer or many const pointers, but also you would need to ensure that there is no direct access to the underlying data when those pointers are valid. At least if you want to be consistent with Rust's approach.

For that reason, I would also not be surprised that whatever type qualifier you would favor would also need to either imply scope or be closely tied to scope somehow to guarantee safety. I don't know that for sure though.
October 31, 2019
On Sunday, 27 October 2019 at 22:36:30 UTC, Timon Gehr wrote:
> Improve `@trusted`:
>
> - The problem with `@trusted` is that it has no defense against `@safe` code destroying its invariants or accessing raw pointers that are only meant to be manipulated by `@trusted` code. There should therefore be a way to mark data as `@trusted` (or equivalent), such that `@safe` code can not access it.

I'm working on that:
https://github.com/dlang/DIPs/pull/179