www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 16355] New: __xpostblit incorrectly generated for a struct

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

          Issue ID: 16355
           Summary: __xpostblit incorrectly generated for a struct with a
                    zero-length static array
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: issues.dlang jmdavisProg.com

I noticed that std.traits.hasElaborateCopyConstructor has an overly elaborate
implementation where it recursively looks at each member of a struct to
determine whether it has a postblit constructor. And that makes sense if you
don't know about __xpostblit (which as I understand it is the function that
calls the postblit constructor on any member variables that needs it as well as
calling the postblit constructor on the struct itself). However, given that any
struct that either has a postblit constructor or which has members with a
postblit constructor should have __xpostblit, and any struct that does not have
a postblit constructor or any membears with postblit constructors should not
have __xpostblit, hasElaborateCopyConstructor should be able to just test
whether the struct has __xpostblit or not rather than recursively checking for
__postblit. However, when I made that change, the tests failed because of this
struct

    static struct S6 { S3[0] field; }

In particular, this code

void main()
{
    import std.traits;
    static struct S2 { this(this) {} }
    static struct S3 { S2 field; }
    static struct S6 { S3[0] field; }
    static assert(!hasElaborateCopyConstructor!S6, "assert 1");
    static assert(!__traits(hasMember, S6, "__postblit"), "assert 2");
    static assert(!__traits(hasMember, S6, "__xpostblit"), "assert 3");
}

results in this compilation error

q.d(9): Error: static assert  "assert 3"

Correctly, S6 does not have __postblit. However, the compiler apparently
decided to give it an __xpostblit when it doesn't actually need one. Yes, the
static array is of a struct that has a postblit constructor, but the static
array has a length of 0, so it should never be necessary to call any postblit
constructors when copying that array. Presumably, the dmd code sees that it's a
static array of something with a postblit constructor without taking into
account the fact that the array's length is 0 and thus that no postblit
constructor will ever need to be called.

So, I would argue that __xpostblit should be fixed to match
hasElaborateCopyConstructor. But if for some reason, we decide that it actually
does make sense for __xpostblit to be declared in this case (though I don't see
why it would be), then this bug report should be changed to indicate that
hasElaborateCopyConstructor needs to be fixed to match.

--
Aug 05 2016