Thread overview
Bug with references (no casting used)
Feb 22, 2014
andrea9940
Feb 22, 2014
Maxim Fomin
Feb 22, 2014
anonymous
Feb 22, 2014
Artur Skawina
February 22, 2014
Hi everyone,
I was trying to get my vector struct to use extensively references for passing parameters and I found a subtle bug which make me lose a few hour.

A sample code that shows the bug is here http://pastebin.com/rvcNdjAE (fails with dmd 2.064 on linux)
I think that the code is wrong and dmd does not recognize it:
opBinary() allocates a struct on the stack which is then accepted by reference in opOpAssign.

I'd like to know if currently there are correct ways to pass rvalue structs by reference or if I should pass everything by value and hope the compiler optimizes all reduntant copies.
February 22, 2014
On Saturday, 22 February 2014 at 17:22:51 UTC, andrea9940 wrote:
> Hi everyone,
> I was trying to get my vector struct to use extensively references for passing parameters and I found a subtle bug which make me lose a few hour.
>
> A sample code that shows the bug is here http://pastebin.com/rvcNdjAE (fails with dmd 2.064 on linux)
> I think that the code is wrong and dmd does not recognize it:
> opBinary() allocates a struct on the stack which is then accepted by reference in opOpAssign.
>
> I'd like to know if currently there are correct ways to pass rvalue structs by reference or if I should pass everything by value and hope the compiler optimizes all reduntant copies.

Looks like compiler bug.
February 22, 2014
On Saturday, 22 February 2014 at 17:22:51 UTC, andrea9940 wrote:
> Hi everyone,
> I was trying to get my vector struct to use extensively references for passing parameters and I found a subtle bug which make me lose a few hour.
>
> A sample code that shows the bug is here http://pastebin.com/rvcNdjAE (fails with dmd 2.064 on linux)
> I think that the code is wrong and dmd does not recognize it:
> opBinary() allocates a struct on the stack which is then accepted by reference in opOpAssign.

Clarifying: The bug is that opBinary returns a reference to a
local (vector), which is invalid. I don't know if dmd should see
that, as it's hidden behind a call.

> I'd like to know if currently there are correct ways to pass rvalue structs by reference or if I should pass everything by value and hope the compiler optimizes all reduntant copies.

There isn't. But adding an overload that forwards to the ref
version is trivial (as long as there's only one parameter):
---
         auto opOpAssign(string op)(const Vector rhs)
         if (op == "+" || op == "-")
         {
                 return opOpAssign!op(rhs);
         }
---
I don't know if the ref even buys you anything performance-wise,
though.
February 22, 2014
On 02/22/14 18:22, andrea9940 wrote:
> I was trying to get my vector struct to use extensively references for passing parameters and I found a subtle bug which make me lose a few hour.
> 
> A sample code that shows the bug is here http://pastebin.com/rvcNdjAE (fails with dmd 2.064 on linux)
> I think that the code is wrong and dmd does not recognize it:
> opBinary() allocates a struct on the stack which is then accepted by reference in opOpAssign.

That is ok; the problem is that opBinary returns a local stack-allocated object by reference. Make it return by value, and with some help from RVO you should get only one copy (which is necessary because you create a new Vector instance).

IOW:

	   Vector opBinary(string op)(T rhs) const;
	   ref Vector opOpAssign(string op)(T rhs);
	   ref Vector opOpAssign(string op)(auto ref const Vector rhs);

artur