digitalmars.D - delegating constructors and "this = ..."
- jpf (53/53) Feb 08 2010 Hi,
Hi, I've come across some strange behavior using delegating constructors and assignment to this. Please have a look a this testcase: -------------------------------------- class Test { static Test[void*] lookupTable; public int i = 0; public this (void* ptr) { //Check if there already is a D object for this ptr if(ptr in lookupTable) { this = lookupTable[ptr]; assert(this.i == 15); /* ok */ return; } i = 15; lookupTable[ptr] = this; } public this (void* ptr, bool fake) { this(ptr); assert(this.i == 15); /* fails */ } } void main() { int a,b; /*for different pointers*/ Test test1 = new Test(&a); Test test2 = new Test(&a); Test test3 = new Test(&b, false); Test test4 = new Test(&b, false); assert(test1 is test2); /* ok */ assert(test2.i == 15); /* ok */ assert(test3 is test4); /* fails */ assert(test4.i == 15); /* fails */ } -------------------------------------- Tested with dmd 1.055. As soon as the constructors are delegated the code doesn't work anymore. The assignment "this = lookupTable[ptr];" still succeeds but in the "this(void* ptr, bool fake)" constructor the this reference seems wrong. The returned object also isn't the one assigned to "this". I'm not sure if this is a bug, but it's at least unexpected behavior. Should I file a bug for this issue? Would the correct bug-tracker for this be http://d.puremagic.com/issues ?
Feb 08 2010
Hello JPF,Hi, I've come across some strange behavior using delegating constructors and assignment to this. Please have a look a this testcase: -------------------------------------- class Test { static Test[void*] lookupTable; public int i = 0; public this (void* ptr) { //Check if there already is a D object for this ptr if(ptr in lookupTable) { this = lookupTable[ptr]; assert(this.i == 15); /* ok */ return; }'this' is a mutable *local* reference (IIRC it is in fact a hidden 1st argument to the function). All the 'this =' lines does is assign to a local value that is discarded immediately. If asserts are turned off, the optimizer would even be free to just dump the then clause from that code as a dead assignment. ('this' being mutable might be considered a bug in the spec)-- <IXOYE><
Feb 08 2010
On 08.02.2010 18:26, BCS wrote:'this' is a mutable *local* reference (IIRC it is in fact a hidden 1st argument to the function). All the 'this =' lines does is assign to a local value that is discarded immediately. If asserts are turned off, the optimizer would even be free to just dump the then clause from that code as a dead assignment. ('this' being mutable might be considered a bug in the spec)Oops, I didn't know that. That explains why I didn't see assigning to this mentioned in the docs. I got the assigning idea from gtkd, they use this as well. One thing is strange though: If you look at the test case, in the end: ------------------------------------- Test test1 = new Test(&a); Test test2 = new Test(&a); assert(test1 is test2); /* ok */ ------------------------------------- This works, test1 and test2 reference the same object, which means "this = lookupTable[ptr];" does not only change the local reference when "this (void* ptr)" is invoked directly. If this is a local reference only, that shouldn't work at all, correct?-- <IXOYE><
Feb 08 2010
On 08.02.2010 18:26, BCS wrote:Hello JPF,Thanks for your help, I think I now understand what's going on. 'this' is a mutable local reference in the constructor but the constructor automatically returns the local 'this'. This explains why the first case works while the second doesn't. This would also mean I could do "this = this(ptr);" in the second constructor and it indeed does work; With the above change the whole testcase works as expected. I now just have to decide whether I'll use the "implementation specific but nice syntax" way or a static function instead of public constructors.Hi, I've come across some strange behavior using delegating constructors and assignment to this. Please have a look a this testcase: -------------------------------------- class Test { static Test[void*] lookupTable; public int i = 0; public this (void* ptr) { //Check if there already is a D object for this ptr if(ptr in lookupTable) { this = lookupTable[ptr]; assert(this.i == 15); /* ok */ return; }'this' is a mutable *local* reference (IIRC it is in fact a hidden 1st argument to the function). All the 'this =' lines does is assign to a local value that is discarded immediately. If asserts are turned off, the optimizer would even be free to just dump the then clause from that code as a dead assignment. ('this' being mutable might be considered a bug in the spec)-- <IXOYE><
Feb 08 2010
Hello JPF,Thanks for your help, I think I now understand what's going on. 'this' is a mutable local reference in the constructor but the constructor automatically returns the local 'this'. This explains why the first case works while the second doesn't. This would also mean I could do "this = this(ptr);" in the second constructor and it indeed does work; With the above change the whole testcase works as expected.Odd....I now just have to decide whether I'll use the "implementation specific but nice syntax" way or a static function instead of public constructors.don't use implementation specific code. I suggest you file a bug/clarification request. If that is the way things are supposed to work, it should be officially sanctioned. If not, it should be removed. -- <IXOYE><
Feb 08 2010
On 08.02.2010 20:45, BCS wrote:Hello JPF,thanks again. I filed a documentation bug here: http://d.puremagic.com/issues/show_bug.cgi?id=3787 Turns out there actually is a similar compiler bug: http://d.puremagic.com/issues/show_bug.cgi?id=780 that was already reported 2006 but it seems it didn't get much attention.Thanks for your help, I think I now understand what's going on. 'this' is a mutable local reference in the constructor but the constructor automatically returns the local 'this'. This explains why the first case works while the second doesn't. This would also mean I could do "this = this(ptr);" in the second constructor and it indeed does work; With the above change the whole testcase works as expected.Odd....I now just have to decide whether I'll use the "implementation specific but nice syntax" way or a static function instead of public constructors.don't use implementation specific code. I suggest you file a bug/clarification request. If that is the way things are supposed to work, it should be officially sanctioned. If not, it should be removed. -- <IXOYE><
Feb 09 2010