3 import core
.internal
.attributes
: betterC
;
7 Given a pointer `chunk` to uninitialized memory (but already typed
8 as `T`), constructs an object of non-`class` type `T` at that
9 address. If `T` is a class, initializes the class reference to null.
10 Returns: A pointer to the newly constructed object (which is the same
13 T
* emplace(T
)(T
* chunk
) @safe pure nothrow
15 import core
.internal
.lifetime
: emplaceRef
;
31 assert(s2
[0].i
== 42 && s2
[1].i
== 42);
50 Given a pointer `chunk` to uninitialized memory (but already typed
51 as a non-class type `T`), constructs an object of type `T` at
52 that address from arguments `args`. If `T` is a class, initializes
53 the class reference to `args[0]`.
54 This function can be `@trusted` if the corresponding constructor of
56 Returns: A pointer to the newly constructed object (which is the same
59 T
* emplace(T
, Args
...)(T
* chunk
, auto ref Args args
)
60 if (is(T
== struct) || Args
.length
== 1)
62 import core
.internal
.lifetime
: emplaceRef
;
64 emplaceRef
!T(*chunk
, forward
!args
);
74 assert(*emplace
!int(&a
, b
) == 42);
86 Given a raw memory area `chunk` (but already typed as a class type `T`),
87 constructs an object of `class` type `T` at that address. The constructor
88 is passed the arguments `Args`.
89 If `T` is an inner class whose `outer` field can be used to access an instance
90 of the enclosing class, then `Args` must not be empty, and the first member of it
91 must be a valid initializer for that `outer` field. Correct initialization of
92 this field is essential to access members of the outer class inside `T` methods.
94 This function is `@safe` if the corresponding constructor of `T` is `@safe`.
95 Returns: The newly constructed object.
97 T
emplace(T
, Args
...)(T chunk
, auto ref Args args
)
100 import core
.internal
.traits
: isInnerClass
;
102 static assert(!__traits(isAbstractClass
, T
), T
.stringof
~
103 " is abstract and it can't be emplaced");
105 // Initialize the object in its pre-ctor state
106 const initializer
= __traits(initSymbol
, T
);
107 (() @trusted { (cast(void*) chunk
)[0 .. initializer
.length
] = initializer
[]; })();
109 static if (isInnerClass
!T
)
111 static assert(Args
.length
> 0,
112 "Initializing an inner class requires a pointer to the outer class");
113 static assert(is(Args
[0] : typeof(T
.outer
)),
114 "The first argument must be a pointer to the outer class");
116 chunk
.outer
= args
[0];
117 alias args1
= args
[1..$];
119 else alias args1
= args
;
121 // Call the ctor if any
122 static if (is(typeof(chunk
.__ctor(forward
!args1
))))
124 // T defines a genuine constructor accepting args
125 // Go the classic route: write .init first, then call ctor
126 chunk
.__ctor(forward
!args1
);
130 static assert(args1
.length
== 0 && !is(typeof(&T
.__ctor
)),
131 "Don't know how to initialize an object of type "
132 ~ T
.stringof
~ " with arguments " ~ typeof(args1
).stringof
);
144 @safe this(int x
) { this.x
= x
; }
147 auto buf
= new void[__traits(classInstanceSize
, SafeClass
)];
148 auto support
= (() @trusted => cast(SafeClass
)(buf
.ptr
))();
149 auto safeClass
= emplace
!SafeClass(support
, 5);
150 assert(safeClass
.x
== 5);
155 @system this(int x
) { this.x
= x
; }
158 auto buf2
= new void[__traits(classInstanceSize
, UnsafeClass
)];
159 auto support2
= (() @trusted => cast(UnsafeClass
)(buf2
.ptr
))();
160 static assert(!__traits(compiles
, emplace
!UnsafeClass(support2
, 5)));
161 static assert(!__traits(compiles
, emplace
!UnsafeClass(buf2
, 5)));
172 @safe auto getI() { return i
; }
175 auto outerBuf
= new void[__traits(classInstanceSize
, Outer
)];
176 auto outerSupport
= (() @trusted => cast(Outer
)(outerBuf
.ptr
))();
178 auto innerBuf
= new void[__traits(classInstanceSize
, Outer
.Inner
)];
179 auto innerSupport
= (() @trusted => cast(Outer
.Inner
)(innerBuf
.ptr
))();
181 auto inner
= innerSupport
.emplace
!(Outer
.Inner
)(outerSupport
.emplace
!Outer
);
182 assert(inner
.getI
== 3);
186 Given a raw memory area `chunk`, constructs an object of `class` type `T` at
187 that address. The constructor is passed the arguments `Args`.
188 If `T` is an inner class whose `outer` field can be used to access an instance
189 of the enclosing class, then `Args` must not be empty, and the first member of it
190 must be a valid initializer for that `outer` field. Correct initialization of
191 this field is essential to access members of the outer class inside `T` methods.
193 `chunk` must be at least as large as `T` needs and should have an alignment
194 multiple of `T`'s alignment. (The size of a `class` instance is obtained by using
195 $(D __traits(classInstanceSize, T))).
197 This function can be `@trusted` if the corresponding constructor of `T` is `@safe`.
198 Returns: The newly constructed object.
200 T
emplace(T
, Args
...)(void[] chunk
, auto ref Args args
)
203 enum classSize
= __traits(classInstanceSize
, T
);
204 assert(chunk
.length
>= classSize
, "chunk size too small.");
206 enum alignment
= __traits(classInstanceAlignment
, T
);
207 assert((cast(size_t
) chunk
.ptr
) % alignment
== 0, "chunk is not aligned.");
209 return emplace
!T(cast(T
)(chunk
.ptr
), forward
!args
);
218 this(int i
){this.i
= i
;}
220 auto buf
= new void[__traits(classInstanceSize
, C
)];
221 auto c
= emplace
!C(buf
, 5);
227 @nogc pure nothrow @system unittest
229 // works with -betterC too:
231 static extern (C
++) class C
233 @nogc pure nothrow @safe:
240 int virtualGetI() { return i
; }
243 align(__traits(classInstanceAlignment
, C
)) byte[__traits(classInstanceSize
, C
)] buffer
;
244 C c
= emplace
!C(buffer
[], 42);
245 assert(c
.virtualGetI() == 42);
255 auto getI() { return i
; }
258 auto outerBuf
= new void[__traits(classInstanceSize
, Outer
)];
259 auto innerBuf
= new void[__traits(classInstanceSize
, Outer
.Inner
)];
260 auto inner
= innerBuf
.emplace
!(Outer
.Inner
)(outerBuf
.emplace
!Outer
);
261 assert(inner
.getI
== 3);
264 @nogc pure nothrow @safe unittest
266 static class __conv_EmplaceTestClass
268 @nogc @safe pure nothrow:
280 this(int i
, ref int j
)
282 assert(this.i
== 3 && i
== 5 && j
== 6);
289 align(__traits(classInstanceAlignment
, __conv_EmplaceTestClass
))
290 ubyte[__traits(classInstanceSize
, __conv_EmplaceTestClass
)] buf
;
291 auto support
= (() @trusted => cast(__conv_EmplaceTestClass
)(buf
.ptr
))();
293 auto fromRval
= emplace
!__conv_EmplaceTestClass(support
, 1);
294 assert(fromRval
.i
== 11);
296 auto fromLval
= emplace
!__conv_EmplaceTestClass(support
, var
);
297 assert(fromLval
.i
== 26);
299 auto k
= emplace
!__conv_EmplaceTestClass(support
, 5, var
);
305 Given a raw memory area `chunk`, constructs an object of non-$(D
306 class) type `T` at that address. The constructor is passed the
307 arguments `args`, if any.
309 `chunk` must be at least as large
310 as `T` needs and should have an alignment multiple of `T`'s
313 This function can be `@trusted` if the corresponding constructor of
315 Returns: A pointer to the newly constructed object.
317 T
* emplace(T
, Args
...)(void[] chunk
, auto ref Args args
)
320 import core
.internal
.traits
: Unqual
;
321 import core
.internal
.lifetime
: emplaceRef
;
323 assert(chunk
.length
>= T
.sizeof
, "chunk size too small.");
324 assert((cast(size_t
) chunk
.ptr
) % T
.alignof
== 0, "emplace: Chunk is not aligned.");
326 emplaceRef
!(T
, Unqual
!T
)(*cast(Unqual
!T
*) chunk
.ptr
, forward
!args
);
327 return cast(T
*) chunk
.ptr
;
338 void[S
.sizeof
] buf
= void;
342 auto s1
= emplace
!S(buf
, s
);
343 assert(s1
.a
== 42 && s1
.b
== 43);
346 // Bulk of emplace unittests starts here
349 @system unittest /* unions */
364 assert(u1
.a
== "hello");
367 @system unittest // bugzilla 15772
369 abstract class Foo
{}
372 // test in emplaceInitializer
373 static assert(!is(typeof(emplace
!Foo(cast(Foo
*) memory
.ptr
))));
374 static assert( is(typeof(emplace
!Bar(cast(Bar
*) memory
.ptr
))));
375 // test in the emplace overload that takes void[]
376 static assert(!is(typeof(emplace
!Foo(memory
))));
377 static assert( is(typeof(emplace
!Bar(memory
))));
383 struct S
{ @disable this(); }
385 static assert(!__traits(compiles
, emplace(&s
)));
423 static assert(!__traits(compiles
, emplace(&ss2
)));
426 static assert(!__traits(compiles
, emplace(&ss1
, s1
)));
442 assert(ss1
[0].i
== 5 && ss1
[1].i
== 5);
447 //Start testing emplace-args here
454 K k
= null, k2
= new K
;
470 void opAssign(S
){assert(0);}
475 assert(sa
[0].i
== 5 && sa
[1].i
== 5);
478 //Start testing emplace-struct here
480 // Test constructor branch
489 assert(x
== 5 && y
== 6);
495 void[S
.sizeof
] s1
= void;
497 assert(*emplace
!S(cast(S
*) s1
.ptr
, s2
) == s2
);
498 assert(*emplace
!S(cast(S
*) s1
, 44, 45) == S(44, 45));
503 static struct __conv_EmplaceTest
508 assert(this.i
== 3 && i
== 5);
511 this(int i
, ref int j
)
513 assert(i
== 5 && j
== 6);
524 __conv_EmplaceTest k
= void;
529 __conv_EmplaceTest x
= void;
535 auto z
= emplace
!__conv_EmplaceTest(new void[__conv_EmplaceTest
.sizeof
], 5, var
);
540 // Test matching fields branch
553 struct S
{ int a
, b
; this(int){} }
555 static assert(!__traits(compiles
, emplace
!S(&s
, 2, 3)));
561 struct S
{ int a
, b
= 7; }
562 S s1
= void, s2
= void;
565 assert(s1
.a
== 2 && s1
.b
== 7);
567 emplace
!S(&s2
, 2, 3);
568 assert(s2
.a
== 2 && s2
.b
== 3);
578 void opAssign(int){assert(0);}
579 void opAssign(S
){assert(0);}
590 //postblit precedence
594 //Works, but breaks in "-w -O" because of @@@9332@@@.
595 //Uncomment test when 9332 is fixed.
600 this(S other
){assert(false);}
601 this(int i
){this.i
= i
;}
605 assert(is(typeof({S b
= a
;}))); //Postblit
606 assert(is(typeof({S b
= S(a
);}))); //Constructor
616 static assert(!is(immutable S2
: S2
));
618 immutable is2
= (immutable S2
).init
;
622 //nested structs and postblit
628 this(int i
){p
= [i
].ptr
;}
638 void opAssign(const SS
)
646 assert(*ssa
.s
.p
== 5);
647 assert(ssa
.s
.p
!= ssb
.s
.p
);
662 static assert(!__traits(compiles
, emplace(&s1
, s1
))); // copy disabled
663 static assert(__traits(compiles
, emplace(&s1
, move(s1
)))); // move not affected
672 //static assert(!__traits(compiles, emplace(&s2, 1)));
673 emplace(&s2
, S2
.init
);
681 static assert(!__traits(compiles
, emplace(&ss1
, ss1
))); // copying disabled
682 static assert(__traits(compiles
, emplace(&ss1
, move(ss1
)))); // move unaffected
690 static assert(!__traits(compiles
, emplace(&ss2
, ss2
))); // copying disabled
691 static assert(__traits(compiles
, emplace(&ss2
, SS2
.init
))); // move is OK
694 // SS1 sss1 = s1; //This doesn't compile
695 // SS1 sss1 = SS1(s1); //This doesn't compile
696 // So emplace shouldn't compile either
697 static assert(!__traits(compiles
, emplace(&sss1
, s1
)));
698 static assert(!__traits(compiles
, emplace(&sss2
, s2
)));
705 //Castable immutability
711 static assert(is( immutable(S1
) : S1
));
713 auto sb
= immutable(S1
)(5);
717 //Un-castable immutability
723 static assert(!is(immutable(S2
) : S2
));
725 auto sb
= immutable(S2
)(null);
726 assert(!__traits(compiles
, emplace(&sa
, sb
)));
739 emplace(&s
, 1, null);
740 emplace(&s
, 2, &s
.i
);
741 assert(s
is S(2, &s
.i
));
790 SS1 ss
= SS1(1, S(2));
800 S
foo() @property{return s
;}
804 SS2 ss
= SS2(1, S(2));
810 version (CoreUnittest
)
813 private struct __std_conv_S
816 this(__std_conv_SS ss
) {assert(0);}
817 static opCall(__std_conv_SS ss
)
819 __std_conv_S s
; s
.i
= ss
.j
;
823 private struct __std_conv_SS
827 ref __std_conv_S
foo() return @property {s
.i
= j
; return s
;}
834 static assert(is(__std_conv_SS
: __std_conv_S
));
835 __std_conv_S s
= void;
836 __std_conv_SS ss
= __std_conv_SS(1);
838 __std_conv_S sTest1
= ss
; //this calls "SS alias this" (and not "S.this(SS)")
839 emplace(&s
, ss
); //"alias this" should take precedence in emplace over "opCall"
854 assert(s1
.a
is s2
.a
);
857 //safety & nothrow & CTFE
861 //emplace should be safe for anything with no elaborate opassign
869 this(int j
)@safe nothrow{i
= j
;}
880 void foo() @safe nothrow
886 emplace(ps1
, S1
.init
);
889 emplace(ps2
, S2
.init
);
895 T t
/+ = void+/; //CTFE void illegal
901 static assert(a
== 5);
903 static assert(b
.i
== 5);
905 static assert(c
.i
== 5);
920 int[2] get(){return [1, 2];}
936 assert(ss
.ii
== [1, 2]);
937 assert(iss
.ii
== [1, 2]);
946 @disable void opAssign(S
);
957 //Without constructor
962 static S1
opCall(int*){assert(0);}
965 static assert(!__traits(compiles
, emplace(&s
, 1)));
972 static S2
opCall(int*){assert(0);}
973 static S2
opCall(int){assert(0);}
974 this(int i
){this.i
= i
;}
980 //With postblit ambiguity
985 static S3
opCall(ref S3
){assert(0);}
988 emplace(&s
, S3
.init
);
1001 immutable int[2] ii
;
1012 static assert(!__traits(compiles
, {S ss
= S(uu
);}));
1013 static assert(!__traits(compiles
, emplace(&s
, uu
)));
1026 emplace(&sii
, sii2
);
1027 //emplace(&sii, uii2); //Sorry, this implementation doesn't know how to...
1028 //emplace(&uii, sii2); //Sorry, this implementation doesn't know how to...
1029 emplace(&uii
, uii2
);
1030 emplace(&sii
, sii2
[]);
1031 //emplace(&sii, uii2[]); //Sorry, this implementation doesn't know how to...
1032 //emplace(&uii, sii2[]); //Sorry, this implementation doesn't know how to...
1033 emplace(&uii
, uii2
[]);
1038 bool allowDestruction
= false;
1043 ~this(){assert(allowDestruction
);}
1051 emplace(&ss3
, ss2
[]);
1052 assert(ss1
[1] == s
);
1053 assert(ss2
[1] == s
);
1054 assert(ss3
[1] == s
);
1055 allowDestruction
= true;
1060 //Checks postblit, construction, and context pointer
1090 S
[2][2][2] sss
= void;
1094 @system unittest //Constness
1096 import core
.internal
.lifetime
: emplaceRef
;
1099 emplaceRef
!(const int)(a
, 5);
1102 const(int)* p
= void;
1103 emplaceRef
!(const int*)(p
, &i
);
1109 alias IS
= immutable(S
);
1111 emplaceRef
!IS(s
, IS());
1113 emplaceRef
!(IS
[2])(ss
, IS());
1115 IS
[2] iss
= IS
.init
;
1116 emplaceRef
!(IS
[2])(ss
, iss
);
1117 emplaceRef
!(IS
[2])(ss
, iss
[]);
1121 pure nothrow @safe @nogc unittest
1123 import core
.internal
.lifetime
: emplaceRef
;
1129 emplaceRef
!int(i
, 5);
1132 // Test attribute propagation for UDTs
1133 pure nothrow @safe /* @nogc */ unittest
1135 import core
.internal
.lifetime
: emplaceRef
;
1139 this(this) pure nothrow @safe @nogc {}
1143 emplaceRef(safe
, Safe());
1145 Safe
[1] safeArr
= [Safe()];
1146 Safe
[1] uninitializedSafeArr
= void;
1147 emplaceRef(uninitializedSafeArr
, safe
);
1148 emplaceRef(uninitializedSafeArr
, safeArr
);
1150 static struct Unsafe
1152 this(this) @system {}
1155 Unsafe unsafe
= void;
1156 static assert(!__traits(compiles
, emplaceRef(unsafe
, unsafe
)));
1158 Unsafe
[1] unsafeArr
= [Unsafe()];
1159 Unsafe
[1] uninitializedUnsafeArr
= void;
1160 static assert(!__traits(compiles
, emplaceRef(uninitializedUnsafeArr
, unsafe
)));
1161 static assert(!__traits(compiles
, emplaceRef(uninitializedUnsafeArr
, unsafeArr
)));
1175 import core
.stdc
.stdlib
: malloc
;
1176 void[] buf
= malloc(Node
.sizeof
)[0 .. Node
.sizeof
];
1178 const Node
* n
= emplace
!(const Node
)(buf
, 42, null, 10);
1179 assert(n
.payload
== 42);
1180 assert(n
.next
== null);
1181 assert(n
.refs
== 10);
1192 assert(x
== 5 && y
== 42);
1198 static align(__traits(classInstanceAlignment
, A
)) byte[__traits(classInstanceSize
, A
)] sbuf
;
1200 auto a
= emplace
!A(buf
, 55);
1201 assert(a
.x
== 55 && a
.y
== 55);
1203 // emplace in bigger buffer
1204 buf
= new byte[](__traits(classInstanceSize
, A
) + 10);
1205 a
= emplace
!A(buf
, 55);
1206 assert(a
.x
== 55 && a
.y
== 55);
1209 static assert(!is(typeof(emplace
!A(buf
))));
1212 //constructor arguments forwarding
1218 this()(auto ref long arg
)
1220 // assert that arg is an lvalue
1221 static assert(__traits(isRef
, arg
));
1223 this()(auto ref double arg
)
1224 // assert that arg is an rvalue
1226 static assert(!__traits(isRef
, arg
));
1231 emplace(&obj
, i
); // lvalue
1232 emplace(&obj
, 0.0); // rvalue
1234 // Bulk of emplace unittests ends here
1237 * Emplaces a copy of the specified source value into uninitialized memory,
1238 * i.e., simulates `T target = source` copy-construction for cases where the
1239 * target memory is already allocated and to be initialized with a copy.
1242 * source = value to be copied into target
1243 * target = uninitialized value to be initialized with a copy of source
1245 void copyEmplace(S
, T
)(ref S source
, ref T target
) @system
1246 if (is(immutable S
== immutable T
))
1248 import core
.internal
.traits
: BaseElemOf
, hasElaborateCopyConstructor
, Unconst
, Unqual
;
1250 // cannot have the following as simple template constraint due to nested-struct special case...
1251 static if (!__traits(compiles
, (ref S src
) { T tgt
= src
; }))
1253 alias B
= BaseElemOf
!T
;
1254 enum isNestedStruct
= is(B
== struct) && __traits(isNested
, B
);
1255 static assert(isNestedStruct
, "cannot copy-construct " ~ T
.stringof
~ " from " ~ S
.stringof
);
1260 import core
.stdc
.string
: memcpy
;
1261 memcpy(cast(Unqual
!(T
)*) &target
, cast(Unqual
!(T
)*) &source
, T
.sizeof
);
1264 static if (is(T
== struct))
1266 static if (__traits(hasPostblit
, T
))
1269 (cast() target
).__xpostblit();
1271 else static if (__traits(hasCopyConstructor
, T
))
1273 // https://issues.dlang.org/show_bug.cgi?id=22766
1274 import core
.internal
.lifetime
: emplaceInitializer
;
1275 emplaceInitializer(*(cast(Unqual
!T
*)&target
));
1276 static if (__traits(isNested
, T
))
1278 // copy context pointer
1279 *(cast(void**) &target
.tupleof
[$-1]) = cast(void*) source
.tupleof
[$-1];
1281 target
.__ctor(source
); // invoke copy ctor
1285 blit(); // no opAssign
1288 else static if (is(T
== E
[n
], E
, size_t n
))
1290 static if (hasElaborateCopyConstructor
!E
)
1295 for (i
= 0; i
< n
; i
++)
1296 copyEmplace(source
[i
], target
[i
]);
1300 // destroy, in reverse order, what we've constructed so far
1302 destroy(*cast(Unconst
!(E
)*) &target
[i
]);
1306 else // trivial copy
1308 blit(); // all elements at once
1313 *cast(Unconst
!(T
)*) &target
= *cast(Unconst
!(T
)*) &source
;
1319 @system pure nothrow @nogc unittest
1323 copyEmplace(source
, target
);
1324 assert(target
== 123);
1329 @system pure nothrow @nogc unittest
1331 immutable int[1][1] source
= [ [123] ];
1332 immutable int[1][1] target
= void;
1333 copyEmplace(source
, target
);
1334 assert(target
[0][0] == 123);
1339 @system pure nothrow @nogc unittest
1344 void opAssign(const scope ref S rhs
) @safe pure nothrow @nogc
1352 copyEmplace(source
, target
);
1353 assert(target
.x
== 42);
1356 // preserve shared-ness
1357 @system pure nothrow unittest
1359 auto s
= new Object();
1360 auto ss
= new shared Object();
1368 copyEmplace(ss
, st
);
1371 static assert(!__traits(compiles
, copyEmplace(s
, st
)));
1372 static assert(!__traits(compiles
, copyEmplace(ss
, t
)));
1375 // https://issues.dlang.org/show_bug.cgi?id=22766
1376 @system pure nothrow @nogc unittest
1381 this(int) @safe pure nothrow @nogc{}
1382 this(ref const(S
) other
) @safe pure nothrow @nogc {}
1387 copyEmplace(s1
, s2
);
1391 version (DigitalMars
) version (X86
) version (Posix
) version = DMD_X86_Posix
;
1393 // don't violate immutability for reference types
1394 @system pure nothrow unittest
1396 auto s
= new Object();
1397 auto si
= new immutable Object();
1400 immutable Object ti
;
1405 copyEmplace(si
, ti
);
1406 version (DMD_X86_Posix
) { /* wrongly fails without -O */ } else
1409 static assert(!__traits(compiles
, copyEmplace(s
, ti
)));
1410 static assert(!__traits(compiles
, copyEmplace(si
, t
)));
1413 version (CoreUnittest
)
1415 private void testCopyEmplace(S
, T
)(const scope T
* expected
= null)
1419 copyEmplace(source
, target
);
1421 assert(target
== *expected
);
1424 T expectedCopy
= source
;
1425 assert(target
== expectedCopy
);
1431 @system pure nothrow @nogc unittest
1435 @safe pure nothrow @nogc:
1437 this(this) { x
+= 10; }
1440 testCopyEmplace
!(S
, S
)();
1441 testCopyEmplace
!(immutable S
, S
)();
1442 testCopyEmplace
!(S
, immutable S
)();
1443 testCopyEmplace
!(immutable S
, immutable S
)();
1445 testCopyEmplace
!(S
[1], S
[1])();
1446 testCopyEmplace
!(immutable S
[1], S
[1])();
1448 // copying to an immutable static array works, but `T expected = source`
1449 // wrongly ignores the postblit: https://issues.dlang.org/show_bug.cgi?id=8950
1450 immutable S
[1] expectedImmutable
= [S(52)];
1451 testCopyEmplace
!(S
[1], immutable S
[1])(&expectedImmutable
);
1452 testCopyEmplace
!(immutable S
[1], immutable S
[1])(&expectedImmutable
);
1455 // copy constructors
1456 @system pure nothrow @nogc unittest
1460 @safe pure nothrow @nogc:
1462 this(int x
) { this.x
= x
; }
1463 this(const scope ref S rhs
) { x
= rhs
.x
+ 10; }
1464 this(const scope ref S rhs
) immutable { x
= rhs
.x
+ 20; }
1467 testCopyEmplace
!(S
, S
)();
1468 testCopyEmplace
!(immutable S
, S
)();
1469 testCopyEmplace
!(S
, immutable S
)();
1470 testCopyEmplace
!(immutable S
, immutable S
)();
1472 // static arrays work, but `T expected = source` wrongly ignores copy ctors
1473 // https://issues.dlang.org/show_bug.cgi?id=20365
1474 S
[1] expectedMutable
= [S(52)];
1475 immutable S
[1] expectedImmutable
= [immutable S(62)];
1476 testCopyEmplace
!(S
[1], S
[1])(&expectedMutable
);
1477 testCopyEmplace
!(immutable S
[1], S
[1])(&expectedMutable
);
1478 testCopyEmplace
!(S
[1], immutable S
[1])(&expectedImmutable
);
1479 testCopyEmplace
!(immutable S
[1], immutable S
[1])(&expectedImmutable
);
1482 // copy constructor in nested struct
1483 @system pure nothrow unittest
1488 @safe pure nothrow @nogc:
1490 this(size_t x
) { this.x
= x
; }
1491 this(const scope ref S rhs
)
1493 assert(x
== 42); // T.init
1502 immutable S target
= void;
1503 copyEmplace(source
, target
);
1504 assert(target
is source
);
1505 assert(copies
== 1);
1510 immutable S
[1] source
= [immutable S(456)];
1512 copyEmplace(source
, target
);
1513 assert(target
[0] is source
[0]);
1514 assert(copies
== 1);
1518 // destruction of partially copied static array
1523 __gshared
int[] deletions
;
1525 this(this) { if (x
== 5) throw new Exception(""); }
1526 ~this() { deletions
~= x
; }
1529 alias T
= immutable S
[3][2];
1530 T source
= [ [S(1), S(2), S(3)], [S(4), S(5), S(6)] ];
1534 copyEmplace(source
, target
);
1539 static immutable expectedDeletions
= [ 4, 3, 2, 1 ];
1540 version (DigitalMars
)
1542 assert(S
.deletions
== expectedDeletions ||
1543 S
.deletions
== [ 4 ]); // FIXME: happens with -O
1546 assert(S
.deletions
== expectedDeletions
);
1551 Forwards function arguments while keeping `out`, `ref`, and `lazy` on
1555 args = a parameter list or an $(REF AliasSeq,std,meta).
1557 An `AliasSeq` of `args` with `out`, `ref`, and `lazy` saved.
1559 template forward(args
...)
1561 import core
.internal
.traits
: AliasSeq
;
1563 template fwd(alias arg
)
1565 // by ref || lazy || const/immutable
1566 static if (__traits(isRef
, arg
) ||
1567 __traits(isOut
, arg
) ||
1568 __traits(isLazy
, arg
) ||
1569 !is(typeof(move(arg
))))
1573 @property auto fwd(){ pragma(inline
, true); return move(arg
); }
1576 alias Result
= AliasSeq
!();
1577 static foreach (arg
; args
)
1578 Result
= AliasSeq
!(Result
, fwd
!arg
);
1579 static if (Result
.length
== 1)
1580 alias forward
= Result
[0];
1582 alias forward
= Result
;
1590 static int foo(int n
) { return 1; }
1591 static int foo(ref int n
) { return 2; }
1595 int bar()(auto ref int x
) { return C
.foo(forward
!x
); }
1598 int baz()(auto ref int x
) { return C
.foo(x
); }
1601 assert(bar(1) == 1);
1602 assert(bar(i
) == 2);
1604 assert(baz(1) == 2);
1605 assert(baz(i
) == 2);
1611 void foo(int n
, ref string s
) { s
= null; foreach (i
; 0 .. n
) s
~= "Hello"; }
1613 // forwards all arguments which are bound to parameter tuple
1614 void bar(Args
...)(auto ref Args args
) { return foo(forward
!args
); }
1616 // forwards all arguments with swapping order
1617 void baz(Args
...)(auto ref Args args
) { return foo(forward
!args
[$/2..$], forward
!args
[0..$/2]); }
1621 assert(s
== "Hello");
1623 assert(s
== "HelloHello");
1628 auto foo(TL
...)(auto ref TL args
)
1631 foreach (i
, _
; args
)
1633 //pragma(msg, "[",i,"] ", __traits(isRef, args[i]) ? "L" : "R");
1634 result
~= __traits(isRef
, args
[i
]) ?
"L" : "R";
1639 string
bar(TL
...)(auto ref TL args
)
1641 return foo(forward
!args
);
1643 string
baz(TL
...)(auto ref TL args
)
1646 return foo(forward
!args
[3], forward
!args
[2], 1, forward
!args
[1], forward
!args
[0], x
);
1650 S
makeS(){ return S(); }
1653 assert(bar(S(), makeS(), n
, s
) == "RRLL");
1654 assert(baz(S(), makeS(), n
, s
) == "LLRRRL");
1660 ref int foo(return ref int a
) { return a
; }
1661 ref int bar(Args
)(auto ref Args args
)
1663 return foo(forward
!args
);
1665 static assert(!__traits(compiles
, { auto x1
= bar(3); })); // case of NG
1667 auto x2
= bar(value
); // case of OK
1685 this()(auto ref X x
)
1694 this()(auto ref X x
)
1698 this()(auto const ref X x
)
1706 auto constX
= (){ const X x
; return x
; };
1707 static assert(__traits(compiles
, { Y y
= x
; }));
1708 static assert(__traits(compiles
, { Y y
= X(); }));
1709 static assert(!__traits(compiles
, { Y y
= cx
; }));
1710 static assert(!__traits(compiles
, { Y y
= constX(); }));
1711 static assert(__traits(compiles
, { Z z
= x
; }));
1712 static assert(__traits(compiles
, { Z z
= X(); }));
1713 static assert(__traits(compiles
, { Z z
= cx
; }));
1714 static assert(__traits(compiles
, { Z z
= constX(); }));
1719 assert(y1
.x_
.i
== 1);
1722 assert(y2
.x_
.i
== 0);
1726 assert(z1
.x_
.i
== 1);
1729 assert(z2
.x_
.i
== 0);
1731 // ref const lvalue, copy
1732 assert(z3
.x_
.i
== 1);
1734 // const rvalue, copy
1735 assert(z4
.x_
.i
== 1);
1742 int foo1(lazy int i
) { return i
; }
1743 int foo2(A
)(auto ref A i
) { return foo1(forward
!i
); }
1744 int foo3(lazy int i
) { return foo2(i
); }
1747 assert(foo3({ ++numCalls
; return 42; }()) == 42);
1748 assert(numCalls
== 1);
1755 int foo1(int a
, int b
) { return a
+ b
; }
1756 int foo2(A
...)(auto ref A args
) { return foo1(forward
!args
); }
1757 int foo3(int a
, lazy int b
) { return foo2(a
, b
); }
1760 assert(foo3(11, { ++numCalls
; return 31; }()) == 42);
1761 assert(numCalls
== 1);
1768 int foo1(int a
, lazy int b
) { return a
+ b
; }
1769 int foo2(A
...)(auto ref A args
) { return foo1(forward
!args
); }
1770 int foo3(int a
, int b
) { return foo2(a
, b
); }
1772 assert(foo3(11, 31) == 42);
1779 void foo1(int a
, out int b
) { b
= a
; }
1780 void foo2(A
...)(auto ref A args
) { foo1(forward
!args
); }
1781 void foo3(int a
, out int b
) { foo2(a
, b
); }
1790 Moves `source` into `target`, via a destructive copy when necessary.
1792 If `T` is a struct with a destructor or postblit defined, source is reset
1793 to its `.init` value after it is moved into target, otherwise it is
1797 If source has internal pointers that point to itself and doesn't define
1798 opPostMove, it cannot be moved, and will trigger an assertion failure.
1801 source = Data to copy.
1802 target = Where to copy into. The destructor, if any, is invoked before the
1805 void move(T
)(ref T source
, ref T target
)
1807 moveImpl(target
, source
);
1810 /// For non-struct types, `move` just performs `target = source`:
1813 Object obj1
= new Object
;
1818 assert(obj3
is obj1
);
1820 assert(obj2
is obj1
);
1824 pure nothrow @safe @nogc unittest
1826 // Structs without destructors are simply copied
1832 S1 s11
= { 10, 11 };
1837 assert(s12
== S1(10, 11));
1840 // But structs with destructors or postblits are reset to their .init value
1841 // after copying to the target.
1847 ~this() pure nothrow @safe @nogc { }
1854 assert(s21
== S2(1, 2));
1855 assert(s22
== S2(3, 4));
1860 import core
.internal
.traits
;
1863 Object obj1
= new Object
;
1867 assert(obj3
is obj1
);
1869 static struct S1
{ int a
= 1, b
= 2; }
1870 S1 s11
= { 10, 11 };
1873 assert(s11
.a
== 10 && s11
.b
== 11 && s12
.a
== 10 && s12
.b
== 11);
1875 static struct S2
{ int a
= 1; int * b
; }
1876 S2 s21
= { 10, null };
1882 // Issue 5661 test(1)
1885 static struct X
{ int n
= 0; ~this(){n
= 0;} }
1888 static assert(hasElaborateDestructor
!S3
);
1892 assert(s31
.x
.n
== 0);
1893 assert(s32
.x
.n
== 1);
1895 // Issue 5661 test(2)
1898 static struct X
{ int n
= 0; this(this){n
= 0;} }
1901 static assert(hasElaborateCopyConstructor
!S4
);
1905 assert(s41
.x
.n
== 0);
1906 assert(s42
.x
.n
== 1);
1919 T
move(T
)(return scope ref T source
)
1921 return moveImpl(source
);
1924 /// Non-copyable structs can still be moved:
1925 pure nothrow @safe @nogc unittest
1930 @disable this(this);
1931 ~this() pure nothrow @safe @nogc {}
1940 // https://issues.dlang.org/show_bug.cgi?id=20869
1941 // `move` should propagate the attributes of `opPostMove`
1946 void opPostMove(const ref S old
) nothrow @system
1949 new int(i
++); // Force @gc impure @system
1953 alias T
= void function() @system nothrow;
1954 static assert(is(typeof({ S s
; move(s
); }) == T
));
1955 static assert(is(typeof({ S s
; move(s
, s
); }) == T
));
1958 private void moveImpl(T
)(scope ref T target
, return scope ref T source
)
1960 import core
.internal
.traits
: hasElaborateDestructor
;
1962 static if (is(T
== struct))
1964 // Unsafe when compiling without -preview=dip1000
1965 if ((() @trusted => &source
== &target
)()) return;
1966 // Destroy target before overwriting it
1967 static if (hasElaborateDestructor
!T
) target
.__xdtor();
1969 // move and emplace source into target
1970 moveEmplaceImpl(target
, source
);
1973 private T
moveImpl(T
)(return scope ref T source
)
1975 // Properly infer safety from moveEmplaceImpl as the implementation below
1976 // might void-initialize pointers in result and hence needs to be @trusted
1977 if (false) moveEmplaceImpl(source
, source
);
1979 return trustedMoveImpl(source
);
1982 private T
trustedMoveImpl(T
)(return scope ref T source
) @trusted
1985 moveEmplaceImpl(result
, source
);
1991 import core
.internal
.traits
;
1994 Object obj1
= new Object
;
1996 Object obj3
= move(obj2
);
1997 assert(obj3
is obj1
);
1999 static struct S1
{ int a
= 1, b
= 2; }
2000 S1 s11
= { 10, 11 };
2002 assert(s11
.a
== 10 && s11
.b
== 11 && s12
.a
== 10 && s12
.b
== 11);
2004 static struct S2
{ int a
= 1; int * b
; }
2005 S2 s21
= { 10, null };
2011 // Issue 5661 test(1)
2014 static struct X
{ int n
= 0; ~this(){n
= 0;} }
2017 static assert(hasElaborateDestructor
!S3
);
2021 assert(s31
.x
.n
== 0);
2022 assert(s32
.x
.n
== 1);
2024 // Issue 5661 test(2)
2027 static struct X
{ int n
= 0; this(this){n
= 0;} }
2030 static assert(hasElaborateCopyConstructor
!S4
);
2034 assert(s41
.x
.n
== 0);
2035 assert(s42
.x
.n
== 1);
2050 static struct S
{ int n
= 0; ~this() @system { n
= 0; } }
2052 static assert(!__traits(compiles
, () @safe { move(a
, b
); }));
2053 static assert(!__traits(compiles
, () @safe { move(a
); }));
2055 () @trusted { move(a
, b
); }();
2058 () @trusted { move(a
); }();
2061 /+ this can't be tested in druntime, tests are still run in phobos
2062 @safe unittest//Issue 6217
2064 import std.algorithm.iteration : map;
2065 auto x = map!"a"([1,2,3]);
2070 @safe unittest// Issue 8055
2090 @system unittest// Issue 8057
2098 // Access to enclosing scope
2104 // Move nested struct
2113 static struct Array(T
)
2115 // nested struct has no member
2121 Array
!int.Payload x
= void;
2126 private enum bool hasContextPointers(T
) = {
2127 static if (__traits(isStaticArray
, T
))
2129 return hasContextPointers
!(typeof(T
.init
[0]));
2131 else static if (is(T
== struct))
2133 import core
.internal
.traits
: anySatisfy
;
2134 return __traits(isNested
, T
) || anySatisfy
!(hasContextPointers
, typeof(T
.tupleof
));
2139 @safe @nogc nothrow pure unittest
2141 static assert(!hasContextPointers
!int);
2142 static assert(!hasContextPointers
!(void*));
2145 static assert(!hasContextPointers
!S
);
2146 static assert(!hasContextPointers
!(S
[1]));
2153 static assert(hasContextPointers
!Nested
);
2154 static assert(hasContextPointers
!(Nested
[1]));
2156 static struct OneLevel
2163 static assert(hasContextPointers
!OneLevel
);
2164 static assert(hasContextPointers
!(OneLevel
[1]));
2166 static struct TwoLevels
2173 static assert(hasContextPointers
!TwoLevels
);
2174 static assert(hasContextPointers
!(TwoLevels
[1]));
2181 // unions can have false positives, so this query ignores them
2182 static assert(!hasContextPointers
!U
);
2185 // target must be first-parameter, because in void-functions DMD + dip1000 allows it to take the place of a return-scope
2186 private void moveEmplaceImpl(T
)(scope ref T target
, return scope ref T source
)
2188 // TODO: this assert pulls in half of phobos. we need to work out an alternative assert strategy.
2189 // static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
2191 // import std.exception : doesPointTo;
2192 // assert(!doesPointTo(source, source) && !hasElaborateMove!T),
2193 // "Cannot move object with internal pointer unless `opPostMove` is defined.");
2196 import core
.internal
.traits
: hasElaborateAssign
, isAssignable
, hasElaborateMove
,
2197 hasElaborateDestructor
, hasElaborateCopyConstructor
;
2198 static if (is(T
== struct))
2201 // Unsafe when compiling without -preview=dip1000
2202 assert((() @trusted => &source
!is &target
)(), "source and target must not be identical");
2204 static if (hasElaborateAssign
!T ||
!isAssignable
!T
)
2206 import core
.stdc
.string
: memcpy
;
2207 () @trusted { memcpy(&target
, &source
, T
.sizeof
); }();
2212 static if (hasElaborateMove
!T
)
2213 __move_post_blt(target
, source
);
2215 // If the source defines a destructor or a postblit hook, we must obliterate the
2216 // object in order to avoid double freeing and undue aliasing
2217 static if (hasElaborateDestructor
!T || hasElaborateCopyConstructor
!T
)
2219 // If there are members that are nested structs, we must take care
2220 // not to erase any context pointers, so we might have to recurse
2221 static if (__traits(isZeroInit
, T
))
2224 wipe(source
, ref () @trusted { return *cast(immutable(T
)*) __traits(initSymbol
, T
).ptr
; } ());
2227 else static if (__traits(isStaticArray
, T
))
2229 static if (T
.length
)
2231 static if (!hasElaborateMove
!T
&&
2232 !hasElaborateDestructor
!T
&&
2233 !hasElaborateCopyConstructor
!T
)
2235 // Single blit if no special per-instance handling is required
2238 assert(source
.ptr
!is target
.ptr
, "source and target must not be identical");
2239 *cast(ubyte[T
.sizeof
]*) &target
= *cast(ubyte[T
.sizeof
]*) &source
;
2244 for (size_t i
= 0; i
< source
.length
; ++i
)
2245 moveEmplaceImpl(target
[i
], source
[i
]);
2251 // Primitive data (including pointers and arrays) or class -
2252 // assignment works great
2258 * Similar to $(LREF move) but assumes `target` is uninitialized. This
2259 * is more efficient because `source` can be blitted over `target`
2260 * without destroying or initializing it first.
2263 * source = value to be moved into target
2264 * target = uninitialized value to be filled by source
2266 void moveEmplace(T
)(ref T source
, ref T target
) @system
2268 moveEmplaceImpl(target
, source
);
2273 pure nothrow @nogc @system unittest
2278 this(int* ptr
) { _ptr
= ptr
; }
2279 ~this() { if (_ptr
) ++*_ptr
; }
2284 Foo foo1
= void; // uninitialized
2285 auto foo2
= Foo(&val
); // initialized
2286 assert(foo2
._ptr
is &val
);
2288 // Using `move(foo2, foo1)` would have an undefined effect because it would destroy
2289 // the uninitialized foo1.
2290 // moveEmplace directly overwrites foo1 without destroying or initializing it first.
2291 moveEmplace(foo2
, foo1
);
2292 assert(foo1
._ptr
is &val
);
2293 assert(foo2
._ptr
is null);
2298 pure nothrow @nogc @system unittest
2303 this(int* ptr
) { _ptr
= ptr
; }
2304 ~this() { if (_ptr
) ++*_ptr
; }
2310 Foo
[1] foo1
= void; // uninitialized
2311 Foo
[1] foo2
= [Foo(&val
)];// initialized
2312 assert(foo2
[0]._ptr
is &val
);
2314 // Using `move(foo2, foo1)` would have an undefined effect because it would destroy
2315 // the uninitialized foo1.
2316 // moveEmplace directly overwrites foo1 without destroying or initializing it first.
2317 moveEmplace(foo2
, foo1
);
2318 assert(foo1
[0]._ptr
is &val
);
2319 assert(foo2
[0]._ptr
is null);
2328 static struct NoCopy
2332 @disable this(this);
2335 static void f(NoCopy
[2]) { }
2337 NoCopy
[2] ncarray
= [ NoCopy(1), NoCopy(2) ];
2339 static assert(!__traits(compiles
, f(ncarray
)));
2347 import core
.stdc
.stdio
;
2350 /// Implementation of `_d_delstruct` and `_d_delstructTrace`
2351 template _d_delstructImpl(T
)
2353 private void _d_delstructImpure(ref T p
)
2355 debug(PRINTF
) printf("_d_delstruct(%p)\n", p
);
2357 import core
.memory
: GC
;
2365 * This is called for a delete statement where the value being deleted is a
2366 * pointer to a struct with a destructor but doesn't have an overloaded
2367 * `delete` operator.
2370 * p = pointer to the value to be deleted
2373 * This function template was ported from a much older runtime hook that
2374 * bypassed safety, purity, and throwabilty checks. To prevent breaking
2375 * existing code, this function template is temporarily declared
2376 * `@trusted` until the implementation can be brought up to modern D
2379 void _d_delstruct(ref T p
) @trusted @nogc pure nothrow
2383 alias Type
= void function(ref T P
) @nogc pure nothrow;
2384 (cast(Type
) &_d_delstructImpure
)(p
);
2388 version (D_ProfileGC
)
2390 import core
.internal
.array
.utils
: _d_HookTraceImpl
;
2392 private enum errorMessage
= "Cannot delete struct if compiling without support for runtime type information!";
2395 * TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl).
2398 * This function template was ported from a much older runtime hook that
2399 * bypassed safety, purity, and throwabilty checks. To prevent breaking
2400 * existing code, this function template is temporarily declared
2401 * `@trusted` until the implementation can be brought up to modern D
2404 alias _d_delstructTrace
= _d_HookTraceImpl
!(T
, _d_delstruct
, errorMessage
);
2408 @system pure nothrow unittest
2411 struct S
{ ~this() nothrow { ++dtors
; } }
2414 _d_delstructImpl
!(typeof(s
))._d_delstruct(s
);
2420 @system pure unittest
2425 struct Inner
{ ~this() { ++innerDtors
; } }
2441 _d_delstructImpl
!(typeof(i1
))._d_delstruct(i1
);
2444 _d_delstructImpl
!(typeof(i2
))._d_delstruct(i2
);
2449 Outer
*o
= new Outer(0);
2450 _d_delstructImpl
!(typeof(o
))._d_delstruct(o
);
2453 assert(innerDtors
== 2);
2454 assert(outerDtors
== 1);
2458 pure nothrow @system unittest
2464 char[1] arr
; // char.init is not 0
2469 Nested
[1] dst
= void;
2470 Nested
[1] src
= [Nested(['a'])];
2472 moveEmplace(src
, dst
);
2474 assert(dst
[0].arr
== ['a']);
2475 assert(src
[0].arr
== [char.init
]);
2476 assert(dst
[0].tupleof
[$-1] is src
[0].tupleof
[$-1]);
2490 static struct NotNested
2500 static struct Deeper
2505 static assert(__traits(isZeroInit
, Nested
));
2506 static assert(__traits(isZeroInit
, NotNested
));
2507 static assert(__traits(isZeroInit
, Deep
));
2508 static assert(__traits(isZeroInit
, Deeper
));
2511 auto a
= NotNested(Nested());
2512 assert(a
.n
.tupleof
[$-1]);
2514 assert(b
.n
.tupleof
[$-1]);
2515 assert(a
.n
.tupleof
[$-1] is b
.n
.tupleof
[$-1]);
2517 auto c
= Deep(NotNested(Nested()));
2519 assert(d
.nn
.n
.tupleof
[$-1]);
2520 assert(c
.nn
.n
.tupleof
[$-1] is d
.nn
.n
.tupleof
[$-1]);
2522 auto e
= Deeper([NotNested(Nested())]);
2524 assert(f
.nn
[0].n
.tupleof
[$-1]);
2525 assert(e
.nn
[0].n
.tupleof
[$-1] is f
.nn
[0].n
.tupleof
[$-1]);
2536 align(32) // better still find context pointer correctly!
2537 int[3] stuff
= [0, 1, 2];
2541 static struct NoAssign
2544 @disable void opAssign(typeof(this));
2547 static struct NotNested
2550 align(Nested
.alignof
* 4) // better still find context pointer correctly!
2552 auto after
= NoAssign(43);
2560 static struct Deeper
2565 static assert(!__traits(isZeroInit
, Nested
));
2566 static assert(!__traits(isZeroInit
, NotNested
));
2567 static assert(!__traits(isZeroInit
, Deep
));
2568 static assert(!__traits(isZeroInit
, Deeper
));
2571 auto a
= NotNested(1, Nested([3, 4, 5]), NoAssign(2));
2573 assert(b
.n
.tupleof
[$-1]);
2574 assert(a
.n
.tupleof
[$-1] is b
.n
.tupleof
[$-1]);
2575 assert(a
.n
.stuff
== [0, 1, 2]);
2576 assert(a
.before
== 42);
2577 assert(a
.after
== NoAssign(43));
2579 auto c
= Deep(NotNested(1, Nested([3, 4, 5]), NoAssign(2)));
2581 assert(d
.nn
.n
.tupleof
[$-1]);
2582 assert(c
.nn
.n
.tupleof
[$-1] is d
.nn
.n
.tupleof
[$-1]);
2583 assert(c
.nn
.n
.stuff
== [0, 1, 2]);
2584 assert(c
.nn
.before
== 42);
2585 assert(c
.nn
.after
== NoAssign(43));
2587 auto e
= Deeper([NotNested(1, Nested([3, 4, 5]), NoAssign(2))]);
2589 assert(f
.nn
[0].n
.tupleof
[$-1]);
2590 assert(e
.nn
[0].n
.tupleof
[$-1] is f
.nn
[0].n
.tupleof
[$-1]);
2591 assert(e
.nn
[0].n
.stuff
== [0, 1, 2]);
2592 assert(e
.nn
[0].before
== 42);
2593 assert(e
.nn
[0].after
== NoAssign(43));
2598 // wipes source after moving
2599 pragma(inline
, true)
2600 private void wipe(T
, Init
...)(return scope ref T source
, ref const scope Init initializer
) @trusted
2602 ((Init
.length
== 1) && (is(immutable T
== immutable Init
[0]))))
2604 static if (__traits(isStaticArray
, T
) && hasContextPointers
!T
)
2606 for (auto i
= 0; i
< T
.length
; i
++)
2607 static if (Init
.length
)
2608 wipe(source
[i
], initializer
[0][i
]);
2612 else static if (is(T
== struct) && hasContextPointers
!T
)
2614 import core
.internal
.traits
: anySatisfy
;
2615 static if (anySatisfy
!(hasContextPointers
, typeof(T
.tupleof
)))
2617 static foreach (i
; 0 .. T
.tupleof
.length
- __traits(isNested
, T
))
2618 static if (Init
.length
)
2619 wipe(source
.tupleof
[i
], initializer
[0].tupleof
[i
]);
2621 wipe(source
.tupleof
[i
]);
2625 static if (__traits(isNested
, T
))
2626 enum sz
= T
.tupleof
[$-1].offsetof
;
2630 static if (Init
.length
)
2631 *cast(ubyte[sz
]*) &source
= *cast(ubyte[sz
]*) &initializer
[0];
2633 *cast(ubyte[sz
]*) &source
= 0;
2638 import core
.internal
.traits
: hasElaborateAssign
, isAssignable
;
2639 static if (Init
.length
)
2641 static if (hasElaborateAssign
!T ||
!isAssignable
!T
)
2642 *cast(ubyte[T
.sizeof
]*) &source
= *cast(ubyte[T
.sizeof
]*) &initializer
[0];
2644 source
= *cast(T
*) &initializer
[0];
2648 *cast(ubyte[T
.sizeof
]*) &source
= 0;
2654 * Allocate an exception of type `T` from the exception pool.
2655 * `T` must be `Throwable` or derived from it and cannot be a COM or C++ class.
2658 * This function does not call the constructor of `T` because that would require
2659 * `forward!args`, which causes errors with -dip1008. This inconvenience will be
2660 * removed once -dip1008 works as intended.
2663 * allocated instance of type `T`
2665 T
_d_newThrowable(T
)() @trusted
2666 if (is(T
: Throwable
) && __traits(getLinkage
, T
) == "D")
2668 debug(PRINTF
) printf("_d_newThrowable(%s)\n", cast(char*) T
.stringof
);
2670 import core
.memory
: pureMalloc
;
2671 auto init
= __traits(initSymbol
, T
);
2672 void* p
= pureMalloc(init
.length
);
2675 import core
.exception
: onOutOfMemoryError
;
2676 onOutOfMemoryError();
2679 debug(PRINTF
) printf(" p = %p\n", p
);
2682 p
[0 .. init
.length
] = init
[];
2684 import core
.internal
.traits
: hasIndirections
;
2685 if (hasIndirections
!T
)
2687 // Inform the GC about the pointers in the object instance
2688 import core
.memory
: GC
;
2689 GC
.addRange(p
, init
.length
);
2692 debug(PRINTF
) printf("initialization done\n");
2694 (cast(Throwable
) p
).refcount() = 1;
2703 this(string msg
= "", Throwable nextInChain
= null)
2705 super(msg
, nextInChain
);
2709 Throwable exc
= _d_newThrowable
!Exception();
2710 Throwable e
= _d_newThrowable
!E();
2712 assert(exc
.refcount() == 1);
2713 assert(e
.refcount() == 1);
2717 * Create a new class instance.
2718 * Allocates memory and sets fields to their initial value, but does not call a
2721 * new C() // _d_newclass!(C)()
2723 * Returns: newly created object
2725 T
_d_newclassT(T
)() @trusted
2728 import core
.internal
.traits
: hasIndirections
;
2729 import core
.exception
: onOutOfMemoryError
;
2730 import core
.memory
: GC
, pureMalloc
;
2732 alias BlkAttr
= GC
.BlkAttr
;
2734 auto init
= __traits(initSymbol
, T
);
2737 static if (__traits(getLinkage
, T
) == "Windows")
2739 p
= pureMalloc(init
.length
);
2741 onOutOfMemoryError();
2745 BlkAttr attr
= BlkAttr
.NONE
;
2747 /* `extern(C++)`` classes don't have a classinfo pointer in their vtable,
2748 * so the GC can't finalize them.
2750 static if (__traits(hasMember
, T
, "__dtor") && __traits(getLinkage
, T
) != "C++")
2751 attr |
= BlkAttr
.FINALIZE
;
2752 static if (!hasIndirections
!T
)
2753 attr |
= BlkAttr
.NO_SCAN
;
2755 p
= GC
.malloc(init
.length
, attr
, typeid(T
));
2756 debug(PRINTF
) printf(" p = %p\n", p
);
2761 printf("p = %p\n", p
);
2762 printf("init.ptr = %p, len = %llu\n", init
.ptr
, cast(ulong)init
.length
);
2763 printf("vptr = %p\n", *cast(void**) init
);
2764 printf("vtbl[0] = %p\n", (*cast(void***) init
)[0]);
2765 printf("vtbl[1] = %p\n", (*cast(void***) init
)[1]);
2766 printf("init[0] = %x\n", (cast(uint*) init
)[0]);
2767 printf("init[1] = %x\n", (cast(uint*) init
)[1]);
2768 printf("init[2] = %x\n", (cast(uint*) init
)[2]);
2769 printf("init[3] = %x\n", (cast(uint*) init
)[3]);
2770 printf("init[4] = %x\n", (cast(uint*) init
)[4]);
2774 p
[0 .. init
.length
] = init
[];
2776 debug(PRINTF
) printf("initialization done\n");
2784 C c
= _d_newclassT
!C();
2789 // Test initializers
2793 class C
{ int x
, y
; }
2794 C c
= _d_newclassT
!C();
2800 class C
{ int x
= 2, y
= 3; }
2801 C c
= _d_newclassT
!C();
2808 T
_d_newclassTTrace(T
)(string file
, int line
, string funcname
) @trusted
2810 version (D_TypeInfo
)
2812 import core
.internal
.array
.utils
: TraceHook
, gcStatsPure
, accumulatePure
;
2813 mixin(TraceHook
!(T
.stringof
, "_d_newclassT"));
2815 return _d_newclassT
!T();
2818 assert(0, "Cannot create new class if compiling without support for runtime type information!");