October 02, 2020
On Friday, 2 October 2020 at 20:44:17 UTC, Per Nordlöw wrote:
> On Friday, 2 October 2020 at 14:08:29 UTC, Steven Schveighoffer wrote:
>> Compile without -preview=in, it prints:
>> ...
>> -Steve
>
> I wonder how Ada handles multiple aliasing of the same argument to a set of reference (`alias`) parameters [1]. Does it have the same ownership and borrowing rules as Rust? I need to check...

SPARK verifies that there is no aliasing with 'in out' and other parameters and globals IIRC

October 02, 2020
On Friday, 2 October 2020 at 14:08:29 UTC, Steven Schveighoffer wrote:
> Is there a way to prevent this?
>
> import std.stdio;
> struct S(size_t elems)
> {
>     int[elems] data;
> }
>
> void foo(T)(in T constdata, ref T normaldata)
> {
>     normaldata.data[0] = 1;
>     writeln(constdata.data[0]);
> }
> void main()
> {
>     S!1 smallval;
>     foo(smallval, smallval);
>     S!100 largeval;
>     foo(largeval, largeval);
> }
>
>
> Compile without -preview=in, it prints:
>
> 0
> 0
>
> Compile with -preview=in, it prints:
>
> 0
> 1
>
> -Steve

So what do we make of the following ?

```
import std.stdio;
struct S(size_t elems)
{
    int[elems] data;
    S copy () { return this; }
}

void foo(T)(auto ref T constdata, ref T normaldata)
{
    normaldata.data[0] = 1;
    writeln(constdata.data[0]);
}
void main()
{
    S!1 smallval;
    foo(smallval.copy, smallval);
    foo(smallval, smallval);
}
```

To me, the `in` approach is better. From the point of view of `foo`'s implementer, you get a stable `ref` or non-`ref` (not both!). You can also rely on it being `ref` if you know more about the type (e.g. if it has a destructor).
From the point of view of the caller, calling the function with the same values will always behave the same, no matter if you pass rvalues or lvalues.
October 02, 2020
On Friday, 2 October 2020 at 21:13:29 UTC, Mathias LANG wrote:
>
> To me, the `in` approach is better. From the point of view of `foo`'s implementer, you get a stable `ref` or non-`ref` (not both!). You can also rely on it being `ref` if you know more about the type (e.g. if it has a destructor).
> From the point of view of the caller, calling the function with the same values will always behave the same, no matter if you pass rvalues or lvalues.

I totally agree.

Also see the formally accepted DIP1021!
https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/accepted/DIP1021.md

"Therefore, if more than one reference to the same data is passed to a function, they must all be const."

October 02, 2020
On Friday, 2 October 2020 at 20:00:46 UTC, Ola Fosheim Grøstad wrote:
> Systems programming implies explicitness, this feature is the opposite.

Systems programming requires explicit control to be *available*. But, the programmer shouldn't be *forced* to explicitly specify every tedious detail to get the desired result.
October 02, 2020
On 10/2/2020 7:32 AM, Andrei Alexandrescu wrote:
> Finally, my "told you so" moment has come! :o)
> 
> https://forum.dlang.org/post/rhmst4$1vmc$1@digitalmars.com

This should be diagnosed by -preview=dip1021. However, #dip1021 will only stop the obvious cases of it. It can be more subtle, which can only be stopped by @live.

https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md
October 02, 2020
On 10/2/2020 10:31 AM, Steven Schveighoffer wrote:
> And this might not be true on a different compiler.

This is looking like a serious problem.
October 02, 2020
On Friday, 2 October 2020 at 21:57:06 UTC, Daniel N wrote:
> "Therefore, if more than one reference to the same data is passed to a function, they must all be const."

Impossible to prove at compiletime in the general case.

Way too expensive to check at runtime as well as the aliasing can happen deep down in a graph.

So you need to specify it as undefined behaviour.



October 02, 2020
On Friday, 2 October 2020 at 22:11:01 UTC, Walter Bright wrote:
> On 10/2/2020 10:31 AM, Steven Schveighoffer wrote:
>> And this might not be true on a different compiler.
>
> This is looking like a serious problem.

It might be. We need to look into this, and once and for all come to a conclusion.
October 02, 2020
On Friday, 2 October 2020 at 22:04:14 UTC, tsbockman wrote:
> On Friday, 2 October 2020 at 20:00:46 UTC, Ola Fosheim Grøstad wrote:
>> Systems programming implies explicitness, this feature is the opposite.
>
> Systems programming requires explicit control to be *available*. But, the programmer shouldn't be *forced* to explicitly specify every tedious detail to get the desired result.

Yes, but if you want passbyvalue for small structs all the time then you need to define enabling constraints as udefined behaviour.

The only viable alternative is to only get the optimization when it provably has the same effect.

Those are the only possible options (even in theory).

October 02, 2020
On Friday, 2 October 2020 at 22:27:33 UTC, Ola Fosheim Grøstad wrote:
> Yes, but if you want passbyvalue for small structs all the time then you need to define enabling constraints as udefined behaviour.

That's fine. I never suggested otherwise.

> The only viable alternative is to only get the optimization when it provably has the same effect.

As I said earlier in this thread, if people are very worried about the undefined behavior, then perhaps the cases which are not proven by the compiler to have the same effect should be @system. There are essential features in D already that cannot be verified by the compiler; that's what @system is for.