aboutsummaryrefslogtreecommitdiff
path: root/libphobos/libdruntime
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-08-25 19:04:50 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-08-28 00:16:34 +0200
commitb7a586beae1027ea0c82411637920a5032d1dedf (patch)
tree4c41a84c4113e90cd0caaa7aa9925f4232dc22d5 /libphobos/libdruntime
parentcace77f4fb8df18c01dfdf9040cc944eedef1147 (diff)
downloadgcc-b7a586beae1027ea0c82411637920a5032d1dedf.zip
gcc-b7a586beae1027ea0c82411637920a5032d1dedf.tar.gz
gcc-b7a586beae1027ea0c82411637920a5032d1dedf.tar.bz2
d: Merge upstream dmd 817610b16d, phobos b578dfad9
D front-end changes: - Import latest bug fixes to mainline. Phobos changes: - Import latest bug fixes to mainline. - std.logger module has been moved out of experimental. - Removed std.experimental.typecons module. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 817610b16d. * d-ctfloat.cc (CTFloat::parse): Update for new front-end interface. * d-lang.cc (d_parse_file): Likewise. * expr.cc (ExprVisitor::visit (AssignExp *)): Remove handling of array assignments to non-trivial static and dynamic arrays. * runtime.def (ARRAYASSIGN): Remove. (ARRAYASSIGN_L): Remove. (ARRAYASSIGN_R): Remove. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 817610b16d. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/internal/array/arrayassign.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos b578dfad9. * src/Makefile.am (PHOBOS_DSOURCES): Remove std/experimental/typecons.d. Add std/logger package. * src/Makefile.in: Regenerate.
Diffstat (limited to 'libphobos/libdruntime')
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/Makefile.am23
-rw-r--r--libphobos/libdruntime/Makefile.in26
-rw-r--r--libphobos/libdruntime/core/demangle.d2
-rw-r--r--libphobos/libdruntime/core/exception.d10
-rw-r--r--libphobos/libdruntime/core/internal/array/arrayassign.d304
-rw-r--r--libphobos/libdruntime/core/internal/array/equality.d27
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/socket.d36
-rw-r--r--libphobos/libdruntime/object.d91
-rw-r--r--libphobos/libdruntime/rt/arrayassign.d165
10 files changed, 464 insertions, 222 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index c358b69..85fc49d 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-d7772a236983ec37b92d21b28bad3cd2de57b945
+817610b16d0f0f469b9fbb28c000956fb910c43f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 2e1e91d..d828749 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -171,17 +171,18 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
core/exception.d core/gc/config.d core/gc/gcinterface.d \
core/gc/registry.d core/int128.d core/internal/abort.d \
- core/internal/array/appending.d core/internal/array/capacity.d \
- core/internal/array/casting.d core/internal/array/comparison.d \
- core/internal/array/concatenation.d core/internal/array/construction.d \
- core/internal/array/duplication.d core/internal/array/equality.d \
- core/internal/array/operations.d core/internal/array/utils.d \
- core/internal/atomic.d core/internal/attributes.d \
- core/internal/container/array.d core/internal/container/common.d \
- core/internal/container/hashtab.d core/internal/container/treap.d \
- core/internal/convert.d core/internal/dassert.d \
- core/internal/destruction.d core/internal/entrypoint.d \
- core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
+ core/internal/array/appending.d core/internal/array/arrayassign.d \
+ core/internal/array/capacity.d core/internal/array/casting.d \
+ core/internal/array/comparison.d core/internal/array/concatenation.d \
+ core/internal/array/construction.d core/internal/array/duplication.d \
+ core/internal/array/equality.d core/internal/array/operations.d \
+ core/internal/array/utils.d core/internal/atomic.d \
+ core/internal/attributes.d core/internal/container/array.d \
+ core/internal/container/common.d core/internal/container/hashtab.d \
+ core/internal/container/treap.d core/internal/convert.d \
+ core/internal/dassert.d core/internal/destruction.d \
+ core/internal/entrypoint.d core/internal/gc/bits.d \
+ core/internal/gc/impl/conservative/gc.d \
core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
core/internal/gc/os.d core/internal/gc/pooltable.d \
core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index de6656c..57660ee 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -192,6 +192,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
core/demangle.lo core/exception.lo core/gc/config.lo \
core/gc/gcinterface.lo core/gc/registry.lo core/int128.lo \
core/internal/abort.lo core/internal/array/appending.lo \
+ core/internal/array/arrayassign.lo \
core/internal/array/capacity.lo core/internal/array/casting.lo \
core/internal/array/comparison.lo \
core/internal/array/concatenation.lo \
@@ -839,17 +840,18 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
core/exception.d core/gc/config.d core/gc/gcinterface.d \
core/gc/registry.d core/int128.d core/internal/abort.d \
- core/internal/array/appending.d core/internal/array/capacity.d \
- core/internal/array/casting.d core/internal/array/comparison.d \
- core/internal/array/concatenation.d core/internal/array/construction.d \
- core/internal/array/duplication.d core/internal/array/equality.d \
- core/internal/array/operations.d core/internal/array/utils.d \
- core/internal/atomic.d core/internal/attributes.d \
- core/internal/container/array.d core/internal/container/common.d \
- core/internal/container/hashtab.d core/internal/container/treap.d \
- core/internal/convert.d core/internal/dassert.d \
- core/internal/destruction.d core/internal/entrypoint.d \
- core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
+ core/internal/array/appending.d core/internal/array/arrayassign.d \
+ core/internal/array/capacity.d core/internal/array/casting.d \
+ core/internal/array/comparison.d core/internal/array/concatenation.d \
+ core/internal/array/construction.d core/internal/array/duplication.d \
+ core/internal/array/equality.d core/internal/array/operations.d \
+ core/internal/array/utils.d core/internal/atomic.d \
+ core/internal/attributes.d core/internal/container/array.d \
+ core/internal/container/common.d core/internal/container/hashtab.d \
+ core/internal/container/treap.d core/internal/convert.d \
+ core/internal/dassert.d core/internal/destruction.d \
+ core/internal/entrypoint.d core/internal/gc/bits.d \
+ core/internal/gc/impl/conservative/gc.d \
core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
core/internal/gc/os.d core/internal/gc/pooltable.d \
core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
@@ -1201,6 +1203,8 @@ core/internal/array/$(am__dirstamp):
@$(MKDIR_P) core/internal/array
@: > core/internal/array/$(am__dirstamp)
core/internal/array/appending.lo: core/internal/array/$(am__dirstamp)
+core/internal/array/arrayassign.lo: \
+ core/internal/array/$(am__dirstamp)
core/internal/array/capacity.lo: core/internal/array/$(am__dirstamp)
core/internal/array/casting.lo: core/internal/array/$(am__dirstamp)
core/internal/array/comparison.lo: \
diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d
index cb8d433..ca87f90 100644
--- a/libphobos/libdruntime/core/demangle.d
+++ b/libphobos/libdruntime/core/demangle.d
@@ -2328,7 +2328,7 @@ char[] mangle(T)(return scope const(char)[] fqn, return scope char[] dst = null)
@property bool empty() const { return !s.length; }
- @property const(char)[] front() const return
+ @property const(char)[] front() const return scope
{
immutable i = indexOfDot();
return i == -1 ? s[0 .. $] : s[0 .. i];
diff --git a/libphobos/libdruntime/core/exception.d b/libphobos/libdruntime/core/exception.d
index 81aa43b..a05a24c 100644
--- a/libphobos/libdruntime/core/exception.d
+++ b/libphobos/libdruntime/core/exception.d
@@ -14,7 +14,7 @@ void __switch_errorT()(string file = __FILE__, size_t line = __LINE__) @trusted
{
// Consider making this a compile time check.
version (D_Exceptions)
- throw staticError!SwitchError(file, line, null);
+ throw staticError!SwitchError("No appropriate switch clause found", file, line, null);
else
assert(0, "No appropriate switch clause found");
}
@@ -446,16 +446,16 @@ class ForkError : Error
*/
class SwitchError : Error
{
- @safe pure nothrow @nogc this( string file = __FILE__, size_t line = __LINE__, Throwable next = null )
+ @safe pure nothrow @nogc this( string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null )
{
- super( "No appropriate switch clause found", file, line, next );
+ super( msg, file, line, next );
}
}
unittest
{
{
- auto se = new SwitchError();
+ auto se = new SwitchError("No appropriate switch clause found");
assert(se.file == __FILE__);
assert(se.line == __LINE__ - 2);
assert(se.next is null);
@@ -463,7 +463,7 @@ unittest
}
{
- auto se = new SwitchError("hello", 42, new Exception("It's an Exception!"));
+ auto se = new SwitchError("No appropriate switch clause found", "hello", 42, new Exception("It's an Exception!"));
assert(se.file == "hello");
assert(se.line == 42);
assert(se.next !is null);
diff --git a/libphobos/libdruntime/core/internal/array/arrayassign.d b/libphobos/libdruntime/core/internal/array/arrayassign.d
new file mode 100644
index 0000000..6132e68
--- /dev/null
+++ b/libphobos/libdruntime/core/internal/array/arrayassign.d
@@ -0,0 +1,304 @@
+module core.internal.array.arrayassign;
+
+// Force `enforceRawArraysConformable` to remain `pure` `@nogc`
+private void enforceRawArraysConformable(const char[] action, const size_t elementSize,
+ const void[] a1, const void[] a2, const bool allowOverlap) @trusted @nogc pure nothrow
+{
+ import core.internal.util.array : enforceRawArraysConformable;
+
+ alias Type = void function(const char[] action, const size_t elementSize,
+ const void[] a1, const void[] a2, in bool allowOverlap = false) @nogc pure nothrow;
+ (cast(Type)&enforceRawArraysConformable)(action, elementSize, a1, a2, allowOverlap);
+}
+
+private template CopyElem(string CopyAction)
+{
+ const char[] CopyElem = "{\n" ~ q{
+ memcpy(&tmp, cast(void*) &dst, elemSize);
+ } ~ CopyAction ~ q{
+ auto elem = cast(Unqual!T*) &tmp;
+ destroy(*elem);
+ } ~ "}\n";
+}
+
+private template CopyArray(bool CanOverlap, string CopyAction)
+{
+ const char[] CopyArray = CanOverlap ? q{
+ if (vFrom.ptr < vTo.ptr && vTo.ptr < vFrom.ptr + elemSize * vFrom.length)
+ foreach_reverse (i, ref dst; to)
+ } ~ CopyElem!(CopyAction) ~ q{
+ else
+ foreach (i, ref dst; to)
+ } ~ CopyElem!(CopyAction)
+ : q{
+ foreach (i, ref dst; to)
+ } ~ CopyElem!(CopyAction);
+}
+
+private template ArrayAssign(string CopyLogic, string AllowOverLap)
+{
+ const char[] ArrayAssign = q{
+ import core.internal.traits : hasElaborateCopyConstructor, Unqual;
+ import core.lifetime : copyEmplace;
+ import core.stdc.string : memcpy;
+
+ void[] vFrom = (cast(void*) from.ptr)[0 .. from.length];
+ void[] vTo = (cast(void*) to.ptr)[0 .. to.length];
+ enum elemSize = T.sizeof;
+
+ enforceRawArraysConformable("copy", elemSize, vFrom, vTo, } ~ AllowOverLap ~ q{);
+
+ void[elemSize] tmp = void;
+
+ } ~ CopyLogic ~ q{
+
+ return to;
+ };
+}
+
+/**
+ * Does array assignment (not construction) from another array of the same
+ * element type. Handles overlapping copies. Assumes the right hand side is an
+ * lvalue,
+ *
+ * Used for static array assignment with non-POD element types:
+ * ---
+ * struct S
+ * {
+ * ~this() {} // destructor, so not Plain Old Data
+ * }
+ *
+ * void main()
+ * {
+ * S[3] arr;
+ * S[3] lvalue;
+ *
+ * arr = lvalue;
+ * // Generates:
+ * // _d_arrayassign_l(arr[], lvalue[]), arr;
+ * }
+ * ---
+ *
+ * Params:
+ * to = destination array
+ * from = source array
+ * Returns:
+ * `to`
+ */
+Tarr _d_arrayassign_l(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
+{
+ mixin(ArrayAssign!(q{
+ static if (hasElaborateCopyConstructor!T)
+ } ~ CopyArray!(true, "copyEmplace(from[i], dst);") ~ q{
+ else
+ } ~ CopyArray!(true, "memcpy(cast(void*) &dst, cast(void*) &from[i], elemSize);"),
+ "true"));
+}
+
+@safe unittest
+{
+ int counter;
+ struct S
+ {
+ int val;
+ this(int val) { this.val = val; }
+ this(const scope ref S rhs)
+ {
+ val = rhs.val;
+ counter++;
+ }
+ }
+
+ S[4] arr1;
+ S[4] arr2 = [S(0), S(1), S(2), S(3)];
+ _d_arrayassign_l(arr1[], arr2[]);
+
+ assert(counter == 4);
+ assert(arr1 == arr2);
+}
+
+// copy constructor
+@safe unittest
+{
+ int counter;
+ struct S
+ {
+ int val;
+ this(int val) { this.val = val; }
+ this(const scope ref S rhs)
+ {
+ val = rhs.val;
+ counter++;
+ }
+ }
+
+ S[4] arr1;
+ S[4] arr2 = [S(0), S(1), S(2), S(3)];
+ _d_arrayassign_l(arr1[], arr2[]);
+
+ assert(counter == 4);
+ assert(arr1 == arr2);
+}
+
+@safe nothrow unittest
+{
+ // Test that throwing works
+ int counter;
+ bool didThrow;
+
+ struct Throw
+ {
+ int val;
+ this(this)
+ {
+ counter++;
+ if (counter == 2)
+ throw new Exception("");
+ }
+ }
+ try
+ {
+ Throw[4] a;
+ Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)];
+ _d_arrayassign_l(a[], b[]);
+ }
+ catch (Exception)
+ {
+ didThrow = true;
+ }
+ assert(didThrow);
+ assert(counter == 2);
+
+
+ // Test that `nothrow` works
+ didThrow = false;
+ counter = 0;
+ struct NoThrow
+ {
+ int val;
+ this(this)
+ {
+ counter++;
+ }
+ }
+ try
+ {
+ NoThrow[4] a;
+ NoThrow[4] b = [NoThrow(1), NoThrow(2), NoThrow(3), NoThrow(4)];
+ _d_arrayassign_l(a[], b[]);
+ }
+ catch (Exception)
+ {
+ didThrow = false;
+ }
+ assert(!didThrow);
+ assert(counter == 4);
+}
+
+/**
+ * Does array assignment (not construction) from another array of the same
+ * element type. Does not support overlapping copies. Assumes the right hand
+ * side is an rvalue,
+ *
+ * Used for static array assignment with non-POD element types:
+ * ---
+ * struct S
+ * {
+ * ~this() {} // destructor, so not Plain Old Data
+ * }
+ *
+ * void main()
+ * {
+ * S[3] arr;
+ * S[3] getRvalue() {return lvalue;}
+ *
+ * arr = getRvalue();
+ * // Generates:
+ * // (__appendtmp = getRvalue), _d_arrayassign_l(arr[], __appendtmp), arr;
+ * }
+ * ---
+ *
+ * Params:
+ * to = destination array
+ * from = source array
+ * Returns:
+ * `to`
+ */
+Tarr _d_arrayassign_r(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
+{
+ mixin(ArrayAssign!(
+ CopyArray!(false, "memcpy(cast(void*) &dst, cast(void*) &from[i], elemSize);"),
+ "false"));
+}
+
+@safe unittest
+{
+ int counter;
+ struct S
+ {
+ int val;
+ this(int val) { this.val = val; }
+ this(const scope ref S rhs)
+ {
+ val = rhs.val;
+ counter++;
+ }
+ }
+
+ S[4] arr1;
+ S[4] arr2 = [S(0), S(1), S(2), S(3)];
+ _d_arrayassign_r(arr1[], arr2[]);
+
+ assert(counter == 0);
+ assert(arr1 == arr2);
+}
+
+// copy constructor
+@safe unittest
+{
+ int counter;
+ struct S
+ {
+ int val;
+ this(int val) { this.val = val; }
+ this(const scope ref S rhs)
+ {
+ val = rhs.val;
+ counter++;
+ }
+ }
+
+ S[4] arr1;
+ S[4] arr2 = [S(0), S(1), S(2), S(3)];
+ _d_arrayassign_r(arr1[], arr2[]);
+
+ assert(counter == 0);
+ assert(arr1 == arr2);
+}
+
+@safe nothrow unittest
+{
+ // Test that `nothrow` works
+ bool didThrow = false;
+ int counter = 0;
+ struct NoThrow
+ {
+ int val;
+ this(this)
+ {
+ counter++;
+ }
+ }
+ try
+ {
+ NoThrow[4] a;
+ NoThrow[4] b = [NoThrow(1), NoThrow(2), NoThrow(3), NoThrow(4)];
+ _d_arrayassign_r(a[], b[]);
+ }
+ catch (Exception)
+ {
+ didThrow = false;
+ }
+ assert(!didThrow);
+ assert(counter == 0);
+}
diff --git a/libphobos/libdruntime/core/internal/array/equality.d b/libphobos/libdruntime/core/internal/array/equality.d
index d3fdd65..c110d64 100644
--- a/libphobos/libdruntime/core/internal/array/equality.d
+++ b/libphobos/libdruntime/core/internal/array/equality.d
@@ -236,6 +236,33 @@ unittest
static assert(!useMemcmp!(int[], int[]));
}
+// https://issues.dlang.org/show_bug.cgi?id=21094
+unittest
+{
+ static class C
+ {
+ int a;
+ }
+ static struct S
+ {
+ bool isValid;
+ C fib;
+
+ inout(C) get() pure @safe @nogc nothrow inout
+ {
+ return isValid ? fib : C.init;
+ }
+ T opCast(T : C)() const { return null; }
+
+ alias get this;
+ }
+
+ auto foo(S[] lhs, S[] rhs)
+ {
+ return lhs == rhs;
+ }
+}
+
// Returns a reference to an array element, eliding bounds check and
// casting void to ubyte.
pragma(inline, true)
diff --git a/libphobos/libdruntime/core/sys/posix/sys/socket.d b/libphobos/libdruntime/core/sys/posix/sys/socket.d
index 3a7b753..fc5dc5d 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/socket.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d
@@ -188,10 +188,40 @@ version (linux)
extern (D) inout(ubyte)* CMSG_DATA( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
- private inout(cmsghdr)* __cmsg_nxthdr(inout(msghdr)*, inout(cmsghdr)*) pure nothrow @nogc;
- extern (D) inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc
+ version (CRuntime_Musl)
{
- return __cmsg_nxthdr(msg, cmsg);
+ extern (D)
+ {
+ private size_t __CMSG_LEN(inout(cmsghdr)* cmsg) pure nothrow @nogc
+ {
+ return (cmsg.cmsg_len + size_t.sizeof -1) & cast(size_t)(~(size_t.sizeof - 1));
+ }
+
+ private inout(cmsghdr)* __CMSG_NEXT(inout(cmsghdr)* cmsg) pure nothrow @nogc
+ {
+ return cmsg + __CMSG_LEN(cmsg);
+ }
+
+ private inout(msghdr)* __MHDR_END(inout(msghdr)* mhdr) pure nothrow @nogc
+ {
+ return cast(inout(msghdr)*)(mhdr.msg_control + mhdr.msg_controllen);
+ }
+
+ inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc
+ {
+ return cmsg.cmsg_len < cmsghdr.sizeof ||
+ __CMSG_LEN(cmsg) + cmsghdr.sizeof >= __MHDR_END(msg) - cast(inout(msghdr)*)(cmsg)
+ ? cast(inout(cmsghdr)*) null : cast(inout(cmsghdr)*) __CMSG_NEXT(cmsg);
+ }
+ }
+ }
+ else
+ {
+ private inout(cmsghdr)* __cmsg_nxthdr(inout(msghdr)*, inout(cmsghdr)*) pure nothrow @nogc;
+ extern (D) inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc
+ {
+ return __cmsg_nxthdr(msg, cmsg);
+ }
}
extern (D) inout(cmsghdr)* CMSG_FIRSTHDR( inout(msghdr)* mhdr ) pure nothrow @nogc
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 8ef65489..d842499 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -6,6 +6,7 @@
* $(TR $(TD Arrays) $(TD
* $(MYREF assumeSafeAppend)
* $(MYREF capacity)
+ * $(A #.dup.2, $(TT dup))
* $(MYREF idup)
* $(MYREF reserve)
* ))
@@ -14,6 +15,7 @@
* $(MYREF byKeyValue)
* $(MYREF byValue)
* $(MYREF clear)
+ * $(MYREF dup)
* $(MYREF get)
* $(MYREF keys)
* $(MYREF rehash)
@@ -23,15 +25,15 @@
* ))
* $(TR $(TD General) $(TD
* $(MYREF destroy)
- * $(MYREF dup)
* $(MYREF hashOf)
- * $(MYREF opEquals)
+ * $(MYREF imported)
+ * $(MYREF noreturn)
* ))
- * $(TR $(TD Types) $(TD
+ * $(TR $(TD Classes) $(TD
* $(MYREF Error)
* $(MYREF Exception)
- * $(MYREF noreturn)
* $(MYREF Object)
+ * $(MYREF opEquals)
* $(MYREF Throwable)
* ))
* $(TR $(TD Type info) $(TD
@@ -61,7 +63,11 @@ alias size_t = typeof(int.sizeof);
alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0);
alias sizediff_t = ptrdiff_t; // For backwards compatibility only.
-alias noreturn = typeof(*null); /// bottom type
+/**
+ * Bottom type.
+ * See $(DDSUBLINK spec/type, noreturn).
+ */
+alias noreturn = typeof(*null);
alias hash_t = size_t; // For backwards compatibility only.
alias equals_t = bool; // For backwards compatibility only.
@@ -266,7 +272,9 @@ class Object
the typeinfo name string compare. This is because of dmd's dll implementation. However,
it can infer to @safe if your class' opEquals is.
+/
-bool opEquals(LHS, RHS)(LHS lhs, RHS rhs) if (is(LHS : const Object) && is(RHS : const Object))
+bool opEquals(LHS, RHS)(LHS lhs, RHS rhs)
+if ((is(LHS : const Object) || is(LHS : const shared Object)) &&
+ (is(RHS : const Object) || is(RHS : const shared Object)))
{
static if (__traits(compiles, lhs.opEquals(rhs)) && __traits(compiles, rhs.opEquals(lhs)))
{
@@ -505,6 +513,16 @@ unittest
assert(obj1 != obj2);
}
+// https://issues.dlang.org/show_bug.cgi?id=23291
+@system unittest
+{
+ static shared class C { bool opEquals(const(shared(C)) rhs) const shared { return true;}}
+ const(C) c = new C();
+ const(C)[] a = [c];
+ const(C)[] b = [c];
+ assert(a[0] == b[0]);
+}
+
private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow;
void setSameMutex(shared Object ownee, shared Object owner)
@@ -3473,13 +3491,18 @@ ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init)
private enum bool isSafeCopyable(T) = is(typeof(() @safe { union U { T x; } T *x; auto u = U(*x); }));
/***********************************
- * Looks up key; if it exists applies the update callable else evaluates the
- * create callable and adds it to the associative array
+ * Calls `create` if `key` doesn't exist in the associative array,
+ * otherwise calls `update`.
+ * `create` returns a corresponding value for `key`.
+ * `update` accepts a key parameter. If it returns a value, the value is
+ * set for `key`.
* Params:
* aa = The associative array.
* key = The key.
- * create = The callable to apply on create.
- * update = The callable to apply on update.
+ * create = The callable to create a value for `key`.
+ * Must return V.
+ * update = The callable to call if `key` exists.
+ * Takes a K argument, returns a V or void.
*/
void update(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update)
if (is(typeof(create()) : V) && (is(typeof(update(aa[K.init])) : V) || is(typeof(update(aa[K.init])) == void)))
@@ -3509,23 +3532,39 @@ if (is(typeof(create()) : V) && (is(typeof(update(aa[K.init])) : V) || is(typeof
}
///
-@system unittest
+@safe unittest
{
- auto aa = ["k1": 1];
+ int[string] aa;
- aa.update("k1", {
- return -1; // create (won't be executed)
- }, (ref int v) {
- v += 1; // update
- });
- assert(aa["k1"] == 2);
-
- aa.update("k2", {
- return 0; // create
- }, (ref int v) {
- v = -1; // update (won't be executed)
- });
- assert(aa["k2"] == 0);
+ // create
+ aa.update("key",
+ () => 1,
+ (int) {} // not executed
+ );
+ assert(aa["key"] == 1);
+
+ // update value by ref
+ aa.update("key",
+ () => 0, // not executed
+ (ref int v) {
+ v += 1;
+ });
+ assert(aa["key"] == 2);
+
+ // update from return value
+ aa.update("key",
+ () => 0, // not executed
+ (int v) => v * 2
+ );
+ assert(aa["key"] == 4);
+
+ // 'update' without changing value
+ aa.update("key",
+ () => 0, // not executed
+ (int) {
+ // do something else
+ });
+ assert(aa["key"] == 4);
}
@safe unittest
@@ -4576,6 +4615,8 @@ public import core.internal.array.casting: __ArrayCast;
public import core.internal.array.concatenation : _d_arraycatnTXImpl;
public import core.internal.array.construction : _d_arrayctor;
public import core.internal.array.construction : _d_arraysetctor;
+public import core.internal.array.arrayassign : _d_arrayassign_l;
+public import core.internal.array.arrayassign : _d_arrayassign_r;
public import core.internal.array.capacity: _d_arraysetlengthTImpl;
public import core.internal.dassert: _d_assert_fail;
diff --git a/libphobos/libdruntime/rt/arrayassign.d b/libphobos/libdruntime/rt/arrayassign.d
index c9db2fc..c9e2b15 100644
--- a/libphobos/libdruntime/rt/arrayassign.d
+++ b/libphobos/libdruntime/rt/arrayassign.d
@@ -19,171 +19,6 @@ private
debug(PRINTF) import core.stdc.stdio;
}
-/*
- * Superseded array assignment hook. Does not take into account destructors:
- * https://issues.dlang.org/show_bug.cgi?id=13661
- * Kept for backward binary compatibility. This function can be removed in the future.
- */
-extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
-{
- debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize);
-
- immutable elementSize = ti.tsize;
-
- // Need a temporary buffer tmp[] big enough to hold one element
- void[16] buf = void;
- void* ptmp = (elementSize > buf.sizeof) ? malloc(elementSize) : buf.ptr;
- scope (exit)
- {
- if (ptmp != buf.ptr)
- free(ptmp);
- }
- return _d_arrayassign_l(ti, from, to, ptmp);
-}
-
-/**
-Does array assignment (not construction) from another array of the same
-element type.
-
-Handles overlapping copies.
-
-The `_d_arrayassign_l` variant assumes the right hand side is an lvalue,
-while `_d_arrayassign_r` assumes it's an rvalue, which means it doesn't have to call copy constructors.
-
-Used for static array assignment with non-POD element types:
----
-struct S
-{
- ~this() {} // destructor, so not Plain Old Data
-}
-
-void main()
-{
- S[3] arr;
- S[3] lvalue;
-
- arr = lvalue;
- // Generates:
- // S _tmp;
- // _d_arrayassign_l(typeid(S), (cast(void*) lvalue.ptr)[0..lvalue.length], (cast(void*) arr.ptr)[0..arr.length], &_tmp);
-
- S[3] getRvalue() {return lvalue;}
- arr = getRvalue();
- // Similar, but `_d_arrayassign_r`
-}
----
-
-Params:
- ti = `TypeInfo` of the array element type.
- dst = target memory. Its `.length` is equal to the element count, not byte length.
- src = source memory. Its `.length` is equal to the element count, not byte length.
- ptmp = Temporary memory for element swapping, must have capacity of `ti.tsize` bytes.
-Returns: `dst`
-*/
-extern (C) void[] _d_arrayassign_l(TypeInfo ti, void[] src, void[] dst, void* ptmp)
-{
- debug(PRINTF) printf("_d_arrayassign_l(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize);
-
- immutable elementSize = ti.tsize;
-
- enforceRawArraysConformable("copy", elementSize, src, dst, true);
-
- if (src.ptr < dst.ptr && dst.ptr < src.ptr + elementSize * src.length)
- {
- // If dst is in the middle of src memory, use reverse order.
- for (auto i = dst.length; i--; )
- {
- void* pdst = dst.ptr + i * elementSize;
- void* psrc = src.ptr + i * elementSize;
- memcpy(ptmp, pdst, elementSize);
- memcpy(pdst, psrc, elementSize);
- ti.postblit(pdst);
- ti.destroy(ptmp);
- }
- }
- else
- {
- // Otherwise, use normal order.
- foreach (i; 0 .. dst.length)
- {
- void* pdst = dst.ptr + i * elementSize;
- void* psrc = src.ptr + i * elementSize;
- memcpy(ptmp, pdst, elementSize);
- memcpy(pdst, psrc, elementSize);
- ti.postblit(pdst);
- ti.destroy(ptmp);
- }
- }
- return dst;
-}
-
-unittest // Bugzilla 14024
-{
- string op;
-
- struct S
- {
- char x = 'x';
- this(this) { op ~= x-0x20; } // upper case
- ~this() { op ~= x; } // lower case
- }
-
- S[4] mem;
- ref S[2] slice(int a, int b) { return mem[a .. b][0 .. 2]; }
-
- op = null;
- mem[0].x = 'a';
- mem[1].x = 'b';
- mem[2].x = 'x';
- mem[3].x = 'y';
- slice(0, 2) = slice(2, 4); // [ab] = [xy]
- assert(op == "XaYb", op);
-
- op = null;
- mem[0].x = 'x';
- mem[1].x = 'y';
- mem[2].x = 'a';
- mem[3].x = 'b';
- slice(2, 4) = slice(0, 2); // [ab] = [xy]
- assert(op == "XaYb", op);
-
- op = null;
- mem[0].x = 'a';
- mem[1].x = 'b';
- mem[2].x = 'c';
- slice(0, 2) = slice(1, 3); // [ab] = [bc]
- assert(op == "BaCb", op);
-
- op = null;
- mem[0].x = 'x';
- mem[1].x = 'y';
- mem[2].x = 'z';
- slice(1, 3) = slice(0, 2); // [yz] = [xy]
- assert(op == "YzXy", op);
-}
-
-/// ditto
-extern (C) void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* ptmp)
-{
- debug(PRINTF) printf("_d_arrayassign_r(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize);
-
- immutable elementSize = ti.tsize;
-
- enforceRawArraysConformable("copy", elementSize, src, dst, false);
-
- // Always use normal order, because we can assume that
- // the rvalue src has no overlapping with dst.
- foreach (i; 0 .. dst.length)
- {
- void* pdst = dst.ptr + i * elementSize;
- void* psrc = src.ptr + i * elementSize;
- memcpy(ptmp, pdst, elementSize);
- memcpy(pdst, psrc, elementSize);
- ti.destroy(ptmp);
- }
- return dst;
-}
-
/**
Set all elements of an array to a single value.