Skip to content

Commit 19bdc68

Browse files
committed
Document the compiler generated postblit types
1 parent cff447d commit 19bdc68

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

spec/struct.dd

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,100 @@ $(GNAME Postblit):
566566
}
567567
---
568568

569+
$(P Depending on the struct layout, the compiler may generate the following
570+
internal postblits:)
571+
572+
$(OL
573+
$(LI `__postblit`. The compiler assigns this name to the explicitly
574+
defined postblit `this(this)` so that it can be treated exactly as
575+
a normal function. Note that if a struct defines a postblit, it cannot
576+
define a function named `__postblit` - no matter the signature -
577+
as this will result in a compilation error due to the name conflict.)
578+
$(LI `__fieldPostblit`. If a struct `X` has at least 1 member which is a
579+
struct that defines a postblit, then a field postblit is generated
580+
for `X` that calls all the underlying postblits of the struct fields
581+
in topological order.)
582+
$(LI `__aggrPostblit`. If a struct has an explicitly defined postblit
583+
and at least 1 struct member that has a postblit (any type of postblit)
584+
an aggregated postblit is generated which calls `__fieldPostblit` first
585+
and then `__postblit`.)
586+
$(LI `__xpostblit`. The field and aggregated postblits, although generated
587+
for a struct, are not actual struct members. In order to be able to call
588+
them, the compiler internally creates an alias, called `__xpostblit` which
589+
is a member of the struct and which points to the generated postblit that
590+
is the most inclusive.)
591+
)
592+
593+
($SPEC_RUNNABLE_EXAMPLE_COMPILE
594+
---
595+
// struct with alias __xpostblit = __postblit
596+
struct X
597+
{
598+
this(this) {}
599+
}
600+
601+
// struct with alias __xpostblit = __fieldPostblit
602+
// which contains a call to X.__xpostblit
603+
struct Y
604+
{
605+
X a;
606+
}
607+
608+
// struct with alias __xpostblit = __aggrPostblit which contains
609+
// a call to Y.__xpostblit and a call to Z.__postblit
610+
struct Z
611+
{
612+
Y a;
613+
this(this) {}
614+
}
615+
616+
void main()
617+
{
618+
// X has __postblit and __xpostblit (pointing to __postblit)
619+
static assert(__traits(hasMember, X, "__postblit"));
620+
static assert(__traits(hasMember, X, "__xpostblit"));
621+
622+
// Y does not have __postblit, but has __xpostblit (pointing to __fieldPostblit)
623+
static assert(!__traits(hasMember, Y, "__postblit"));
624+
static assert(__traits(hasMember, Y, "__xpostblit"));
625+
// __fieldPostblit is not a member of the struct
626+
static assert(!__traits(hasMember, Y, "__fieldPostblit"));
627+
628+
// Z has __postblit and __xpostblit (pointing to __aggrPostblit)
629+
static assert(__traits(hasMember, Z, "__postblit"));
630+
static assert(__traits(hasMember, Z, "__xpostblit"));
631+
// __aggrPostblit is not a member of the struct
632+
static assert(!__traits(hasMember, Z, "__aggrPostblit"));
633+
}
634+
---
635+
)
636+
637+
$(P Neither of the above postblits is defined for structs that don't
638+
define `this(this)` and don't have fields that transitively define it.
639+
Example:)
640+
641+
($SPEC_RUNNABLE_EXAMPLE_COMPILE
642+
---
643+
struct X
644+
{}
645+
646+
struct Y
647+
{
648+
int a;
649+
X b;
650+
}
651+
652+
void main()
653+
{
654+
static assert(!__traits(hasMember, X, "__postblit"));
655+
static assert(!__traits(hasMember, X, "__xpostblit"));
656+
657+
static assert(!__traits(hasMember, Y, "__postblit"));
658+
static assert(!__traits(hasMember, Y, "__xpostblit"));
659+
}
660+
---
661+
)
662+
569663
$(P Unions may not have fields that have postblits.)
570664

571665
$(H2 $(LEGACY_LNAME2 StructDestructor, struct-destructor, Struct Destructors))

0 commit comments

Comments
 (0)