D2 struct as value in Associative Array (issue 1886) still not working.

Michael Rynn michaelrynn at optusnet.com.au
Thu Dec 17 16:22:58 PST 2009


I ran into issue 1886.  Associative arrays and struct as value with
opAssign. I added a comment to that open issue, but I am annoyed, so I am
posting here also, in case I can strike a chord with someone.


struct noblit { int x; }

struct postblit {
   int x;

   this(this){} // these break the AA useability as value (but not key)
   ~this(){}
}
string key = "test";

noblit[string] nmap;
noblit nval;

nval.x = 15;
nmap[key] = nval; // ok

postblit[string] map;
postblit val;
val.x = 15;
map[key] = val; // range error


I stepped thru the x86 code generated in the debugger using Visual Studio
2008 after conversion with cv2pdb -- great tool.

In the noblit case :-
The code  calls __aaGet
     
	the arguments are the key, TypeInfo_Aa at __init, and address of the
map structure.
	An address? is returned in EAX, which is checked for null, The 
value of
	nval is directly blitted to the returned address.

	__aaGet does the checking if the key points to existing value,
and allocates memory for new value as required.


In the postblit case the generated code seems to miss the point entirely.

The code initially makes a temporary copy of val. and calls the postblit
constructor, which calls this(this).  --> @postblit__cpctor -->
postblit at __postblit.

Why is a prior temporary copy required, when one hopes that its the map
that is going to provide the final destination?

>From the temporary copy, it then pushes the bits value of the temporary
(not the address!),
then the key, then TypeInfo_Aa at __init, and address of map.

The code then calls __aaGetRvalue  ( not __aaGet )

__aaGetRvalue gives up very quickly, failing its first check.

     It pushes registers, and then checks the address in [esp+18h]. This
     being null, it pop-exits with null as the result in eax. Obviously
     __aaGetRvalue is expecting something else to be setup.
     
     
     Presumably if __aaGetRvalue actually worked, it would just reblit
the value in the temporary to the memory it allocated or found, without
calling postblit again.

I would like to see ideally.
	No temporary copy made initially.

	The map lookup able to allocate or find memory for the key. The 
address
	returned.
	The copy made and then post-blit called.

Failing that , please fix up __aaGetRvalue so it does the right thing.



The opAssign example in the D2.0 Associated Array is wrong. It has
something like
S* opAssign(ref const S  value)
{
	this.x = value.x;
	return this;  // Now it needs to be &this.
}


Or should it be?:

S opAssign(ref const S  value)
{
	this.x = value.x;
	return this;
}

I cannot tell from the documentation what is the recommendation D2 struct
opAssign.   struct seems to work for most of the other facilities in D2.

The DPL book fails to cover such intricasies, apart from the metaphorical
"There be Dragons..". This is wise, since this is flunky.


struct { <contents> this(this){} }

It was easy enough and also more elegant to wrap the struct contents in a 
class anyway. And this is probably a good thing.

Still , its a bug in D2 types functionality.

Michael Rynn
------------




More information about the Digitalmars-d mailing list