www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - SysTime and std.array.array

reply "Paolo Invernizzi" <paolo.invernizzi gmail.com> writes:
Hi all,

I really missing something here, because the following code is 
taking two different path based on the presence or not of a field 
with SysTime, where the field itself is not involved at all in 
the process.

It seems that I'm using something forbidden, or something that it 
is leading to an undefined behaviour, but I have not idea of what 
it is the source of the problem.

Note that I'm using array() as in the original code I was using 
it over a range, this is a reduction of the same problem.

Suggestions are welcome! http://dpaste.dzfl.pl/fc130984

Paolo Invernizzi

---
import std.datetime;
import std.math;

struct A
{
     double i;
}


struct B
{
     invariant()
     {
		if(j == 0)
			assert(a.i.isNaN, "why is 'j' zero?? and i is not NaN?");
		else
			assert( ! a.i.isNaN );
     }
	
     SysTime when; // comment this line avoid the breakage
     int j;
     A a;
}
void main()
{
     B b1 = B.init;
	assert(&b1); // verify that default eyes invariants are ok;

	auto b2 = B(
		SysTime(0, UTC()),  // comment this line avoid the breakage
		1, A(1));
	assert(&b2);
	auto b3 = B(
		SysTime(0, UTC()),  // comment this line avoid the breakage
		1, A(1)
	);
	assert(&b3);
	
     import std.array;
     auto arr = [b2, b3];
	
	assert(arr[0].j == 1);
	assert(arr[1].j == 1);
     auto a2 = arr.array(); // << bang, invariant is raised, also 
if b2 and b3 are good
}
--
Aug 25 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 25 August 2013 at 14:50:16 UTC, Paolo Invernizzi wrote:
 Hi all,

 --
I didn't fully investigate, but my guess is that you are seeing emplace bugs. Basically, *array* first allocates an array containing noise, and then tries to emplace data onto there. Unfortunatly, emplace does it wrong, calling "opAssign" when it shouldn't. Further, SysTime is implemented (AFAIK), as a rebindable, which has an elaborate opAssign. This means that when you call emplace, it calls opAssign, which triggers your invariant, which fails, since data is just noise. This is why commenting out that data member also avoids the bug. I'd tell you I have an open pull request that fixes it, but its been stuck without review for *months*.
Aug 25 2013
parent "Paolo Invernizzi" <paolo.invernizzi gmail.com> writes:
On Sunday, 25 August 2013 at 19:01:14 UTC, monarch_dodra wrote:
 On Sunday, 25 August 2013 at 14:50:16 UTC, Paolo Invernizzi 
 wrote:
 Hi all,

 --
I didn't fully investigate, but my guess is that you are seeing emplace bugs. Basically, *array* first allocates an array containing noise, and then tries to emplace data onto there. Unfortunatly, emplace does it wrong, calling "opAssign" when it shouldn't. Further, SysTime is implemented (AFAIK), as a rebindable, which has an elaborate opAssign. This means that when you call emplace, it calls opAssign, which triggers your invariant, which fails, since data is just noise. This is why commenting out that data member also avoids the bug. I'd tell you I have an open pull request that fixes it, but its been stuck without review for *months*.
Thank you for the explanation, very appreciated: I've found your pull request, and I'm adding a comment pushing for an inclusion. (some bug number to vote up?) It's not easy to get familiar with ranges and templates, and that kind of bugs turns sometimes using Phobos facilities like walking in a minefields! I've another question: why the opAssign in SysTime is triggering the invariants in the enclosing struct? I mean, they nest also in this case? Thank you - Paolo Invernizzi
Aug 25 2013