Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Move _dup to duplication.d
Browse files Browse the repository at this point in the history
  • Loading branch information
dkorpel committed Jul 4, 2022
1 parent b917da2 commit 555f647
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 54 deletions.
54 changes: 54 additions & 0 deletions src/core/internal/array/duplication.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,60 @@ Source: $(DRUNTIMESRC core/internal/_array/_duplication.d)
*/
module core.internal.array.duplication;

private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;

U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
{
if (__ctfe)
return _dupCtfe!(T, U)(a);

import core.stdc.string : memcpy;
auto arr = _d_newarrayU(typeid(T[]), a.length);
memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
return *cast(U[]*) &arr;
}

U[] _dupCtfe(T, U)(scope T[] a)
{
static if (is(T : void))
assert(0, "Cannot dup a void[] array at compile time.");
else
{
U[] res;
foreach (ref e; a)
res ~= e;
return res;
}
}

U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
{
// note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
// has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
if (__ctfe)
return _dupCtfe!(T, U)(a);

import core.lifetime: copyEmplace;
U[] res = () @trusted {
auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
size_t i;
scope (failure)
{
import core.internal.lifetime: emplaceInitializer;
// Initialize all remaining elements to not destruct garbage
foreach (j; i .. a.length)
emplaceInitializer(cast() arr[j]);
}
for (; i < a.length; i++)
{
copyEmplace(a.ptr[i], arr[i]);
}
return cast(U[])(arr[0..a.length]);
} ();

return res;
}

// https://issues.dlang.org/show_bug.cgi?id=22107
@safe unittest
{
Expand Down
57 changes: 3 additions & 54 deletions src/object.d
Original file line number Diff line number Diff line change
Expand Up @@ -3765,6 +3765,7 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
if (!is(const(T) : T))
{
import core.internal.traits : Unconst;
import core.internal.array.duplication : _dup;
static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
" to "~Unconst!T.stringof~" in dup.");

Expand All @@ -3786,13 +3787,15 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
@property T[] dup(T)(const(T)[] a)
if (is(const(T) : T))
{
import core.internal.array.duplication : _dup;
return _dup!(const(T), T)(a);
}


/// Provide the .idup array property.
@property immutable(T)[] idup(T)(T[] a)
{
import core.internal.array.duplication : _dup;
static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
" to immutable in idup.");
return _dup!(T, immutable(T))(a);
Expand All @@ -3813,58 +3816,6 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
assert(s == "abc");
}

private U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
{
if (__ctfe)
return _dupCtfe!(T, U)(a);

import core.stdc.string : memcpy;
auto arr = _d_newarrayU(typeid(T[]), a.length);
memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
return *cast(U[]*) &arr;
}

private U[] _dupCtfe(T, U)(scope T[] a)
{
static if (is(T : void))
assert(0, "Cannot dup a void[] array at compile time.");
else
{
U[] res;
foreach (ref e; a)
res ~= e;
return res;
}
}

private U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
{
// note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
// has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
if (__ctfe)
return _dupCtfe!(T, U)(a);

import core.lifetime: copyEmplace;
U[] res = () @trusted {
auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
size_t i;
scope (failure)
{
import core.internal.lifetime: emplaceInitializer;
// Initialize all remaining elements to not destruct garbage
foreach (j; i .. a.length)
emplaceInitializer(cast() arr[j]);
}
for (; i < a.length; i++)
{
copyEmplace(a.ptr[i], arr[i]);
}
return cast(U[])(arr[0..a.length]);
} ();

return res;
}

// HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
// necessary for now to prevent breaking code.
private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
Expand Down Expand Up @@ -4052,8 +4003,6 @@ auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow @system
assert(is(typeof(b3) == immutable(int[])));
}

private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;

private void _doPostblit(T)(T[] arr)
{
// infer static postblit type, run postblit if any
Expand Down

0 comments on commit 555f647

Please sign in to comment.