2 The `.dup` and `.idup` properties for Associative Arrays and Dynamic Arrays
4 Copyright: Copyright Digital Mars 2000 - 2022.
5 License: Distributed under the $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
6 (See accompanying file LICENSE)
7 Source: $(DRUNTIMESRC core/internal/_array/_duplication.d)
9 module core
.internal
.array
.duplication
;
11 U
[] _dup(T
, U
)(scope T
[] a
) pure nothrow @trusted if (__traits(isPOD
, T
))
14 return _dupCtfe
!(T
, U
)(a
);
18 return _dupCtfe
!(T
, U
)(a
);
22 import core
.stdc
.string
: memcpy
;
23 import core
.internal
.array
.construction
: _d_newarrayUPureNothrow
;
24 auto arr
= _d_newarrayUPureNothrow
!U(a
.length
, is(U
== shared));
25 memcpy(cast(void*) arr
.ptr
, cast(const(void)*) a
.ptr
, T
.sizeof
* a
.length
);
30 U
[] _dupCtfe(T
, U
)(scope T
[] a
)
32 static if (is(T
: void))
33 assert(0, "Cannot dup a void[] array at compile time.");
43 U
[] _dup(T
, U
)(T
[] a
) if (!__traits(isPOD
, T
))
45 // note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
46 // has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
48 return _dupCtfe
!(T
, U
)(a
);
52 return _dupCtfe
!(T
, U
)(a
);
56 import core
.lifetime
: copyEmplace
;
57 import core
.internal
.array
.construction
: _d_newarrayU
;
58 U
[] res
= () @trusted {
59 auto arr
= cast(U
*) _d_newarrayU
!T(a
.length
, is(T
== shared));
63 import core
.internal
.lifetime
: emplaceInitializer
;
64 // Initialize all remaining elements to not destruct garbage
65 foreach (j
; i
.. a
.length
)
66 emplaceInitializer(cast() arr
[j
]);
68 for (; i
< a
.length
; i
++)
70 copyEmplace(a
.ptr
[i
], arr
[i
]);
72 return cast(U
[])(arr
[0..a
.length
]);
79 // https://issues.dlang.org/show_bug.cgi?id=22107
88 void fun(scope S
[] values
...) @safe
96 static struct S1
{ int* p
; }
97 static struct S2
{ @disable this(); }
98 static struct S3
{ @disable this(this); }
100 int dg1() pure nothrow @safe
115 static assert(!is(typeof(m
.idup
)));
116 static assert(!is(typeof(i
.dup
)));
121 static assert(!is(typeof(m
.dup
)));
122 static assert(!is(typeof(i
.idup
)));
127 static assert(!is(typeof(m
.idup
)));
130 int[] a
= (inout(int)) { inout(const(int))[] a
; return a
.dup
; }(0);
135 int dg2() pure nothrow @safe
138 S2
[] m
= [S2
.init
, S2
.init
];
139 immutable(S2
)[] i
= [S2
.init
, S2
.init
];
156 static struct Sunpure
{ this(this) @safe nothrow {} }
157 static struct Sthrow
{ this(this) @safe pure {} }
158 static struct Sunsafe
{ this(this) @system pure nothrow {} }
159 static struct Snocopy
{ @disable this(this); }
163 cast(void) [].dup
!Sunsafe
;
164 static assert(!__traits(compiles
, () pure { [].dup
!Sunpure
; }));
165 static assert(!__traits(compiles
, () nothrow { [].dup
!Sthrow
; }));
166 static assert(!__traits(compiles
, () @safe { [].dup
!Sunsafe
; }));
167 static assert(!__traits(compiles
, () { [].dup
!Snocopy
; }));
172 static assert(!__traits(compiles
, () pure { [].idup
!Sunpure
; }));
173 static assert(!__traits(compiles
, () nothrow { [].idup
!Sthrow
; }));
174 static assert(!__traits(compiles
, () @safe { [].idup
!Sunsafe
; }));
175 static assert(!__traits(compiles
, () { [].idup
!Snocopy
; }));
180 // test that the copy-constructor is called with .dup
181 static struct ArrElem
188 this(ref const ArrElem
)
192 this(ref ArrElem
) immutable
198 auto arr
= [ArrElem(1), ArrElem(1)];
200 ArrElem
[] b
= arr
.dup
;
201 assert(b
[0].a
== 2 && b
[1].a
== 2);
203 immutable ArrElem
[] c
= arr
.idup
;
204 assert(c
[0].a
== 3 && c
[1].a
== 3);
209 static struct Sunpure
{ this(ref const typeof(this)) @safe nothrow {} }
210 static struct Sthrow
{ this(ref const typeof(this)) @safe pure {} }
211 static struct Sunsafe
{ this(ref const typeof(this)) @system pure nothrow {} }
214 cast(void) [].dup
!Sunsafe
;
215 static assert(!__traits(compiles
, () pure { [].dup
!Sunpure
; }));
216 static assert(!__traits(compiles
, () nothrow { [].dup
!Sthrow
; }));
217 static assert(!__traits(compiles
, () @safe { [].dup
!Sunsafe
; }));
219 // for idup to work on structs that have copy constructors, it is necessary
220 // that the struct defines a copy constructor that creates immutable objects
221 static struct ISunpure
{ this(ref const typeof(this)) immutable @safe nothrow {} }
222 static struct ISthrow
{ this(ref const typeof(this)) immutable @safe pure {} }
223 static struct ISunsafe
{ this(ref const typeof(this)) immutable @system pure nothrow {} }
227 static assert(!__traits(compiles
, () pure { [].idup
!ISunpure
; }));
228 static assert(!__traits(compiles
, () nothrow { [].idup
!ISthrow
; }));
229 static assert(!__traits(compiles
, () @safe { [].idup
!ISunsafe
; }));
234 static int*[] pureFoo() pure { return null; }
235 { char[] s
; immutable x
= s
.dup
; }
236 { immutable x
= (cast(int*[])null).dup
; }
237 { immutable x
= pureFoo(); }
238 { immutable x
= pureFoo().dup
; }
245 debug(SENTINEL
) {} else
246 assert(b
.capacity
>= 3);
253 shared(void)[] s
= [cast(shared)1];
254 immutable(void)[] i
= [cast(immutable)2];
257 static assert(is(typeof(s
.dup
) == shared(void)[]));
265 static assert(!__traits(compiles
, m
= s
.dup
));
288 // postblit and hence .dup could escape
289 this(this) { gp
= p
; }
293 scope S
[1] arr
= [S(&p
)];
294 auto a
= arr
.dup
; // dup does escape
297 // https://issues.dlang.org/show_bug.cgi?id=21983
298 // dup/idup destroys partially constructed arrays on failure
301 static struct SImpl(bool postblit
)
311 throw new Exception("");
316 this(scope ref const SImpl other
)
319 throw new Exception("");
321 this.num
= other
.num
;
330 import core
.stdc
.stdio
;
331 printf("Unexpected value: %lld\n", l
);
338 alias Postblit
= SImpl
!true;
339 alias Copy
= SImpl
!false;
343 S
[4] arr
= [ S(1), S(2), S(3), S(4) ];
355 static assert(test!Postblit());
356 assert(test!Postblit());
358 static assert(test!Copy());
362 // https://issues.dlang.org/show_bug.cgi?id=24453
365 static inout(char)[] foo(ref scope return inout(char)[] s
)