October 02, 2020
On 10/2/20 6:11 PM, 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.

I was wrong about this case, because it's a dynamic array (which is specifically carved out as an exception). Indeed, there seem to be quite a few exceptions carved out, presumably to make existing code behave reasonably.

But this could be true for another type that isn't in the exception categories. Potentially, a compiler can decide to make the following not true, while others say it is true:

alias A = void delegate(in long);
alias B = void delegate(const long);

static assert(is(A : B));

-Steve
October 02, 2020
On Friday, 2 October 2020 at 22:46:11 UTC, tsbockman wrote:
> On Friday, 2 October 2020 at 22:27:33 UTC, Ola Fosheim Grøstad wrote:
> 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.

I have no issues with undefined behaviour as long as it is easy to understand and explain, like requiring 'in' params to be nonaliased in the function body. It has to be easy to grok and remember.

However the D community tends to want D to distinguish itself from c++ in this regard.





October 02, 2020
On 10/2/2020 4:03 PM, Steven Schveighoffer wrote:
> On 10/2/20 6:11 PM, 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.
> 
> I was wrong about this case, because it's a dynamic array (which is specifically carved out as an exception). Indeed, there seem to be quite a few exceptions carved out, presumably to make existing code behave reasonably.

Having a struct wrap a dynamic array comes to mind:

    struct A { int[] a; }

vs:

    int[] b;

Having these have different function calling ABIs is something I've tried to avoid. I.e. a wrapped type should have the same ABI as the type. Before this, it was true.

> 
> But this could be true for another type that isn't in the exception categories. Potentially, a compiler can decide to make the following not true, while others say it is true:
> 
> alias A = void delegate(in long);
> alias B = void delegate(const long);
> 
> static assert(is(A : B));

It's not looking good.
October 03, 2020
On Friday, 2 October 2020 at 23:03:49 UTC, Ola Fosheim Grøstad wrote:
>
> I have no issues with undefined behaviour as long as it is easy to understand and explain, like requiring 'in' params to be nonaliased in the function body. It has to be easy to grok and remember.

Or the even simpler rule: don't use 'in' :)
October 03, 2020
On 10/2/20 6:11 PM, 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.

They say one should choose one's fights wisely, so I spent some time
pondering. I could just let this thread scroll by and not think twice
about it. By next week, I may as well forget.

But then I realized this is /exactly/ the kind of crap that we'll all
scratch our heads six months from now, "How did this ever pass review?
Who approved this? How in the world did a group of competent,
well-intended people, looked at this and said - yep, good idea. Let's."

???

This glib take is EXTREMELY concerning:

> In the general case, no. You can have two distinct pointers with the
> same value, and there's nothing the frontend can do to detect it.
> 
> This scenario has been brought up during the review. I doubt it will,
> in practice, be an issue though. This is not a common pattern, nor
> does it seems useful. It rather looks like a code smell.

Wait a SECOND! Are we really in the market of developing and deploying language features that come unglued at the slightest and subtlest misuse? We most certainly shouldn't.

I sincerely congratulated Mathias and the other participants for working on this. It's an important topic. Knowing that all those involved are very good at what they do, and without having looked closely, I was sure they got something really nice going that avoids this absolutely blatant semantic grenade. And now I see this is exactly it - we got a -preview of a grenade. How is this possible? How can we sleep at night now?

Again: take a step back and reconsider, why did this pass muster?

This is important, folks. It's really important as parameter passing goes to the core of what the virtual machine does. You can't say, meh, let's just fudge it here, and whatever is surprising it's on the user.

Please, we really need to put back the toothpaste in the tube here. I could on everybody's clear head here to reconsider this.
October 03, 2020
On 2020-10-03 01:03, Steven Schveighoffer wrote:

> But this could be true for another type that isn't in the exception categories. Potentially, a compiler can decide to make the following not true, while others say it is true:
> 
> alias A = void delegate(in long);
> alias B = void delegate(const long);
> 
> static assert(is(A : B));

FYI, same problem with `__traits(isReturnOnStack)` [1].

[1] https://dlang.org/spec/traits.html#isReturnOnStack

-- 
/Jacob Carlborg
October 03, 2020
On Saturday, 3 October 2020 at 05:02:36 UTC, Andrei Alexandrescu wrote:
> On 10/2/20 6:11 PM, Walter Bright wrote:
>> [...]
>
> They say one should choose one's fights wisely, so I spent some time
> pondering. I could just let this thread scroll by and not think twice
> about it. By next week, I may as well forget.
>
> [...]

This. We have to be more stringent
October 03, 2020
On Friday, 2 October 2020 at 23:03:49 UTC, Ola Fosheim Grøstad wrote:
> On Friday, 2 October 2020 at 22:46:11 UTC, tsbockman wrote:
>> On Friday, 2 October 2020 at 22:27:33 UTC, Ola Fosheim Grøstad wrote:
>> 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.
>
> I have no issues with undefined behaviour as long as it is easy to understand and explain, like requiring 'in' params to be nonaliased in the function body. It has to be easy to grok and remember.
>
> However the D community tends to want D to distinguish itself from c++ in this regard.

How about this?

You can freely mix any number of 'in' and 'out' parameters and keep the optimized behavior.

As soon as you add any 'ref' parameter 'in' will pass by value.

October 03, 2020
On 02.10.20 22:06, Steven Schveighoffer wrote:
> On 10/2/20 3:54 PM, tsbockman wrote:
>> On Friday, 2 October 2020 at 14:48:18 UTC, Steven Schveighoffer wrote:
>>> I think in should always mean ref. If you want to pass not by ref, use const.
>>
>> Please do not kill this optimization. There is currently no other reasonable way available in the D language to express the idea of "pass by reference or by value, whichever is faster". But, there is an easy way to require that a parameter always be passed in a specific way: just don't use `in` and use `scope const` or `scope const ref` directly.
>>
>> Implementing this optimization manually is quite painful in D; the possibilities are complex and very ugly, and require detailed knowledge of the platform's ABI to implement correctly in the general case.
>>
>> D is a systems programming language, and should not kill useful features just because they have potential pitfalls. At most, problematic features may be blocked by @safe/linters/style guides, but please don't remove them entirely.
> 
> The only way this feature can stay the way it is is to add to the undefined behavior of the language:
> ...

No. UB means demons may fly out of your nose. It's not that. You just get one of two behaviors, one is pass-by-reference, the other is pass-by-value.

> "It is undefined behavior to pass a mutable argument to an `in` parameter, and to read from that parameter after that mutable data has been modified while executing the function."
> 
> If everyone is OK with that, then it can stay the way it is. Otherwise, the spec has to be more specific about whether it's expected to be ref or not ref.
> 
> -Steve

There's a difference between "the behavior may be either A or B" and "the behavior may be anything you like"...
October 03, 2020
On Saturday, 3 October 2020 at 05:02:36 UTC, Andrei Alexandrescu wrote:
> [...]
>
> Wait a SECOND! Are we really in the market of developing and deploying language features that come unglued at the slightest and subtlest misuse? We most certainly shouldn't.

I agree. What I don't agree with is that this aliasing is a "slight and subtle misuse". I went through the 64 projects and their dependencies that are on Buildkite, and didn't see a hint of this pattern emerging. Nor did it in any other code I've surveyed in the almost 5 months the PR was open.

> I sincerely congratulated Mathias and the other participants for working on this. It's an important topic. Knowing that all those involved are very good at what they do, and without having looked closely, I was sure they got something really nice going that avoids this absolutely blatant semantic grenade. And now I see this is exactly it - we got a -preview of a grenade. How is this possible? How can we sleep at night now?
>
> Again: take a step back and reconsider, why did this pass muster?

Maybe because the people that want to use this actually know this is nowhere near as big of an issue as some people try to make it look.

Also because some of the criticism is based on the rather loose definition of the promotion to value at the moment. That definition is intentionally loose, not because it needs to be, but because the feature is in `-preview` and the rules need to take into account all platforms that D support, something that cannot be done in DMD alone.

> This is important, folks. It's really important as parameter passing goes to the core of what the virtual machine does. You can't say, meh, let's just fudge it here, and whatever is surprising it's on the user.
>
> Please, we really need to put back the toothpaste in the tube here. I could on everybody's clear head here to reconsider this.

Perhaps you don't know this, but the very first implementation, the one I had when I opened the PR on April 3rd actually always used `ref`. It had quite a few issues. @Kinke suggested an alternative, and that alternative brought many benefits with it, for a very minor downside, which can easily be mitigated: if your function's semantic really depend on mutation through an alias propagating (or not) to an `in` parameter, then you can use `__traits(isRef, paramname)` to check it.
Later on, on July 31st, I brought the topic to the forum, which pressed on another suggestion @Kinke has made, using the full function type instead of just the parameter type. At the time, you also made mention of this issue, and it was considered.

I wonder, did you try to adapt one of your projects to `in` ? Not merely throwing the switch, but also adding a couple `in` here and there, were it makes sense.

Not that this `-preview` is the only one that has ever been usable from release day (perhaps `markdown` was as well, but it only affected documentation generation). All the other previews would fail on your project because druntime and Phobos were never adapted after the switch was merged. `-preview=in` not only works with druntime/phobos, but many libraries from Buildkite were also adapted to work with or without it (https://github.com/dlang/dmd/pull/11632). I was expecting this would increase user engagement, allow to gather feedback, use cases, and lead to a healthy discussion, just like it allowed to refine the implementation. But I wasn't expecting FUD to be spread over a `-preview` before people even tried it.