Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-11 Thread Johan Engelen via Digitalmars-d-learn

On Thursday, 10 May 2018 at 19:14:39 UTC, Meta wrote:


So it looks like disabling a struct's postblit actually counts 
as having a __postblit and __xpostblit function (don't ask me 
why), in addition to a construction and opAssign... no idea 
why, and maybe this is a bug, but I bet there's a good reason 
for it.


https://issues.dlang.org/show_bug.cgi?id=18628

-Johan



Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-10 Thread Meta via Digitalmars-d-learn

On Thursday, 10 May 2018 at 12:55:36 UTC, Uknown wrote:

On Thursday, 10 May 2018 at 11:06:06 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 21:09:12 UTC, Meta wrote:
It's a context pointer to the enclosing 
function/object/struct. Mark the struct as static to get rid 
of it.


Ok, but why an extra void* for `S.tupleof` and not for 
`T.tupleof` which is also scoped inside a unittest?


I'm guessing T is a POD, so it doesn't need a context pointer, 
whereas S is not counted as a POD since a member function was 
@disabled.


Yes, exactly. From my tests, if you add _any_ member method to a 
struct, it becomes non-POD. When you think about it, this makes 
perfect sense, as there's no possible way to access anything 
through a context pointer if there is no executable code within 
the struct's scope.


As far an @disabled postblit:

Plain Old Data
A struct or union is Plain Old Data (POD) if it meets the 
following criteria:


it is not nested
it has no postblits, destructors, or assignment operators
it has no ref fields or fields that are themselves non-PO

https://docarchives.dlang.io/v2.079.0/spec/struct.html#POD

Now if you do this:

struct R
{
@disable this(this);
int* _ptr;
}
unittest
{
struct S
{
@disable this(this);
int* _ptr;
}
struct T
{
int* _ptr;
}
pragma(msg, "R: ", typeof(R.tupleof));
pragma(msg, __traits(allMembers, R));

pragma(msg, "S: ", typeof(S.tupleof));
pragma(msg, __traits(allMembers, S));

pragma(msg, "T: ", typeof(T.tupleof));
pragma(msg, __traits(allMembers, T));
}

It prints:

R: (int*)
tuple("__postblit", "_ptr", "__xpostblit", "opAssign")

S: (int*, void*)
tuple("__postblit", "_ptr", "this", "__xpostblit", "opAssign")

T: (int*)
tuple("_ptr")

So it looks like disabling a struct's postblit actually counts as 
having a __postblit and __xpostblit function (don't ask me why), 
in addition to a construction and opAssign... no idea why, and 
maybe this is a bug, but I bet there's a good reason for it.


Anyway, as per my first point, this means it'll need a context 
pointer unless you mark the struct as static.


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-10 Thread Uknown via Digitalmars-d-learn

On Thursday, 10 May 2018 at 11:06:06 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 21:09:12 UTC, Meta wrote:
It's a context pointer to the enclosing 
function/object/struct. Mark the struct as static to get rid 
of it.


Ok, but why an extra void* for `S.tupleof` and not for 
`T.tupleof` which is also scoped inside a unittest?


I'm guessing T is a POD, so it doesn't need a context pointer, 
whereas S is not counted as a POD since a member function was 
@disabled.


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-10 Thread Per Nordlöw via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 21:09:12 UTC, Meta wrote:
It's a context pointer to the enclosing function/object/struct. 
Mark the struct as static to get rid of it.


Ok, but why an extra void* for `S.tupleof` and not for 
`T.tupleof` which is also scoped inside a unittest?


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Meta via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 18:04:40 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 17:52:48 UTC, Meta wrote:
I wasn't able to reproduce it on dmd-nightly: 
https://run.dlang.io/is/9wT8tH


What version of the compiler are you using?


Ahh, the struct needs to be in a unittest block for it to 
happen:


struct R
{
@disable this(this);
int* _ptr;
}
unittest
{
struct S
{
@disable this(this);
int* _ptr;
}
struct T
{
int* _ptr;
}
pragma(msg, "R: ", typeof(R.tupleof));
pragma(msg, "S: ", typeof(S.tupleof));
pragma(msg, "T: ", typeof(T.tupleof));
}

prints

R: (int*)
S: (int*, void*)
T: (int*)

Why is that?


It's a context pointer to the enclosing function/object/struct. 
Mark the struct as static to get rid of it.


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Per Nordlöw via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 17:52:48 UTC, Meta wrote:
I wasn't able to reproduce it on dmd-nightly: 
https://run.dlang.io/is/9wT8tH


What version of the compiler are you using?


Ahh, the struct needs to be in a unittest block for it to happen:

struct R
{
@disable this(this);
int* _ptr;
}
unittest
{
struct S
{
@disable this(this);
int* _ptr;
}
struct T
{
int* _ptr;
}
pragma(msg, "R: ", typeof(R.tupleof));
pragma(msg, "S: ", typeof(S.tupleof));
pragma(msg, "T: ", typeof(T.tupleof));
}

prints

R: (int*)
S: (int*, void*)
T: (int*)

Why is that?


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Meta via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 14:07:37 UTC, Per Nordlöw wrote:

Why (on earth) does

struct S
{
@disable this(this);
int* _ptr;
}
pragma(msg, typeof(S.tupleof));

prints

(int*, void*)

when

struct S
{
int* _ptr;
}
pragma(msg, typeof(S.tupleof));

prints

(int*)

?!!!


I wasn't able to reproduce it on dmd-nightly: 
https://run.dlang.io/is/9wT8tH


What version of the compiler are you using?


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Per Nordlöw via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 14:36:38 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 14:34:02 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 14:20:41 UTC, Per Nordlöw wrote:
If so, we can temporarily modify the trait to exclude the 
last `void*` member of the `S.tuple`. Given that it's always 
added as the last member.


Also note that

pragma(msg, __traits(isDisabled, S.this(this)));

fails to compile as

Error: identifier expected following `.`, not `this`


Ahh, but both

pragma(msg, __traits(isDisabled, S.__postblit));
pragma(msg, __traits(isDisabled, S.__xpostblit));

prints true for a struct with `@disable this(this);`

Which one should I pick to check if last element of `S.tupleof` 
should be discarded?


Managed to put together the hack

private template mustAddGCRangeOfStructOrUnion(T)
if (is(T == struct) ||
is(T == union))
{
import std.traits : hasUDA;
import std.meta : anySatisfy;
static if (__traits(hasMember, T, "__postblit"))
{
static if (__traits(isDisabled, T.__postblit))
{
enum mustAddGCRangeOfStructOrUnion = 
anySatisfy!(mustAddGCRangeOfMember, T.tupleof[0 .. $ - 1]);

}
else
{
enum mustAddGCRangeOfStructOrUnion = 
anySatisfy!(mustAddGCRangeOfMember, T.tupleof);

}
}
else
{
enum mustAddGCRangeOfStructOrUnion = 
anySatisfy!(mustAddGCRangeOfMember, T.tupleof);

}
}

defined here

https://github.com/nordlow/phobos-next/blob/master/src/gc_traits.d#L81

Destroy.


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Per Nordlöw via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 14:34:02 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 14:20:41 UTC, Per Nordlöw wrote:
If so, we can temporarily modify the trait to exclude the last 
`void*` member of the `S.tuple`. Given that it's always added 
as the last member.


Also note that

pragma(msg, __traits(isDisabled, S.this(this)));

fails to compile as

Error: identifier expected following `.`, not `this`


Ahh, but both

pragma(msg, __traits(isDisabled, S.__postblit));
pragma(msg, __traits(isDisabled, S.__xpostblit));

prints true for a struct with `@disable this(this);`

Which one should I pick to check if last element of `S.tupleof` 
should be discarded?


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Per Nordlöw via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 14:20:41 UTC, Per Nordlöw wrote:
If so, we can temporarily modify the trait to exclude the last 
`void*` member of the `S.tuple`. Given that it's always added 
as the last member.


Also note that

pragma(msg, __traits(isDisabled, S.this(this)));

fails to compile as

Error: identifier expected following `.`, not `this`


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Per Nordlöw via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 14:20:41 UTC, Per Nordlöw wrote:
If so, we can temporarily modify the trait to exclude the last 
`void*` member of the `S.tuple`. Given that it's always added 
as the last member.


Note that `std.traits.isCopyable!S` cannot be used, because it 
will return true when `S` has uncopyable members regardless of 
whether S.tupleof have any extra void* element or not (because of 
S's disabled postblit).


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Per Nordlöw via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 14:07:37 UTC, Per Nordlöw wrote:
This prevents the trait `mustAddGCRangeOfStructOrUnion` [1] 
from detecting when a container with manual memory management 
doesn't have to be scanned by the GC as in, for instance,


enum NoGc;
struct S
{
@disable this(this); // disable S postlib
@NoGc int* _ptr;
}
static assert(!mustAddGCRangeOfStructOrUnion!S); // is 
false when postblit of `S` is disabled


[1] 
https://github.com/nordlow/phobos-next/blob/master/src/gc_traits.d#L81


Can we statically check if the postblit has been disabled via

@disable this(this);

?

If so, we can temporarily modify the trait to exclude the last 
`void*` member of the `S.tuple`. Given that it's always added as 
the last member.


Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Per Nordlöw via Digitalmars-d-learn

Why (on earth) does

struct S
{
@disable this(this);
int* _ptr;
}
pragma(msg, typeof(S.tupleof));

prints

(int*, void*)

when

struct S
{
int* _ptr;
}
pragma(msg, typeof(S.tupleof));

prints

(int*)

?!!!

This prevents the trait `mustAddGCRangeOfStructOrUnion` [1] from 
detecting when a container with manual memory management doesn't 
have to be scanned by the GC as in, for instance,


enum NoGc;
struct S
{
@disable this(this); // disable S postlib
@NoGc int* _ptr;
}
static assert(!mustAddGCRangeOfStructOrUnion!S); // is false 
when postblit of `S` is disabled


[1] 
https://github.com/nordlow/phobos-next/blob/master/src/gc_traits.d#L81