October 02, 2020
On 10/2/20 2:33 PM, Ola Fosheim Grøstad wrote:
> On Friday, 2 October 2020 at 17:31:06 UTC, Steven Schveighoffer wrote:
>> Yes, the problem is the "sometimes ref". Because ref changes the semantics.
>>
>> I read it as, in means by ref, unless the compiler can prove it's the same to pass by value, and that is more efficient. But if it's for *optimization*, it shouldn't change the effective semantics. The optimizer should be invisible.
>>
>> In practice, I don't think the compiler can prove that.
> 
> A good backend most certainly can? This ought to be a pure backend issue and not affect the fontend at all if the separation front/back is as it should be.

How does the compiler prove that passing by value or by reference is not going to affect the resulting code? I mean, it could potentially say, there are no references in all the mutable parameters, and so I can pass by value. But that's kind of a wide net.

> 
> Calling conventions do not belong in a language spec...
> 

You mean by ref or by value isn't part of the language spec? I don't understand the point.

-Steve

October 02, 2020
On Friday, 2 October 2020 at 19:03:52 UTC, Steven Schveighoffer wrote:
> On 10/2/20 2:33 PM, Ola Fosheim Grøstad wrote:
> How does the compiler prove that passing by value or by reference is not going to affect the resulting code? I mean, it could potentially say, there are no references in all the mutable parameters, and so I can pass by value. But that's kind of a wide net.

It can do bookeeping of how one param can influence another.
If you have potential aliasing you can analyse if the affected const ref is read after a mutation is possible. If it is read before then there is no issue.

It may track ownership intenally and determine that the reference is isolated (the only one). Then track it as if it is effectively immutable.

> You mean by ref or by value isn't part of the language spec? I don't understand the point.

The spec should list undefined behaviour and required observable effects, but not parameter passing strategies.

You can call something pass-by-value, but the compiler can still pass a reference as long as it cannot be observed unless undefined behaviour has been triggered by the programmer (by stepping outside the language).

October 02, 2020
On 10/2/20 3:20 PM, Ola Fosheim Grøstad wrote:

> You can call something pass-by-value, but the compiler can still pass a reference as long as it cannot be observed unless undefined behaviour has been triggered by the programmer (by stepping outside the language).
> 

That's just the thing. The -preview=in feature does not define whether the parameter is pass by value or by reference. It says, "up to the compiler".

So code will work differently on different compilers.

I should be able to expect one behavior, and then if the compiler can pass the parameter differently but I can't tell, then that's fine. But this isn't that.

-Steve
October 02, 2020
On Friday, 2 October 2020 at 18:31:20 UTC, Per Nordlöw wrote:
> On Friday, 2 October 2020 at 17:16:46 UTC, Max Haughton wrote:
>> Could we be ambitious and aim to have ownership taken to the max and catch this statically? This particular case is relatively low hanging fruit but having the in parameter work this way would be nice if it was safe.
>
> For which parameter types should such ownership checking be performed?
>
> All kinds of references types including ref params, classes and pointers or a subset of them?

I think for any scheme to be successful it would have to (within @safe code) have to cover pretty much everything, from the parameter all the way up to the allocation (be that a class, pointer to struct etc.). A more limited ownership system could still be very useful (what exists now is getting there) but to *guarantee* safety it must go further.

Obviously this would be a huge task - not impossible (we have some very clever people) but big - but if it happens at some point it would need to be very thoroughly planned i.e. from the "basics" like how to handle malloc and free (or your allocator of choice) to the more subtle issues like where to make the surgical cuts to the languages design - D only sort of has move semantics at the moment, which (recall that assignment in rust is move by default) at a glance make a provably safe system more difficult (especially wrt types that own pointers I think).

On a more meta level I think dmd needs to be carefully structured to separate the AST from the analysis. I'm aware that talk is cheap, but it could get very ugly if done wrong .




October 02, 2020
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.
October 02, 2020
On Friday, 2 October 2020 at 19:37:43 UTC, Steven Schveighoffer wrote:
> On 10/2/20 3:20 PM, Ola Fosheim Grøstad wrote:
> That's just the thing. The -preview=in feature does not define whether the parameter is pass by value or by reference. It says, "up to the compiler".

Yes, I agree with you. The language spec should stick to the proper theoretical concept, e.g. pass by reference. It could also require no-aliasing of in-parameters and define aliasing as undefined behaviour that the compiler may or may not detect.

Disallowing aliasing can give better codegen (faster).

Then it could put in a footnote that some compilers optimize such and such as values in registers ( for those that read disassembled code ), but it should be no more than a footnote.

> I should be able to expect one behavior, and then if the compiler can pass the parameter differently but I can't tell, then that's fine. But this isn't that.

True.


October 02, 2020
On Friday, 2 October 2020 at 19:54:35 UTC, tsbockman wrote:
> On Friday, 2 October 2020 at 14:48:18 UTC, Steven Schveighoffer wrote:
> D is a systems programming language, and should not kill useful features just because they have potential pitfalls.

Systems programming implies explicitness, this feature is the opposite.




October 02, 2020
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:

"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
October 02, 2020
On 10/2/20 4:06 PM, Steven Schveighoffer wrote:
> "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."

It should actually be "a mutable argument that has no destructor, no
postblit, no copy constructor, is copyable, and is not a reference type" As those are defined to be ref or not ref explicitly by the spec.

-Steve
October 02, 2020
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...

https://en.wikibooks.org/wiki/Ada_Programming/Subprograms:

"Explicitly aliased parameters and access parameters specify pass by reference."