www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Possible bug in RVO?

reply Yuxuan Shui <yshuiv7 gmail.com> writes:
I have encountered a weird bug.

I defined a Set class, which has a opBinary!"-". And somehow this:

auto tmp = set_a-set_b;

produces different results as this:

set_a = set_a-set_b;

the latter will produce an empty set.

I tried to reduce the source code to get a test case. But this 
problem just goes away after removing some code.

Any ideas what I could have done wrong?
Apr 03 2016
next sibling parent Yuxuan Shui <yshuiv7 gmail.com> writes:
On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
 I have encountered a weird bug.

 I defined a Set class, which has a opBinary!"-". And somehow 
 this:

 auto tmp = set_a-set_b;

 produces different results as this:

 set_a = set_a-set_b;

 the latter will produce an empty set.

 I tried to reduce the source code to get a test case. But this 
 problem just goes away after removing some code.

 Any ideas what I could have done wrong?
OK, I think I got a test case: import std.traits; struct Set { public: void insert(ulong v) { aa[v] = true; } size_t size() const { return aa.length; } auto opBinary(string op)(ref Set o) const { Set ret; foreach(k; aa.byKey) if (k !in o.aa) ret.insert(k); return ret; } disable this(this); bool[ulong] aa; } struct XX { Set a, b, tmp; this(int n) { a.insert(n); tmp = a-b; a = a-b; } } void main(){ import std.stdio; XX xx = XX(1000); writeln(xx.a.size); writeln(xx.tmp.size); } This does not happen when 'a' is on stack, that's why I was having trouble reproducing it. I don't think this is valid code, because Set has disabled post-blit, 'a = a-b' should report an error. However, I don't think current behavior of dmd is correct either.
Apr 03 2016
prev sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
 I have encountered a weird bug.

 I defined a Set class, which has a opBinary!"-". And somehow 
 this:

 auto tmp = set_a-set_b;

 produces different results as this:

 set_a = set_a-set_b;

 the latter will produce an empty set.

 I tried to reduce the source code to get a test case. But this 
 problem just goes away after removing some code.

 Any ideas what I could have done wrong?
A slightly more reduced test case: struct Set { void insert(ulong v) { aa[v] = true; } disable this(this); bool[ulong] aa; } auto clobber(ref Set x, ref Set o) { Set ret; ret.aa = x.aa; return ret; } struct XX { Set a, b, tmp; this(int n) { a.insert(1); //a.aa[1] = true; <--- Swap above line with this doesn't trigger the bug tmp = a.clobber(b); a = a.clobber(b); } } void main(){ import std.stdio; XX xx = XX(0); writeln(xx.a.aa.length); writeln(xx.tmp.aa.length); }
Apr 03 2016
next sibling parent Yuxuan Shui <yshuiv7 gmail.com> writes:
On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote:
 On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
 I have encountered a weird bug.

 I defined a Set class, which has a opBinary!"-". And somehow 
 this:

 auto tmp = set_a-set_b;

 produces different results as this:

 set_a = set_a-set_b;

 the latter will produce an empty set.

 I tried to reduce the source code to get a test case. But this 
 problem just goes away after removing some code.

 Any ideas what I could have done wrong?
A slightly more reduced test case:
And LDC has the same problem with the first test case, but not with the second one.
Apr 03 2016
prev sibling parent reply Anonymouse <asdf asdf.com> writes:
On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote:
 On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
 auto clobber(ref Set x, ref Set o) {
 	Set ret;
 	ret.aa = x.aa;
assert(x.aa.length > 0); // <-- boom
 	return ret;
 }
No idea myself but that's where it seems to go wrong.
Apr 04 2016
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 04/04/2016 09:36 AM, Anonymouse wrote:
 On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote:
 On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
 auto clobber(ref Set x, ref Set o) {
     Set ret;
     ret.aa = x.aa;
assert(x.aa.length > 0); // <-- boom
     return ret;
 }
No idea myself but that's where it seems to go wrong.
Looks like a bug. Just to make it more visible: auto clobber(ref Set x, ref Set o) { writefln("entered clobber - x.aa: %s", x.aa); Set ret; writefln("did not touch x.aa - x.aa: %s", x.aa); ret.aa = x.aa; return ret; } x.aa changes during the second call: entered clobber - x.aa: [1:true] did not touch x.aa - x.aa: [1:true] entered clobber - x.aa: [1:true] did not touch x.aa - x.aa: [] <-- What happened? Ali
Apr 04 2016
parent Yuxuan Shui <yshuiv7 gmail.com> writes:
On Monday, 4 April 2016 at 21:31:08 UTC, Ali Çehreli wrote:
 On 04/04/2016 09:36 AM, Anonymouse wrote:
 On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote:
     [...]
assert(x.aa.length > 0); // <-- boom
 [...]
No idea myself but that's where it seems to go wrong.
Looks like a bug. Just to make it more visible: auto clobber(ref Set x, ref Set o) { writefln("entered clobber - x.aa: %s", x.aa); Set ret; writefln("did not touch x.aa - x.aa: %s", x.aa); ret.aa = x.aa; return ret; } x.aa changes during the second call: entered clobber - x.aa: [1:true] did not touch x.aa - x.aa: [1:true] entered clobber - x.aa: [1:true] did not touch x.aa - x.aa: [] <-- What happened? Ali
I filed an bug report here: https://issues.dlang.org/show_bug.cgi?id=15869
Apr 04 2016