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)
 
 -- 
 <IXOYE><
 
 
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?
 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








 
 
 
 jpf <spam example.com> 