Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Show file tree
Hide file tree
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
94 changes: 27 additions & 67 deletions src/core/internal/array/appending.d
Original file line number Diff line number Diff line change
Expand Up @@ -76,79 +76,39 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage);
}

/// Implementation of `_d_arrayappendT` and `_d_arrayappendTTrace`
template _d_arrayappendTImpl(Tarr : T[], T)
/// Implementation of `_d_arrayappendT`
ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @trusted
{
import core.internal.array.utils : _d_HookTraceImpl;

private enum errorMessage = "Cannot append to array if compiling without support for runtime type information!";

/**
* Append array `y` to array `x`.
* Params:
* x = what array to append to, taken as a reference
* y = what should be appended
* Returns:
* The new value of `x`
* 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 pure` until the implementation can be brought up to modern D expectations.
*/
static if (isCopyingNothrow!T)
ref Tarr _d_arrayappendT(return ref scope Tarr x, scope Tarr y) @trusted pure nothrow
{
pragma(inline, false);

mixin(_d_arrayappendTBody);
}
else
ref Tarr _d_arrayappendT(return ref scope Tarr x, scope Tarr y) @trusted pure
{
pragma(inline, false);
pragma(inline, false);

mixin(_d_arrayappendTBody);
}
import core.stdc.string : memcpy;
import core.internal.traits : hasElaborateCopyConstructor, Unqual;
import core.lifetime : copyEmplace;

private enum _d_arrayappendTBody = q{
import core.stdc.string : memcpy;
import core.internal.traits : hasElaborateCopyConstructor, Unqual;
import core.lifetime : copyEmplace;
auto length = x.length;

auto length = x.length;
_d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length);

_d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length);

static if (hasElaborateCopyConstructor!T)
{
foreach (i; 0 .. y.length)
copyEmplace(y[i], x[length + i]);
}
else
{
// blit all elements at once
if (y.length)
memcpy(cast(Unqual!T *)&x[length], cast(Unqual!T *)&y[0], y.length * T.sizeof);
}

return x;
};
static if (hasElaborateCopyConstructor!T)
{
foreach (i, ref elem; y)
copyEmplace(elem, x[length + i]);
}
else
{
// blit all elements at once
if (y.length)
memcpy(cast(Unqual!T *)&x[length], cast(Unqual!T *)&y[0], y.length * T.sizeof);
}

/**
* TraceGC wrapper around $(REF _d_arrayappendT, rt,array,appending,_d_arrayappendTImpl).
* 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 pure` until the implementation can be brought up to modern D expectations.
*/
alias _d_arrayappendTTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendT, errorMessage);
return x;
}

@safe unittest
{
double[] arr1;
foreach (i; 0 .. 4)
_d_arrayappendTImpl!(typeof(arr1))._d_arrayappendT(arr1, [cast(double)i]);
_d_arrayappendT(arr1, [cast(double)i]);
assert(arr1 == [0.0, 1.0, 2.0, 3.0]);
}

Expand All @@ -167,7 +127,7 @@ template _d_arrayappendTImpl(Tarr : T[], T)
Item[] arr2 = [Item(), Item()];
Item[] arr1_org = [Item(), Item()];
arr1_org ~= arr2;
_d_arrayappendTImpl!(typeof(arr1))._d_arrayappendT(arr1, arr2);
_d_arrayappendT(arr1, arr2);

// postblit should have triggered on at least the items in arr2
assert(blitted >= arr2.length);
Expand All @@ -187,7 +147,7 @@ template _d_arrayappendTImpl(Tarr : T[], T)
Item[][] arr1 = [[Item()]];
Item[][] arr2 = [[Item()]];

_d_arrayappendTImpl!(typeof(arr1))._d_arrayappendT(arr1, arr2);
_d_arrayappendT(arr1, arr2);

// no postblit should have happened because arr{1,2} contain dynamic arrays
assert(blitted == 0);
Expand All @@ -207,16 +167,16 @@ template _d_arrayappendTImpl(Tarr : T[], T)
Item[1][] arr1 = [[Item()]];
Item[1][] arr2 = [[Item()]];

_d_arrayappendTImpl!(typeof(arr1))._d_arrayappendT(arr1, arr2);
_d_arrayappendT(arr1, arr2);
// copy constructor should have been invoked because arr{1,2} contain static arrays
assert(copied >= arr2.length);
}

@safe nothrow unittest
{
string str;
_d_arrayappendTImpl!(typeof(str))._d_arrayappendT(str, "a");
_d_arrayappendTImpl!(typeof(str))._d_arrayappendT(str, "b");
_d_arrayappendTImpl!(typeof(str))._d_arrayappendT(str, "c");
_d_arrayappendT(str, "a");
_d_arrayappendT(str, "b");
_d_arrayappendT(str, "c");
assert(str == "abc");
}
2 changes: 1 addition & 1 deletion src/object.d
Original file line number Diff line number Diff line change
Expand Up @@ -4882,7 +4882,7 @@ they are only intended to be instantiated by the compiler, not the user.

public import core.internal.entrypoint : _d_cmain;

public import core.internal.array.appending : _d_arrayappendTImpl;
public import core.internal.array.appending : _d_arrayappendT;
public import core.internal.array.appending : _d_arrayappendcTXImpl;
public import core.internal.array.comparison : __cmp;
public import core.internal.array.equality : __equals;
Expand Down
4 changes: 2 additions & 2 deletions src/rt/lifetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -2126,7 +2126,7 @@ extern (C) void[] _d_arrayappendcd(ref byte[] x, dchar c) @weak

// Hack because _d_arrayappendT takes `x` as a reference
auto xx = cast(shared(char)[])x;
object._d_arrayappendTImpl!(shared(char)[])._d_arrayappendT(xx, cast(shared(char)[])appendthis);
object._d_arrayappendT(xx, cast(shared(char)[])appendthis);
x = cast(byte[])xx;
return x;
}
Expand Down Expand Up @@ -2187,7 +2187,7 @@ extern (C) void[] _d_arrayappendwd(ref byte[] x, dchar c) @weak
//

auto xx = (cast(shared(wchar)*)x.ptr)[0 .. x.length];
object._d_arrayappendTImpl!(shared(wchar)[])._d_arrayappendT(xx, cast(shared(wchar)[])appendthis);
object._d_arrayappendT(xx, cast(shared(wchar)[])appendthis);
x = (cast(byte*)xx.ptr)[0 .. xx.length];
return x;
}
Expand Down