Jump to page: 1 25  
Page
Thread overview
Binding rvalues to ref parameters redux
Mar 27, 2019
Nicholas Wilson
Mar 27, 2019
Nicholas Wilson
Mar 27, 2019
Nicholas Wilson
Mar 27, 2019
Nicholas Wilson
Mar 27, 2019
Nicholas Wilson
Mar 27, 2019
Timon Gehr
Mar 28, 2019
bitwise
Mar 28, 2019
Nicholas Wilson
Mar 28, 2019
Nicholas Wilson
Apr 01, 2019
bitwise
Apr 01, 2019
Timon Gehr
Apr 02, 2019
bitwise
Apr 02, 2019
bitwise
Apr 02, 2019
Nicholas Wilson
Apr 03, 2019
bitwise
Apr 04, 2019
Nicholas Wilson
Apr 04, 2019
Atila Neves
Apr 04, 2019
bitwise
Apr 05, 2019
Atila Neves
Apr 06, 2019
bitwise
Apr 03, 2019
Nick Treleaven
Mar 28, 2019
bitwise
Mar 28, 2019
Rubn
Apr 01, 2019
bitwise
Mar 28, 2019
Olivier FAURE
Mar 29, 2019
Alexibu
Mar 31, 2019
Manu
Mar 31, 2019
Manu
Mar 28, 2019
kinke
Mar 29, 2019
kinke
Mar 29, 2019
Olivier FAURE
Mar 29, 2019
Olivier FAURE
Apr 11, 2019
bitwise
Apr 12, 2019
bitwise
March 26, 2019
Work has been underway on redoing DIP 1016. I haven't made a pull request yet as it's a bit early. Looking for high-level observations:

https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a

Thanks in advance for any feedback.
March 27, 2019
On Wednesday, 27 March 2019 at 01:38:40 UTC, Andrei Alexandrescu wrote:
> Work has been underway on redoing DIP 1016. I haven't made a pull request yet as it's a bit early. Looking for high-level observations:
>
> https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
>
> Thanks in advance for any feedback.

I'd factor out
```
struct Point {
  long x, y, z;
  ...
}
Point fun();
```
from the rationale. No need to repeat it.
March 27, 2019
On Wednesday, 27 March 2019 at 01:38:40 UTC, Andrei Alexandrescu wrote:
> Work has been underway on redoing DIP 1016. I haven't made a pull request yet as it's a bit early. Looking for high-level observations:
>
> https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
>
> Thanks in advance for any feedback.

A couple more points.

In the combinatorial explosion example, give the root case an implementation.

double distance(ref const Point p1, ref const Point p2); // used by all other overloads

->

// used by all other overloads
double distance(ref const Point p1, ref const Point p2) { ... }


> More discussion on rationale and motivating examples can be found in the "Rationale" section of DIP 1016.

Thats fine for a draft, for the real thing this will need to include those examples. In particular the main points not included are:

* Its a PITA to get proper composition with higher order function templates.
* Disruption of pipelines


Under the "Binding Rules" please state the types of the symbols used up front (Where do Tk and Uk come from? what are they? Types? Parameters?)
March 27, 2019
On Wednesday, 27 March 2019 at 01:38:40 UTC, Andrei Alexandrescu wrote:
> Work has been underway on redoing DIP 1016. I haven't made a pull request yet as it's a bit early. Looking for high-level observations:
>
> https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
>
> Thanks in advance for any feedback.

> void function(int a, int b, int c) fun();
> int g();
> int h(int);
> int i();
> int j();
> fun(g(), h(j()), i()); // evaluates g() then j() then h() then i()
>                        // after which control is transferred to the callee

should be

fun()(g(), h(j()), i()).
March 27, 2019
On Wednesday, 27 March 2019 at 01:38:40 UTC, Andrei Alexandrescu wrote:
> Work has been underway on redoing DIP 1016. I haven't made a pull request yet as it's a bit early. Looking for high-level observations:
>
> https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
>
> Thanks in advance for any feedback.

Destructors of temporaries should be a subsection of its own.
It needs code examples, because while

>The order of destruction for temporaries inserted for a given function call is the inverse order of construction.

is fine and easy to understand, the rest is not. It would be far better to describe this through lambda lowering.

The document mentions

> Related, returning a ref parameter by ref enables safe and efficient "pipelining" of function calls.

But gives it no further discussion, c.f. the section of return ref in DIP 1016.

The document does not deal with overload resolution at all.

March 27, 2019
On 3/27/19 12:33 AM, Nicholas Wilson wrote:
> It would be far better to describe this through lambda lowering.

One important realization working on this was that insertion of constructors and destructors cannot be realized via lambda lowering because lifetimes don't follow some natural scoping. For example, the temporaries created on the left-hand side of && survive through the end of the full expression, whereas those created on the right-hand side do not. The "?:" operator is a hot mess including additional hidden state variables, conditional destruction thus breaking the language rules etc. I'll make sure the document mentions why lowering is not the appropriate mechanism to describe insertion of constructors and destructors.

One other thing is that these temporary construction and destruction rules preexisted. In fact probably the nicest thing about the DIP is that no new rules are introduced - temporaries are created and destroyed exactly as if there was no "ref" for the parameter. That way we could migrate some of the DIP into the spec, thus simplifying the DIP. I've already done that with the definitions of "full expression", "lvalue", and "rvalue".
March 27, 2019
On Wednesday, 27 March 2019 at 11:13:02 UTC, Andrei Alexandrescu wrote:
> One important realization working on this was that insertion of constructors and destructors cannot be realized via lambda lowering because lifetimes don't follow some natural scoping. For example, the temporaries created on the left-hand side of && survive through the end of the full expression, whereas those created on the right-hand side do not. The "?:" operator is a hot mess including additional hidden state variables, conditional destruction thus breaking the language rules etc. I'll make sure the document mentions why lowering is not the appropriate mechanism to describe insertion of constructors and destructors.

Well the way it is currently worded is _very_ confusing, it could do with examples of whatever transformation is applied.

> One other thing is that these temporary construction and destruction rules preexisted. In fact probably the nicest thing about the DIP is that no new rules are introduced - temporaries are created and destroyed exactly as if there was no "ref" for the parameter.

It should state that.

> That way we could migrate some of the DIP into the spec, thus simplifying the DIP. I've already done that with the definitions of "full expression", "lvalue", and "rvalue".


March 27, 2019
On 3/27/19 9:59 AM, Nicholas Wilson wrote:
> On Wednesday, 27 March 2019 at 11:13:02 UTC, Andrei Alexandrescu wrote:
>> One important realization working on this was that insertion of constructors and destructors cannot be realized via lambda lowering because lifetimes don't follow some natural scoping. For example, the temporaries created on the left-hand side of && survive through the end of the full expression, whereas those created on the right-hand side do not. The "?:" operator is a hot mess including additional hidden state variables, conditional destruction thus breaking the language rules etc. I'll make sure the document mentions why lowering is not the appropriate mechanism to describe insertion of constructors and destructors.
> 
> Well the way it is currently worded is _very_ confusing, it could do with examples of whatever transformation is applied.

Thanks, yah, a few more examples will definitely help.

>> One other thing is that these temporary construction and destruction rules preexisted. In fact probably the nicest thing about the DIP is that no new rules are introduced - temporaries are created and destroyed exactly as if there was no "ref" for the parameter.
> 
> It should state that.

The current wording is kinda buried in a paragraph: "In expressions containing rvalues bound to ref parameters, the order of evaluation of expressions and the lifetime of temporaries thus generated remain the same as if the ref parameters would be value parameters of the same type." I'll work on expanding on it and make it more prominent. Thanks!
March 27, 2019
On 27.03.19 02:38, Andrei Alexandrescu wrote:
> Work has been underway on redoing DIP 1016. I haven't made a pull request yet as it's a bit early. Looking for high-level observations:
> 
> https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
> 
> Thanks in advance for any feedback.

Assuming that we don't add a new function parameter storage class, I think this DIP gets the semantics exactly right. However, I would explain the following two things:

- Currently, the main use case of disallowed rvalue-ref calls is to check whether a (templated) function may change your argument using `ref` by trying to call it with an rvalue inside `__traits(compiles, ...)`. Maybe the DIP could state that even though this use case breaks, after this change, the functionality is in fact still available, but instead of an rvalue, you use an overload set containing a property getter and a property setter. (This is in fact a backwards-compatible way to do it.)

- It may not be immediately obvious that the DIP does not break overloading of ref and non-ref. [1]  The reason why overloading does not break is that a non-ref function may be called with a property getter that also has a setter, while the ref overload may not, so `ref` would keep being more specialized. [2]


However, I think adding a new storage class that documents that `ref` is being used for efficiency rather than for (shallow) modification, and restricting the rvalue rewrite to such parameters may make D code more readable, and it will make introspection more effective, because trying to call a function with an rvalue will query intent to modify. Additionally, it would avoid code breakage.

But of course, this means we would have two kinds of `ref` arguments, one that accepts lvalues and one that accepts both lvalues and rvalues, and the obvious next step would be to add `ref` arguments that only accept rvalues. :o)


[1] In my own frontend, if implemented without also changing the overloading logic, `ref` would no longer be more specialized than non-ref.

[2] In my frontend, the most restricted kind of expression that matches a non-ref argument (used to try to call the other function to determine specialization) is currently an rvalue of the respective type, after this change it would need to be an overload set of property getter and setter.
March 28, 2019
On Wednesday, 27 March 2019 at 01:38:40 UTC, Andrei Alexandrescu wrote:
> Work has been underway on redoing DIP 1016. I haven't made a pull request yet as it's a bit early. Looking for high-level observations:
>
> https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
>
> Thanks in advance for any feedback.

From the response to DIP 1016:

> Here, the DIP Author clearly expresses two reasons why a programmer may choose to declare a function to accept `ref` arguments. The Language Maintainers see this as the core of the proposal and would expect the distinction between the two cases to be maintained throughout. [However, this proposal does not maintain the distinction and instead conflates the two][1] cases. The Language Maintainers insist that any proposal allowing `ref` parameters to accept rvalue references must clearly define how functions which make use of `ref` for side effects will not accept rvalues.

I don't see anything in the new DIP that addresses the above issue. [1]

It seems like a waste to have a keyword that's just an alias for two others (in = const scope), so why not put 'in' to better use, like to qualify a ref parameter as accepting rvalues, or to outright replace 'ref' for rvalue-ref accepting parameters?

  Bit
« First   ‹ Prev
1 2 3 4 5