Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Closed
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
50 changes: 35 additions & 15 deletions src/core/internal/array/appending.d
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
mixin(_d_arrayappendcTXBody);
}
else
ref Tarr _d_arrayappendcTX(return scope ref Tarr px, size_t n) @trusted pure nothrow
ref Tarr _d_arrayappendcTX(return scope ref Tarr px, size_t n) @trusted pure
{
pragma(inline, false);

Expand Down Expand Up @@ -109,19 +109,27 @@ template _d_arrayappendTImpl(Tarr : T[], T)
}

private enum _d_arrayappendTBody = q{
import core.stdc.string : memcpy;
import core.internal.traits : Unqual;
version (D_TypeInfo)
{
import core.stdc.string : memcpy;
import core.internal.traits : Unqual;

auto length = x.length;
auto sizeelem = T.sizeof;
auto length = x.length;
auto sizeelem = T.sizeof;

_d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length);
if (_d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length) is null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under what condition would _d_arrayappendcTxImpl return null?

assert(0);

if (y.length)
memcpy(cast(Unqual!T *)&x[length], cast(Unqual!T *)&y[0], y.length * sizeelem);

// do postblit
__doPostblit(cast(Unqual!Tarr)x[length .. length + y.length]);
if (y.length)
memcpy(cast(Unqual!T *)&x[length], cast(Unqual!T *)&y[0], y.length * sizeelem);

// do postblit
if (__doPostblit(cast(Unqual!Tarr)x[length .. length + y.length]) is null)
assert(0);
}
else
assert(0, "Cannot append arrays if compiling without support for runtime type information!");
return x;
};

Expand All @@ -139,7 +147,7 @@ template _d_arrayappendTImpl(Tarr : T[], T)
* Run postblit on `t` if it is a struct and needs it.
* Or if `t` is a array, run it on the children if they have a postblit.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the return type is changing, I recommend updating the DDoc comment to include a Returns explanation.

private void __doPostblit(T)(auto ref T t) @trusted pure
private auto __doPostblit(T)(auto ref T t) @trusted pure
{
import core.internal.traits : hasElaborateCopyConstructor;

Expand All @@ -149,14 +157,26 @@ private void __doPostblit(T)(auto ref T t) @trusted pure
static if (__traits(hasMember, T, "__xpostblit") &&
// Bugzilla 14746: Check that it's the exact member of S.
__traits(isSame, T, __traits(parent, t.__xpostblit)))
t.__xpostblit();
{
import core.internal.array.utils : isPure;
static if (isPure!(t.__xpostblit))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be static if (isPostblitPure!T)? I don't see isPostblitPure used anywhere.

t.__xpostblit();
else
(cast(void delegate() pure)&t.__xpostblit)();
return &t;
}
}
else static if (is(T U : U[]) && hasElaborateCopyConstructor!U)
else static if (is(T U : U[]))
{
// only do a postblit if the `U` requires it.
foreach (ref el; t)
__doPostblit(el);
static if (hasElaborateCopyConstructor!U)
foreach (ref el; t)
__doPostblit(el);

return t;
}
else
static assert(0, "No idea how to postblit " ~ typeof(t).stringof);
}

@safe unittest
Expand Down
52 changes: 45 additions & 7 deletions src/core/internal/array/utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
module core.internal.array.utils;

import core.internal.traits : Parameters;
import core.internal.traits : Parameters, hasElaborateCopyConstructor;

private auto gcStatsPure() nothrow pure
{
Expand Down Expand Up @@ -93,7 +93,7 @@ auto _d_HookTraceImpl(T, alias Hook, string errorMessage)(string file, int line,
}

/**
* Check if the function `F` is calleable in a `nothrow` scope.
* Check if the function `F` is callable in a `nothrow` scope.
* Params:
* F = Function that does not take any parameters
* Returns:
Expand All @@ -102,7 +102,16 @@ auto _d_HookTraceImpl(T, alias Hook, string errorMessage)(string file, int line,
enum isNoThrow(alias F) = is(typeof(() nothrow { F(); }));

/**
* Check if the type `T`'s postblit is called in nothrow, if it exist
* Check if the function `F` is callable in a `pure` scope.
* Params:
* F = Function that does not take any parameters
* Returns:
* if the function is callable in a `pure` scope.
*/
enum isPure(alias F) = is(typeof(() pure { F(); }));

/**
* Check if the type `T`'s postblit is called in a `nothrow` scope, if it exist
* Params:
* T = Type to check
* Returns:
Expand All @@ -112,10 +121,39 @@ enum isNoThrow(alias F) = is(typeof(() nothrow { F(); }));
template isPostblitNoThrow(T) {
static if (__traits(isStaticArray, T))
enum isPostblitNoThrow = isPostblitNoThrow!(typeof(T.init[0]));
else static if (__traits(hasMember, T, "__xpostblit") &&
// Bugzilla 14746: Check that it's the exact member of S.
__traits(isSame, T, __traits(parent, T.init.__xpostblit)))
enum isPostblitNoThrow = isNoThrow!(T.init.__xpostblit);
else static if (is(T == struct) && hasElaborateCopyConstructor!T)
{
static if (__traits(hasMember, T, "__xpostblit") &&
// Bugzilla 14746: Check that it's the exact member of S.
__traits(isSame, T, __traits(parent, T.init.__xpostblit)))
enum isPostblitNoThrow = isNoThrow!(T.init.__xpostblit);
else
enum isPostblitNoThrow = true;
}
else
enum isPostblitNoThrow = true;
};

/**
* Check if the type `T`'s postblit is called in a `pure` scope, if it exist
* Params:
* T = Type to check
* Returns:
* if the postblit is callable in a `pure` scope, if it exist.
* if it does not exist, return true.
*/
template isPostblitPure(T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curly braces on new line

static if (__traits(isStaticArray, T))
enum isPostblitPure = isPostblitPure!(typeof(T.init[0]));
else static if (is(T == struct) && hasElaborateCopyConstructor!T)
{
static if (__traits(hasMember, T, "__xpostblit") &&
// Bugzilla 14746: Check that it's the exact member of S.
__traits(isSame, T, __traits(parent, T.init.__xpostblit)))
enum isPostblitPure = isPure!(T.init.__xpostblit);
else
enum isPostblitNoThrow = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isPostblitPure instead of isPostblitNoThrow?

}
else
enum isPostblitPure = true;
};