diff options
Diffstat (limited to 'libphobos/src')
-rw-r--r-- | libphobos/src/MERGE | 2 | ||||
-rw-r--r-- | libphobos/src/std/algorithm/setops.d | 2 | ||||
-rw-r--r-- | libphobos/src/std/bitmanip.d | 3 | ||||
-rw-r--r-- | libphobos/src/std/datetime/interval.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/datetime/systime.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/experimental/allocator/mallocator.d | 1 | ||||
-rw-r--r-- | libphobos/src/std/functional.d | 165 | ||||
-rw-r--r-- | libphobos/src/std/sumtype.d | 1 | ||||
-rw-r--r-- | libphobos/src/std/utf.d | 12 |
9 files changed, 186 insertions, 8 deletions
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 5fd357c..963ffe0 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -a1f8c4c0700ce4e256f4130ad7883c6ea3890901 +16cb085b584f100fa677e2e64ff6b6dbb4921ad1 The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/algorithm/setops.d b/libphobos/src/std/algorithm/setops.d index ede1831..cc6f5b7 100644 --- a/libphobos/src/std/algorithm/setops.d +++ b/libphobos/src/std/algorithm/setops.d @@ -404,7 +404,7 @@ if (ranges.length >= 2 && r = ranges[i].save; // rollover } } - @property Result save() scope return + @property Result save() return scope { Result copy = this; foreach (i, r; ranges) diff --git a/libphobos/src/std/bitmanip.d b/libphobos/src/std/bitmanip.d index 9af9d72..de2e0fb 100644 --- a/libphobos/src/std/bitmanip.d +++ b/libphobos/src/std/bitmanip.d @@ -1447,7 +1447,8 @@ public: size_t bitCount; foreach (i; 0 .. fullWords) bitCount += countBitsSet(_ptr[i]); - bitCount += countBitsSet(_ptr[fullWords] & endMask); + if (endBits) + bitCount += countBitsSet(_ptr[fullWords] & endMask); return bitCount; } else diff --git a/libphobos/src/std/datetime/interval.d b/libphobos/src/std/datetime/interval.d index ba2a210..d787e3a 100644 --- a/libphobos/src/std/datetime/interval.d +++ b/libphobos/src/std/datetime/interval.d @@ -7848,12 +7848,12 @@ if (isTimePoint!TP && duration = The duration which separates each successive time point in the range. +/ -TP delegate(scope const TP) everyDuration(TP, Direction dir = Direction.fwd, D)(D duration) nothrow +TP delegate(return scope const TP) everyDuration(TP, Direction dir = Direction.fwd, D)(D duration) nothrow if (isTimePoint!TP && __traits(compiles, TP.init + duration) && (dir == Direction.fwd || dir == Direction.bwd)) { - TP func(scope const TP tp) + TP func(return scope const TP tp) { static if (dir == Direction.fwd) return tp + duration; diff --git a/libphobos/src/std/datetime/systime.d b/libphobos/src/std/datetime/systime.d index db325f7..949ad7d 100644 --- a/libphobos/src/std/datetime/systime.d +++ b/libphobos/src/std/datetime/systime.d @@ -6269,7 +6269,7 @@ public: duration = The $(REF Duration, core,time) to add to or subtract from this $(LREF SysTime). +/ - SysTime opBinary(string op)(Duration duration) @safe const pure nothrow scope + SysTime opBinary(string op)(Duration duration) @safe const pure nothrow return scope if (op == "+" || op == "-") { SysTime retval = SysTime(this._stdTime, this._timezone); @@ -7668,7 +7668,7 @@ public: $(LREF SysTime) for the last day in the month that this Date is in. The time portion of endOfMonth is always 23:59:59.9999999. +/ - @property SysTime endOfMonth() @safe const nothrow scope + @property SysTime endOfMonth() @safe const nothrow return scope { immutable hnsecs = adjTime; immutable days = getUnitsFromHNSecs!"days"(hnsecs); diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d index 895d588..de9afbb 100644 --- a/libphobos/src/std/experimental/allocator/mallocator.d +++ b/libphobos/src/std/experimental/allocator/mallocator.d @@ -392,6 +392,7 @@ version (Posix) AlignedMallocator.instance.alignedReallocate(c, 32, 32); assert(c.ptr); + version (LDC_AddressSanitizer) {} else // AddressSanitizer does not support such large memory allocations (0x10000000000 max) version (DragonFlyBSD) {} else /* FIXME: Malloc on DragonFly does not return NULL when allocating more than UINTPTR_MAX * $(LINK: https://bugs.dragonflybsd.org/issues/3114, dragonfly bug report) * $(LINK: https://github.com/dlang/druntime/pull/1999#discussion_r157536030, PR Discussion) */ diff --git a/libphobos/src/std/functional.d b/libphobos/src/std/functional.d index da698e0..90b0f91 100644 --- a/libphobos/src/std/functional.d +++ b/libphobos/src/std/functional.d @@ -1847,3 +1847,168 @@ if (isCallable!(F)) static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD))); } } + +// Converts an unsigned integer to a compile-time string constant. +private enum toCtString(ulong n) = n.stringof[0 .. $ - "LU".length]; + +// Check that .stringof does what we expect, since it's not guaranteed by the +// language spec. +@safe unittest +{ + assert(toCtString!0 == "0"); + assert(toCtString!123456 == "123456"); +} + +/** + * Passes the fields of a struct as arguments to a function. + * + * Can be used with a $(LINK2 https://dlang.org/spec/expression.html#function_literals, + * function literal) to give temporary names to the fields of a struct or + * tuple. + * + * Params: + * fun = Callable that the struct's fields will be passed to. + * + * Returns: + * A function that accepts a single struct as an argument and passes its + * fields to `fun` when called. + */ +template bind(alias fun) +{ + /** + * Params: + * args = The struct or tuple whose fields will be used as arguments. + * + * Returns: `fun(args.tupleof)` + */ + auto ref bind(T)(auto ref T args) + if (is(T == struct)) + { + import std.meta : Map = staticMap; + import core.lifetime : move; + + // Forwards the i'th member of `args` + // Needed because core.lifetime.forward doesn't work on struct members + template forwardArg(size_t i) + { + static if (__traits(isRef, args) || !is(typeof(move(args.tupleof[i])))) + enum forwardArg = "args.tupleof[" ~ toCtString!i ~ "], "; + else + enum forwardArg = "move(args.tupleof[" ~ toCtString!i ~ "]), "; + } + + static if (args.tupleof.length == 0) + enum argList = ""; + else + alias argList = Map!(forwardArg, Iota!(args.tupleof.length)); + + return mixin("fun(", argList, ")"); + } +} + +/// Giving names to tuple elements +@safe unittest +{ + import std.typecons : tuple; + + auto name = tuple("John", "Doe"); + string full = name.bind!((first, last) => first ~ " " ~ last); + assert(full == "John Doe"); +} + +/// Passing struct fields to a function +@safe unittest +{ + import std.algorithm.comparison : min, max; + + struct Pair + { + int a; + int b; + } + + auto p = Pair(123, 456); + assert(p.bind!min == 123); // min(p.a, p.b) + assert(p.bind!max == 456); // max(p.a, p.b) +} + +/// In a range pipeline +@safe unittest +{ + import std.algorithm.iteration : map, filter; + import std.algorithm.comparison : equal; + import std.typecons : tuple; + + auto ages = [ + tuple("Alice", 35), + tuple("Bob", 64), + tuple("Carol", 21), + tuple("David", 39), + tuple("Eve", 50) + ]; + + auto overForty = ages + .filter!(bind!((name, age) => age > 40)) + .map!(bind!((name, age) => name)); + + assert(overForty.equal(["Bob", "Eve"])); +} + +// Zero arguments +@safe unittest +{ + struct Empty {} + + assert(Empty().bind!(() => 123) == 123); +} + +// Non-copyable arguments +@safe unittest +{ + import std.typecons : tuple; + + static struct NoCopy + { + int n; + @disable this(this); + } + + static struct Pair + { + NoCopy a, b; + } + + static auto fun(NoCopy a, NoCopy b) + { + return tuple(a.n, b.n); + } + + auto expected = fun(NoCopy(1), NoCopy(2)); + assert(Pair(NoCopy(1), NoCopy(2)).bind!fun == expected); +} + +// ref arguments +@safe unittest +{ + import std.typecons : tuple; + + auto t = tuple(123, 456); + t.bind!((ref int a, int b) { a = 789; b = 1011; }); + + assert(t[0] == 789); + assert(t[1] == 456); +} + +// auto ref arguments +@safe unittest +{ + import std.typecons : tuple; + + auto t = tuple(123); + t.bind!((auto ref x) { + static assert(__traits(isRef, x)); + }); + tuple(123).bind!((auto ref x) { + static assert(!__traits(isRef, x)); + }); +} diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d index 3833c84..8da38bd 100644 --- a/libphobos/src/std/sumtype.d +++ b/libphobos/src/std/sumtype.d @@ -13,6 +13,7 @@ include: License: Boost License 1.0 Authors: Paul Backus +Source: $(PHOBOSSRC std/sumtype.d) +/ module std.sumtype; diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d index 5c23684..f0200ce 100644 --- a/libphobos/src/std/utf.d +++ b/libphobos/src/std/utf.d @@ -1209,6 +1209,15 @@ do assert("ë"w.decode(i) == 'ë' && i == 1); } +@safe pure unittest // https://issues.dlang.org/show_bug.cgi?id=22867 +{ + import std.conv : hexString; + string data = hexString!"f787a598"; + size_t offset = 0; + try data.decode(offset); + catch (UTFException ex) assert(offset == 0); +} + /++ `decodeFront` is a variant of $(LREF decode) which specifically decodes the first code point. Unlike $(LREF decode), `decodeFront` accepts any @@ -1671,7 +1680,6 @@ if ( } } - index += i + 1; static if (i == 3) { if (d > dchar.max) @@ -1682,6 +1690,8 @@ if ( throw invalidUTF(); } } + + index += i + 1; return d; } } |