Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 28 additions & 25 deletions src/core/internal/array/construction.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,27 @@ import core.internal.traits : Unqual;
/**
* Does array initialization (not assignment) from another array of the same element type.
* Params:
* to = what array to initialize
* from = what data the array should be initialized with
* makeWeaklyPure = unused; its purpose is to prevent the function from becoming
* strongly pure and risk being optimised out
* Returns:
* The created and initialized array `to`
* Bugs:
* This function template was ported from a much older runtime hook that bypassed safety,
* purity, and throwabilty checks. To prevent breaking existing code, this function template
* is temporarily declared `@trusted` until the implementation can be brought up to modern D expectations.
*
* The third parameter is never used, but is necessary in order for the
* function be treated as weakly pure, instead of strongly pure.
* This is needed because constructions such as the one below can be ignored by
* the compiler if `_d_arrayctor` is believed to be pure, because purity would
* mean the call to `_d_arrayctor` has no effects (no side effects and the
* return value is ignored), despite it actually modifying the contents of `a`.
* const S[2] b;
* const S[2] a = b; // this would get lowered to _d_arrayctor(a, b)
*/
Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @trusted
if (is(Unqual!T1 == Unqual!T2))
Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* makeWeaklyPure = null) @trusted
{
pragma(inline, false);
import core.internal.traits : hasElaborateCopyConstructor;
Expand All @@ -32,20 +43,12 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste
import core.stdc.stdint : uintptr_t;
debug(PRINTF) import core.stdc.stdio : printf;

debug(PRINTF) printf("_d_arrayctor(from = %p,%d) size = %d\n", from.ptr, from.length, T1.sizeof);

// Declare `to` inside a union so `__ArrayDtor(to)` isn't called in case
// `copyEmplace` throws.
union ToArr
{
Unqual!Tarr1 to;
}
ToArr toUn = void;
debug(PRINTF) printf("_d_arrayctor(from = %p,%d) size = %d\n", from.ptr, from.length, T.sizeof);

void[] vFrom = (cast(void*) from.ptr)[0..from.length];
void[] vTo = (cast(void*) toUn.to.ptr)[0..Tarr1.length];
void[] vTo = (cast(void*) to.ptr)[0..to.length];

// Force `enforceRawArraysConformable` to be `pure`
// Force `enforceRawArraysConformable` to remain weakly `pure`
void enforceRawArraysConformable(const char[] action, const size_t elementSize,
const void[] a1, const void[] a2) @trusted
{
Expand All @@ -56,23 +59,23 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste
(cast(Type)&enforceRawArraysConformableNogc)(action, elementSize, a1, a2, false);
}

enforceRawArraysConformable("initialization", T1.sizeof, vFrom, vTo);
enforceRawArraysConformable("initialization", T.sizeof, vFrom, vTo);

static if (hasElaborateCopyConstructor!T1)
static if (hasElaborateCopyConstructor!T)
{
size_t i;
try
{
for (i = 0; i < toUn.to.length; i++)
copyEmplace(from[i], cast(T1) toUn.to[i]);
for (i = 0; i < to.length; i++)
copyEmplace(from[i], to[i]);
}
catch (Exception o)
{
/* Destroy, in reverse order, what we've constructed so far
*/
while (i--)
{
auto elem = cast(Unqual!T1*) &toUn.to[i];
auto elem = cast(Unqual!T*) &to[i];
destroy(*elem);
}

Expand All @@ -82,10 +85,10 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste
else
{
// blit all elements at once
memcpy(cast(void*) toUn.to.ptr, from.ptr, toUn.to.length * T1.sizeof);
memcpy(cast(void*) to.ptr, from.ptr, to.length * T.sizeof);
}

return cast(Tarr1) toUn;
return to;
}

// postblit
Expand All @@ -100,7 +103,7 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste

S[4] arr1;
S[4] arr2 = [S(0), S(1), S(2), S(3)];
arr1 = _d_arrayctor!(typeof(arr1))(arr2[]);
_d_arrayctor(arr1[], arr2[]);

assert(counter == 4);
assert(arr1 == arr2);
Expand All @@ -123,7 +126,7 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste

S[4] arr1;
S[4] arr2 = [S(0), S(1), S(2), S(3)];
arr1 = _d_arrayctor!(typeof(arr1))(arr2[]);
_d_arrayctor(arr1[], arr2[]);

assert(counter == 4);
assert(arr1 == arr2);
Expand All @@ -149,7 +152,7 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste
{
Throw[4] a;
Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)];
a = _d_arrayctor!(typeof(a))(b[]);
_d_arrayctor(a[], b[]);
}
catch (Exception)
{
Expand All @@ -174,7 +177,7 @@ Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @truste
{
NoThrow[4] a;
NoThrow[4] b = [NoThrow(1), NoThrow(2), NoThrow(3), NoThrow(4)];
a = _d_arrayctor!(typeof(a))(b[]);
_d_arrayctor(a[], b[]);
}
catch (Exception)
{
Expand Down Expand Up @@ -280,7 +283,7 @@ void _d_arraysetctor(Tarr : T[], T)(scope Tarr p, scope ref T value) @trusted
{
Throw[4] a;
Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)];
a = _d_arrayctor!(typeof(a))(b[]);
_d_arrayctor(a[], b[]);
}
catch (Exception)
{
Expand Down