diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-07-10 17:16:17 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-07-10 23:31:29 +0200 |
commit | e9251fea2debebfebe1f762a4a8d5b3b1d4c75ef (patch) | |
tree | 09b47f4d760019131aa27d19bfb8e5ee0f1ed31f /libphobos/src/std | |
parent | 2d7c95e31431a297060c94697af84f498abf97a2 (diff) | |
download | gcc-e9251fea2debebfebe1f762a4a8d5b3b1d4c75ef.zip gcc-e9251fea2debebfebe1f762a4a8d5b3b1d4c75ef.tar.gz gcc-e9251fea2debebfebe1f762a4a8d5b3b1d4c75ef.tar.bz2 |
d: Merge upstream dmd, druntime a88e1335f7, phobos 1921d29df.
D front-end changes:
- Import dmd v2.104.1.
- Deprecation phase ended for access to private method when
overloaded with public method.
D runtime changes:
- Import druntime v2.104.1.
- Linux input header translations were added to druntime.
- Integration with the Valgrind `memcheck' tool has been added
to the garbage collector.
Phobos changes:
- Import phobos v2.104.1.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd a88e1335f7.
* dmd/VERSION: Bump version to v2.104.1.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime a88e1335f7.
* src/MERGE: Merge upstream phobos 1921d29df.
* config.h.in: Regenerate.
* configure: Regenerate.
* configure.ac (libphobos-checking): Add valgrind flag.
(DRUNTIME_LIBRARIES_VALGRIND): Call.
* libdruntime/Makefile.am (DRUNTIME_CSOURCES): Add
etc/valgrind/valgrind_.c.
(DRUNTIME_DSOURCES): Add etc/valgrind/valgrind.d.
(DRUNTIME_DSOURCES_LINUX): Add core/sys/linux/input.d,
core/sys/linux/input_event_codes.d, core/sys/linux/uinput.d.
* libdruntime/Makefile.in: Regenerate.
* m4/druntime/libraries.m4 (DRUNTIME_LIBRARIES_VALGRIND): Define.
Diffstat (limited to 'libphobos/src/std')
-rw-r--r-- | libphobos/src/std/algorithm/iteration.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/algorithm/mutation.d | 2 | ||||
-rw-r--r-- | libphobos/src/std/algorithm/searching.d | 48 | ||||
-rw-r--r-- | libphobos/src/std/complex.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/container/array.d | 2 | ||||
-rw-r--r-- | libphobos/src/std/conv.d | 22 | ||||
-rw-r--r-- | libphobos/src/std/exception.d | 2 | ||||
-rw-r--r-- | libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d | 2 | ||||
-rw-r--r-- | libphobos/src/std/format/internal/floats.d | 12 | ||||
-rw-r--r-- | libphobos/src/std/format/internal/write.d | 8 | ||||
-rw-r--r-- | libphobos/src/std/math/operations.d | 15 | ||||
-rw-r--r-- | libphobos/src/std/path.d | 22 | ||||
-rw-r--r-- | libphobos/src/std/random.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/range/package.d | 41 | ||||
-rw-r--r-- | libphobos/src/std/regex/internal/ir.d | 25 | ||||
-rw-r--r-- | libphobos/src/std/signals.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/stdio.d | 90 | ||||
-rw-r--r-- | libphobos/src/std/traits.d | 6 | ||||
-rw-r--r-- | libphobos/src/std/typecons.d | 134 | ||||
-rw-r--r-- | libphobos/src/std/uni/package.d | 39 |
20 files changed, 363 insertions, 123 deletions
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d index 55ccb51..39927be 100644 --- a/libphobos/src/std/algorithm/iteration.d +++ b/libphobos/src/std/algorithm/iteration.d @@ -2026,7 +2026,7 @@ private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured) } } - // Cannot be a copy constructor due to issue 22239 + // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239 this(this) @trusted { import core.lifetime : emplace; @@ -2128,7 +2128,7 @@ if (isForwardRange!Range) }(); } - // Cannot be a copy constructor due to issue 22239 + // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239 this(this) @trusted { import core.lifetime : emplace; diff --git a/libphobos/src/std/algorithm/mutation.d b/libphobos/src/std/algorithm/mutation.d index 9b1d920..61b6a5e 100644 --- a/libphobos/src/std/algorithm/mutation.d +++ b/libphobos/src/std/algorithm/mutation.d @@ -3049,7 +3049,7 @@ if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs)))) swap(b1, b2); } -// issue 20732 +// https://issues.dlang.org/show_bug.cgi?id=20732 @safe unittest { static struct A diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d index ee318c8..f061915 100644 --- a/libphobos/src/std/algorithm/searching.d +++ b/libphobos/src/std/algorithm/searching.d @@ -1282,7 +1282,7 @@ if (isInputRange!R && @safe pure unittest { - //example from issue 19727 + //example from https://issues.dlang.org/show_bug.cgi?id=19727 import std.path : asRelativePath; string[] ext = ["abc", "def", "ghi"]; string path = "/foo/file.def"; @@ -1315,19 +1315,12 @@ in } do { - import std.typecons : Rebindable; + import std.typecons : Rebindable2; alias Element = ElementType!Range; - Rebindable!Element seed = r.front; + auto seed = Rebindable2!Element(r.front); r.popFront(); - static if (is(Rebindable!Element == T[], T)) - { - return extremum!(map, selector)(r, seed); - } - else - { - return extremum!(map, selector)(r, seed.get); - } + return extremum!(map, selector)(r, seed.get); } private auto extremum(alias map, alias selector = "a < b", Range, @@ -1337,25 +1330,24 @@ if (isInputRange!Range && !isInfinite!Range && !is(CommonType!(ElementType!Range, RangeElementType) == void) && is(typeof(unaryFun!map(ElementType!(Range).init)))) { - import std.typecons : Rebindable; + import std.typecons : Rebindable2; alias mapFun = unaryFun!map; alias selectorFun = binaryFun!selector; alias Element = ElementType!Range; alias CommonElement = CommonType!(Element, RangeElementType); - Rebindable!CommonElement extremeElement = seedElement; + auto extremeElement = Rebindable2!CommonElement(seedElement); // if we only have one statement in the loop, it can be optimized a lot better static if (__traits(isSame, map, a => a)) { - // direct access via a random access range is faster static if (isRandomAccessRange!Range) { foreach (const i; 0 .. r.length) { - if (selectorFun(r[i], extremeElement)) + if (selectorFun(r[i], extremeElement.get)) { extremeElement = r[i]; } @@ -1365,7 +1357,7 @@ if (isInputRange!Range && !isInfinite!Range && { while (!r.empty) { - if (selectorFun(r.front, extremeElement)) + if (selectorFun(r.front, extremeElement.get)) { extremeElement = r.front; } @@ -1376,7 +1368,7 @@ if (isInputRange!Range && !isInfinite!Range && else { alias MapType = Unqual!(typeof(mapFun(CommonElement.init))); - MapType extremeElementMapped = mapFun(extremeElement); + MapType extremeElementMapped = mapFun(extremeElement.get); // direct access via a random access range is faster static if (isRandomAccessRange!Range) @@ -1405,15 +1397,7 @@ if (isInputRange!Range && !isInfinite!Range && } } } - // Rebindable is an alias to T for arrays - static if (is(typeof(extremeElement) == T[], T)) - { - return extremeElement; - } - else - { - return extremeElement.get; - } + return extremeElement.get; } private auto extremum(alias selector = "a < b", Range)(Range r) @@ -2309,7 +2293,7 @@ private R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, scope R2 needle) @safe: string _impl; - // This is what triggers issue 7992. + // This is what triggers https://issues.dlang.org/show_bug.cgi?id=7992. @property size_t length() const { return _impl.length; } @property void length(size_t len) { _impl.length = len; } @@ -2322,7 +2306,7 @@ private R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, scope R2 needle) @property CustomString save() { return this; } } - // If issue 7992 occurs, this will throw an exception from calling + // If https://issues.dlang.org/show_bug.cgi?id=7992 occurs, this will throw an exception from calling // popFront() on an empty range. auto r = find(CustomString("a"), CustomString("b")); assert(r.empty); @@ -3880,6 +3864,14 @@ if (isInputRange!Range && !isInfinite!Range && assert(arr.maxElement!"a.val".val == 1); } +// https://issues.dlang.org/show_bug.cgi?id=23993 +@safe unittest +{ + import std.bigint : BigInt; + + assert([BigInt(2), BigInt(3)].maxElement == BigInt(3)); +} + // minPos /** Computes a subrange of `range` starting at the first occurrence of `range`'s diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d index 3b860fe..347e351 100644 --- a/libphobos/src/std/complex.d +++ b/libphobos/src/std/complex.d @@ -1066,7 +1066,7 @@ Complex!T asin(T)(Complex!T z) @safe pure nothrow @nogc { import std.math.operations : isClose; import std.math.constants : PI; - version (DigitalMars) {} else // Disabled because of issue 21376 + version (DigitalMars) {} else // Disabled because of https://issues.dlang.org/show_bug.cgi?id=21376 assert(isClose(asin(complex(0.5f)), float(PI) / 6)); } @@ -1092,7 +1092,7 @@ Complex!T acos(T)(Complex!T z) @safe pure nothrow @nogc { import std.math.operations : isClose; import std.math.constants : PI; - version (DigitalMars) {} else // Disabled because of issue 21376 + version (DigitalMars) {} else // Disabled because of https://issues.dlang.org/show_bug.cgi?id=21376 assert(isClose(acos(complex(0.5f)), float(PI) / 3)); } diff --git a/libphobos/src/std/container/array.d b/libphobos/src/std/container/array.d index f5efe6d..0d6be93 100644 --- a/libphobos/src/std/container/array.d +++ b/libphobos/src/std/container/array.d @@ -1566,7 +1566,7 @@ if (!is(immutable T == immutable bool)) r2[0 .. 0] += 0; } -// Test issue 11194 +// Test https://issues.dlang.org/show_bug.cgi?id=11194 @system unittest { static struct S { diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d index 89d4e5e..aabcd78 100644 --- a/libphobos/src/std/conv.d +++ b/libphobos/src/std/conv.d @@ -209,14 +209,14 @@ template to(T) return toImpl!T(args); } - // Fix issue 6175 + // Fix https://issues.dlang.org/show_bug.cgi?id=6175 T to(S)(ref S arg) if (isStaticArray!S) { return toImpl!T(arg); } - // Fix issue 16108 + // Fix https://issues.dlang.org/show_bug.cgi?id=16108 T to(S)(ref S arg) if (isAggregateType!S && !isCopyable!S) { @@ -423,7 +423,7 @@ template to(T) assert(c == "abcx"); } -// Tests for issue 6175 +// Tests for https://issues.dlang.org/show_bug.cgi?id=6175 @safe pure nothrow unittest { char[9] sarr = "blablabla"; @@ -432,7 +432,7 @@ template to(T) assert(sarr.length == darr.length); } -// Tests for issue 7348 +// Tests for https://issues.dlang.org/show_bug.cgi?id=7348 @safe pure /+nothrow+/ unittest { assert(to!string(null) == "null"); @@ -454,7 +454,7 @@ template to(T) assert(text("a", s) == "aS"); } -// Tests for issue 11390 +// Tests for https://issues.dlang.org/show_bug.cgi?id=11390 @safe pure /+nothrow+/ unittest { const(typeof(null)) ctn; @@ -463,7 +463,7 @@ template to(T) assert(to!string(itn) == "null"); } -// Tests for issue 8729: do NOT skip leading WS +// Tests for https://issues.dlang.org/show_bug.cgi?id=8729: do NOT skip leading WS @safe pure unittest { import std.exception; @@ -1370,7 +1370,7 @@ if (is (T == immutable) && isExactSomeString!T && is(S == enum)) S2 s2; assert(to!string(s2) == "S2(42, 43.5)"); - // Test for issue 8080 + // Test for https://issues.dlang.org/show_bug.cgi?id=8080 struct S8080 { short[4] data; @@ -1972,7 +1972,7 @@ $(UL private T toImpl(T, S)(S value) if (isInputRange!S && isSomeChar!(ElementEncodingType!S) && !isExactSomeString!T && is(typeof(parse!T(value))) && - // issue 20539 + // https://issues.dlang.org/show_bug.cgi?id=20539 !(is(T == enum) && is(typeof(value == OriginalType!T.init)) && !isSomeString!(OriginalType!T))) { scope(success) @@ -5560,7 +5560,7 @@ private bool isHexLiteral(String)(scope const String hexData) static assert( ("5A 01A C FF de 1b"d).isHexLiteral); static assert( ("0123456789abcdefABCDEF"d).isHexLiteral); static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"d).isHexLiteral); - // library version allows what's pointed by issue 10454 + // library version allows what's pointed by https://issues.dlang.org/show_bug.cgi?id=10454 static assert( ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").isHexLiteral); } @@ -5931,7 +5931,7 @@ if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) && } } -@safe unittest // opSlice (issue 16192) +@safe unittest // opSlice (https://issues.dlang.org/show_bug.cgi?id=16192) { import std.meta : AliasSeq; @@ -5959,7 +5959,7 @@ if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) && for (; !r.empty; r.popFront(), ++i) { assert(original[i .. original.length].tupleof == r.tupleof); - // tupleof is used to work around issue 16216. + // tupleof is used to work around https://issues.dlang.org/show_bug.cgi?id=16216. } // opSlice vs popBack diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d index 6ffc0f7..1d93d35 100644 --- a/libphobos/src/std/exception.d +++ b/libphobos/src/std/exception.d @@ -1035,7 +1035,7 @@ Params: Bugs: The function is explicitly annotated `@nogc` because inference could fail, - see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, issue 17084). + see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, Bugzilla issue 17084). Returns: `true` if `source`'s representation embeds a pointer that points to `target`'s representation or somewhere inside diff --git a/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d b/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d index 65226e7..6883d33 100644 --- a/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d +++ b/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d @@ -827,7 +827,7 @@ version (StdUnittest) // Both sequences must work on either system - // A sequence of allocs which generates the error described in issue 16564 + // A sequence of allocs which generates the error described in https://issues.dlang.org/show_bug.cgi?id=16564 // that is a gap at the end of buf from the perspective of the allocator // for 64 bit systems (leftover balance = 8 bytes < 16) diff --git a/libphobos/src/std/format/internal/floats.d b/libphobos/src/std/format/internal/floats.d index 632bf76..afe0bfa 100644 --- a/libphobos/src/std/format/internal/floats.d +++ b/libphobos/src/std/format/internal/floats.d @@ -1449,7 +1449,7 @@ if (is(T == float) || is(T == double) assert(printFloat(-0.1L, f) == "-1.000000e-01"); assert(printFloat(10.0L, f) == "1.000000e+01"); assert(printFloat(-10.0L, f) == "-1.000000e+01"); - version (Windows) {} // issue 20972 + version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972 else { assert(printFloat(1e4000L, f) == "1.000000e+4000"); @@ -1472,7 +1472,7 @@ if (is(T == float) || is(T == double) { // log2 is broken for x87-reals on some computers in CTFE // the following tests excludes these computers from the tests - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) { @@ -2120,7 +2120,7 @@ if (is(T == float) || is(T == double) assert(printFloat(-0.1L, f) == "-0.100000"); assert(printFloat(10.0L, f) == "10.000000"); assert(printFloat(-10.0L, f) == "-10.000000"); - version (Windows) {} // issue 20972 + version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972 else { auto result1 = printFloat(1e4000L, f); @@ -2145,7 +2145,7 @@ if (is(T == float) || is(T == double) { // log2 is broken for x87-reals on some computers in CTFE // the following tests excludes these computers from the tests - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) { @@ -2803,7 +2803,7 @@ if (is(T == float) || is(T == double) assert(printFloat(-0.1L, f) == "-0.1"); assert(printFloat(10.0L, f) == "10"); assert(printFloat(-10.0L, f) == "-10"); - version (Windows) {} // issue 20972 + version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972 else { assert(printFloat(1e4000L, f) == "1e+4000"); @@ -2826,7 +2826,7 @@ if (is(T == float) || is(T == double) { // log2 is broken for x87-reals on some computers in CTFE // the following tests excludes these computers from the tests - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) { diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d index 7f127c0..8eb70ea 100644 --- a/libphobos/src/std/format/internal/write.d +++ b/libphobos/src/std/format/internal/write.d @@ -738,7 +738,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) assert(FloatingPointControl.rounding == FloatingPointControl.roundToNearest); } - // issue 20320 + // https://issues.dlang.org/show_bug.cgi?id=20320 real a = 0.16; real b = 0.016; assert(format("%.1f", a) == "0.2"); @@ -749,7 +749,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) assert(format("%.1f", a1) == "0.2"); assert(format("%.2f", b1) == "0.02"); - // issue 9889 + // https://issues.dlang.org/show_bug.cgi?id=9889 assert(format("%.1f", 0.09) == "0.1"); assert(format("%.1f", -0.09) == "-0.1"); assert(format("%.1f", 0.095) == "0.1"); @@ -907,7 +907,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) // log2 is broken for x87-reals on some computers in CTFE // the following test excludes these computers from the test - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) // 80 bit reals { @@ -3334,7 +3334,7 @@ if (isSomeString!T1 && isSomeString!T2 && isSomeString!T3 && isSomeString!T4) long fractsWidth = fracts.length; // TODO: does not take graphemes into account long suffixWidth; - // TODO: remove this workaround which hides issue 21815 + // TODO: remove this workaround which hides https://issues.dlang.org/show_bug.cgi?id=21815 if (f.width > 0) { prefixWidth = getWidth(prefix); diff --git a/libphobos/src/std/math/operations.d b/libphobos/src/std/math/operations.d index f2e1800..4bf19ee 100644 --- a/libphobos/src/std/math/operations.d +++ b/libphobos/src/std/math/operations.d @@ -1287,11 +1287,12 @@ bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType // two numbers if (lhs == rhs) return true; - static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity))) - { - if (lhs == lhs.infinity || rhs == rhs.infinity || - lhs == -lhs.infinity || rhs == -rhs.infinity) return false; - } + static if (is(typeof(lhs.infinity))) + if (lhs == lhs.infinity || lhs == -lhs.infinity) + return false; + static if (is(typeof(rhs.infinity))) + if (rhs == rhs.infinity || rhs == -rhs.infinity) + return false; import std.math.algebraic : abs; @@ -1406,6 +1407,8 @@ bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType assert(!isClose(1,real.nan)); assert(!isClose(real.nan,real.max)); assert(!isClose(real.nan,real.nan)); + + assert(!isClose(-double.infinity, 1)); } @safe pure nothrow @nogc unittest @@ -1950,7 +1953,7 @@ if (isFloatingPoint!T) // log2 is broken for x87-reals on some computers in CTFE // the following test excludes these computers from the test - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (F.realFormat == RealFormat.ieeeExtended && test == 7681) { diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d index e81f2b6..449235a 100644 --- a/libphobos/src/std/path.d +++ b/libphobos/src/std/path.d @@ -1595,7 +1595,7 @@ if (isSomeChar!C) @safe unittest { - // Test for issue 7397 + // Test for https://issues.dlang.org/show_bug.cgi?id=7397 string[] ary = ["a", "b"]; version (Posix) { @@ -1875,7 +1875,7 @@ if (isSomeChar!C) @safe unittest { - // Test for issue 7397 + // Test for https://issues.dlang.org/show_bug.cgi?id=7397 string[] ary = ["a", "b"]; version (Posix) { @@ -2745,7 +2745,7 @@ else version (Posix) See_Also: $(LREF asAbsolutePath) which does not allocate */ -string absolutePath(string path, lazy string base = getcwd()) +string absolutePath(return scope const string path, lazy string base = getcwd()) @safe pure { import std.array : array; @@ -2792,6 +2792,19 @@ string absolutePath(string path, lazy string base = getcwd()) assertThrown(absolutePath("bar", "foo")); } +// Ensure that we can call absolute path with scope paramaters +@safe unittest +{ + string testAbsPath(scope const string path, scope const string base) { + return absolutePath(path, base); + } + + version (Posix) + assert(testAbsPath("some/file", "/foo/bar") == "/foo/bar/some/file"); + version (Windows) + assert(testAbsPath(`some\file`, `c:\foo\bar`) == `c:\foo\bar\some\file`); +} + /** Transforms `path` into an absolute path. The following algorithm is used: @@ -3559,7 +3572,8 @@ if (isConvertibleToString!Range) assert(!globMatch("foo.bar", "[gh]???bar")); assert(!globMatch("foo.bar"w, "[!fg]*bar"w)); assert(!globMatch("foo.bar"d, "[fg]???baz"d)); - assert(!globMatch("foo.di", "*.d")); // test issue 6634: triggered bad assertion + // https://issues.dlang.org/show_bug.cgi?id=6634 + assert(!globMatch("foo.di", "*.d")); // triggered bad assertion assert(globMatch("foo.bar", "{foo,bif}.bar")); assert(globMatch("bif.bar"w, "{foo,bif}.bar"w)); diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d index 066ed17..87e63f3 100644 --- a/libphobos/src/std/random.d +++ b/libphobos/src/std/random.d @@ -2842,7 +2842,7 @@ auto ref choice(Range)(ref Range range) "Choice did not return a valid element from the given Range"); } -@safe unittest // issue 18631 +@safe unittest // https://issues.dlang.org/show_bug.cgi?id=18631 { auto rng = MinstdRand0(42); const a = [0,1,2]; @@ -2855,7 +2855,7 @@ auto ref choice(Range)(ref Range range) auto z1 = choice(cast(const)[1, 2, 3], rng); } -@safe unittest // Ref range (issue 18631 PR) +@safe unittest // Ref range (https://issues.dlang.org/show_bug.cgi?id=18631 PR) { struct TestRange { diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d index d37c641..191ec32 100644 --- a/libphobos/src/std/range/package.d +++ b/libphobos/src/std/range/package.d @@ -3902,24 +3902,17 @@ Returns: struct Repeat(T) { private: - //Store a non-qualified T when possible: This is to make Repeat assignable - static if ((is(T == class) || is(T == interface)) && (is(T == const) || is(T == immutable))) - { - import std.typecons : Rebindable; - alias UT = Rebindable!T; - } - else static if (is(T : Unqual!T) && is(Unqual!T : T)) - alias UT = Unqual!T; - else - alias UT = T; - UT _value; + import std.typecons : Rebindable2; + + // Store a rebindable T to make Repeat assignable. + Rebindable2!T _value; public: /// Range primitives - @property inout(T) front() inout { return _value; } + @property inout(T) front() inout { return _value.get; } /// ditto - @property inout(T) back() inout { return _value; } + @property inout(T) back() inout { return _value.get; } /// ditto enum bool empty = false; @@ -3934,7 +3927,7 @@ public: @property auto save() inout { return this; } /// ditto - inout(T) opIndex(size_t) inout { return _value; } + inout(T) opIndex(size_t) inout { return _value.get; } /// ditto auto opSlice(size_t i, size_t j) @@ -3959,7 +3952,12 @@ public: } /// Ditto -Repeat!T repeat(T)(T value) { return Repeat!T(value); } +Repeat!T repeat(T)(T value) +{ + import std.typecons : Rebindable2; + + return Repeat!T(Rebindable2!T(value)); +} /// pure @safe nothrow unittest @@ -9144,7 +9142,7 @@ public: { static if (needsEndTracker) { - if (poppedElems < windowSize) + if (nextSource.empty) hasShownPartialBefore = true; } else @@ -10124,6 +10122,15 @@ public: assert("ab cd".splitter(' ').slide!(No.withPartial)(2).equal!equal([["ab", "cd"]])); } +// https://issues.dlang.org/show_bug.cgi?id=23976 +@safe unittest +{ + import std.algorithm.comparison : equal; + import std.algorithm.iteration : splitter; + + assert("1<2".splitter('<').slide(2).equal!equal([["1", "2"]])); +} + private struct OnlyResult(Values...) if (Values.length > 1) { @@ -10339,7 +10346,7 @@ if (!is(CommonType!Values == void)) /// ditto auto only()() { - // cannot use noreturn due to issue 22383 + // cannot use noreturn due to https://issues.dlang.org/show_bug.cgi?id=22383 struct EmptyElementType {} EmptyElementType[] result; return result; diff --git a/libphobos/src/std/regex/internal/ir.d b/libphobos/src/std/regex/internal/ir.d index ec0cb66..3b38f9c 100644 --- a/libphobos/src/std/regex/internal/ir.d +++ b/libphobos/src/std/regex/internal/ir.d @@ -49,10 +49,29 @@ CharMatcher[CodepointSet] matcherCache; } } -@property ref wordMatcher()() +// Force pure because that is needed +// Templated so that we don't pull in std.uni wordCharacter unnecessarily. +@property ref wordMatcher()() pure { - static immutable CharMatcher matcher = CharMatcher(wordCharacter); - return matcher; + static auto actual() + { + static CharMatcher matcher; + static bool haveMatcher; + + if (!haveMatcher) + { + matcher = CharMatcher(wordCharacter); + haveMatcher = true; + } + + return &matcher; + } + + // WORKAROUND: if the compiler won't memoize the output of the function for us, + // we'll do it with pure and there will be casts and it'll be happy about it. + // This is unfortunately needed to make std.regex as a whole faster to import & use + // in build times ~500ms. + return *(cast(immutable(CharMatcher)* function() @safe nothrow @nogc pure)&actual)(); } // some special Unicode white space characters diff --git a/libphobos/src/std/signals.d b/libphobos/src/std/signals.d index e5dc67e..97004d5 100644 --- a/libphobos/src/std/signals.d +++ b/libphobos/src/std/signals.d @@ -624,7 +624,7 @@ void linkin() { } a.value6 = 46; } -// Triggers bug from issue 15341 +// Triggers bug from https://issues.dlang.org/show_bug.cgi?id=15341 @system unittest { class Observer @@ -666,7 +666,7 @@ version (none) // Disabled because of https://issues.dlang.org/show_bug.cgi?id=5 } } -// Triggers bug from issue 16249 +// Triggers bug from https://issues.dlang.org/show_bug.cgi?id=16249 @system unittest { class myLINE diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d index 5ed685f..19ce988 100644 --- a/libphobos/src/std/stdio.d +++ b/libphobos/src/std/stdio.d @@ -34,9 +34,17 @@ $(TR $(TD Misc) $(TD )) )) -Standard I/O functions that extend $(B core.stdc.stdio). $(B core.stdc.stdio) +Standard I/O functions that extend $(LINK2 https://dlang.org/phobos/core_stdc_stdio.html, core.stdc.stdio). $(B core.stdc.stdio) is $(D_PARAM public)ally imported when importing $(B std.stdio). +There are three layers of I/O: +$(OL +$(LI The lowest layer is the operating system layer. The two main schemes are Windows and Posix.) +$(LI C's $(TT stdio.h) which unifies the two operating system schemes.) +$(LI $(TT std.stdio), this module, unifies the various $(TT stdio.h) implementations into +a high level package for D programs.) +) + Source: $(PHOBOSSRC std/stdio.d) Copyright: Copyright The D Language Foundation 2007-. License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). @@ -48,6 +56,55 @@ CSTDIO=$(HTTP cplusplus.com/reference/cstdio/$1/, $1) */ module std.stdio; +/* +# Glossary + +The three layers have many terms for their data structures and types. +Here we try to bring some sanity to them for the intrepid code spelunker. + +## Windows + +Handle + + A Windows handle is an opaque object of type HANDLE. + The `HANDLE` for standard devices can be retrieved with + Windows `GetStdHandle()`. + +## Posix + +file descriptor, aka fileno, aka fildes + + An int from 0..`FOPEN_MAX`, which is an index into some internal data + structure. + 0 is for `stdin`, 1 for `stdout`, 2 for `stderr`. + Negative values usually indicate an error. + +## stdio.h + +`FILE` + + A struct that encapsulates the C library's view of the operating system + files. A `FILE` should only be referred to via a pointer. + +`fileno` + + A field of `FILE` which is the Posix file descriptor for Posix systems, and + and an index into an array of file `HANDLE`s for Windows. + This array is how Posix behavior is emulated on Windows. + For Digital Mars C, that array is `__osfhnd[]`, and is initialized + at program start by the C runtime library. + In this module, they are typed as `fileno_t`. + +`stdin`, `stdout`, `stderr` + + Global pointers to `FILE` representing standard input, output, and error streams. + Being global means there are synchronization issues when multiple threads + are doing I/O on the same streams. + +## std.stdio + +*/ + import core.stdc.stddef : wchar_t; public import core.stdc.stdio; import std.algorithm.mutation : copy; @@ -129,6 +186,10 @@ else version (Solaris) { version = GENERIC_IO; } +else +{ + static assert(0, "unsupported operating system"); +} // Character type used for operating system filesystem APIs version (Windows) @@ -140,6 +201,7 @@ else private alias FSChar = char; } +private alias fileno_t = int; // file descriptor, fildes, fileno version (Windows) { @@ -203,7 +265,7 @@ version (DIGITAL_MARS_STDIO) // @@@DEPRECATED_2.107@@@ deprecated("internal function _fileno was unintentionally available from " ~ "std.stdio and will be removed afer 2.107") - int _fileno(FILE* f) { return f._file; } + fileno_t _fileno(FILE* f) { return f._file; } } else version (MICROSOFT_STDIO) { @@ -550,7 +612,7 @@ Throws: `ErrnoException` if the file could not be opened. stdioOpenmode, "'")), name); - // MSVCRT workaround (issue 14422) + // MSVCRT workaround (https://issues.dlang.org/show_bug.cgi?id=14422) version (MICROSOFT_STDIO) { setAppendWin(stdioOpenmode); @@ -708,7 +770,7 @@ Throws: `ErrnoException` in case of error. { auto handle = _p.handle; _p.handle = null; - // fclose disassociates the FILE* even in case of error (issue 19751) + // fclose disassociates the FILE* even in case of error (https://issues.dlang.org/show_bug.cgi?id=19751) errnoEnforce(.fclose(handle) == 0, "Could not close file `"~_name~"'"); } @@ -1140,7 +1202,7 @@ Throws: `ErrnoException` if the file is not opened or the call to `fread` fails. enforce(isOpen, "Attempting to read from an unopened file"); version (Windows) { - immutable fd = .fileno(_p.handle); + immutable fileno_t fd = .fileno(_p.handle); immutable mode = .__setmode(fd, _O_BINARY); scope(exit) .__setmode(fd, mode); version (DIGITAL_MARS_STDIO) @@ -1230,7 +1292,7 @@ Throws: `ErrnoException` if the file is not opened or if the call to `fwrite` fa version (Windows) { - immutable fd = .fileno(_p.handle); + immutable fileno_t fd = .fileno(_p.handle); immutable oldMode = .__setmode(fd, _O_BINARY); if (oldMode != _O_BINARY) @@ -2287,7 +2349,7 @@ Returns the `FILE*` corresponding to this object. /** Returns the file number corresponding to this object. */ - @property int fileno() const @trusted + @property fileno_t fileno() const @trusted { import std.exception : enforce; @@ -3108,10 +3170,13 @@ is empty, throws an `Exception`. In case of an I/O error throws // "wide-oriented" for us. immutable int mode = __setmode(f.fileno, _O_TEXT); // Set some arbitrary mode to obtain the previous one. - __setmode(f.fileno, mode); // Restore previous mode. - if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT)) + if (mode != -1) // __setmode() succeeded { - orientation_ = 1; // wide + __setmode(f.fileno, mode); // Restore previous mode. + if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT)) + { + orientation_ = 1; // wide + } } } else @@ -3336,7 +3401,8 @@ is empty, throws an `Exception`. In case of an I/O error throws version (Windows) { - int fd, oldMode; + fileno_t fd; + int oldMode; version (DIGITAL_MARS_STDIO) ubyte oldInfo; } @@ -3795,7 +3861,7 @@ void main() assert(std.file.readText!string(deleteme) == "y"); } -@safe unittest // issue 18801 +@safe unittest // https://issues.dlang.org/show_bug.cgi?id=18801 { static import std.file; import std.string : stripLeft; diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d index 689f0ae..4dc569d 100644 --- a/libphobos/src/std/traits.d +++ b/libphobos/src/std/traits.d @@ -5337,7 +5337,7 @@ package template isBlitAssignable(T) enum isBlitAssignable = isBlitAssignable!(OriginalType!T); } else static if (isStaticArray!T && is(T == E[n], E, size_t n)) - // Workaround for issue 11499 : isStaticArray!T should not be necessary. + // Workaround for https://issues.dlang.org/show_bug.cgi?id=11499 : isStaticArray!T should not be necessary. { enum isBlitAssignable = isBlitAssignable!E; } @@ -8877,7 +8877,9 @@ template getSymbolsByUDA(alias symbol, alias attribute) @Attr void c(); } - static assert(getSymbolsByUDA!(A, Attr).stringof == "tuple(a, a, c)"); + alias ola = __traits(getOverloads, A, "a"); + static assert(__traits(isSame, getSymbolsByUDA!(A, Attr), + AliasSeq!(ola[0], ola[1], A.c))); } // getSymbolsByUDA no longer works on modules diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d index 0748d52..67a1ede 100644 --- a/libphobos/src/std/typecons.d +++ b/libphobos/src/std/typecons.d @@ -2955,6 +2955,140 @@ Rebindable!T rebindable(T)(Rebindable!T obj) assert(rebindable(pr3341_aa)[321] == 543); } +package(std) struct Rebindable2(T) +{ +private: + static if (isAssignable!(typeof(cast() T.init))) + { + enum useQualifierCast = true; + + typeof(cast() T.init) data; + } + else + { + enum useQualifierCast = false; + + align(T.alignof) + static struct Payload + { + static if (hasIndirections!T) + { + void[T.sizeof] data; + } + else + { + ubyte[T.sizeof] data; + } + } + + Payload data; + } + +public: + + static if (!__traits(compiles, { T value; })) + { + @disable this(); + } + + /** + * Constructs a `Rebindable2` from a given value. + */ + this(T value) @trusted + { + static if (useQualifierCast) + { + this.data = cast() value; + } + else + { + set(value); + } + } + + /** + * Overwrites the currently stored value with `value`. + */ + void opAssign(this This)(T value) @trusted + { + clear; + set(value); + } + + /** + * Returns the value currently stored in the `Rebindable2`. + */ + T get(this This)() @property @trusted + { + static if (useQualifierCast) + { + return cast(T) this.data; + } + else + { + return *cast(T*) &this.data; + } + } + + /// Ditto + inout(T) get() inout @property @trusted + { + static if (useQualifierCast) + { + return cast(inout(T)) this.data; + } + else + { + return *cast(inout(T)*) &this.data; + } + } + + static if (!useQualifierCast) + { + ~this() @trusted + { + clear; + } + } + +private: + + void set(this This)(T value) + { + static if (useQualifierCast) + { + this.data = cast() value; + } + else + { + // As we're escaping a copy of `value`, deliberately leak a copy: + static union DontCallDestructor + { + T value; + } + DontCallDestructor copy = DontCallDestructor(value); + this.data = *cast(Payload*) © + } + } + + void clear(this This)() + { + // work around reinterpreting cast being impossible in CTFE + if (__ctfe) + { + return; + } + + // call possible struct destructors + .destroy!(No.initialize)(*cast(T*) &this.data); + } +} + +package(std) Rebindable2!T rebindable2(T)(T value) +{ + return Rebindable2!T(value); +} + /** Similar to `Rebindable!(T)` but strips all qualifiers from the reference as opposed to just constness / immutability. Primary intended use case is with diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d index e2a0de7..6ab6ba0 100644 --- a/libphobos/src/std/uni/package.d +++ b/libphobos/src/std/uni/package.d @@ -8592,7 +8592,7 @@ public: Decomposes a Hangul syllable. If `ch` is not a composed syllable then this function returns $(LREF Grapheme) containing only `ch` as is. */ -Grapheme decomposeHangul(dchar ch) @safe +Grapheme decomposeHangul(dchar ch) nothrow pure @safe { immutable idxS = cast(int) ch - jamoSBase; if (idxS < 0 || idxS >= jamoSCount) return Grapheme(ch); @@ -8709,7 +8709,15 @@ enum { In cases where the string in question is already normalized, it is returned unmodified and no memory allocation happens. +/ -inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] input) +/* + WARNING: @trusted lambda inside - handle with same care as @trusted + functions + + Despite being a template, the attributes do no harm since this doesn't work + with user-defined range or character types anyway. +*/ +pure @safe inout(C)[] normalize(NormalizationForm norm=NFC, C) + (return scope inout(C)[] input) { import std.algorithm.mutation : SwapStrategy; import std.algorithm.sorting : sort; @@ -8790,20 +8798,24 @@ inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu // reset variables decomposed.length = 0; () @trusted { - decomposed.assumeSafeAppend(); + // assumeSafeAppend isn't considered pure as of writing, hence the + // cast. It isn't pure in the sense that the elements after + // the array in question are affected, but we don't use those + // making the call pure for our purposes. + (cast(void delegate() pure nothrow) {decomposed.assumeSafeAppend();})(); ccc.length = 0; - ccc.assumeSafeAppend(); + (cast(void delegate() pure nothrow) {ccc.assumeSafeAppend();})(); } (); input = input[anchors[1]..$]; // and move on anchors = splitNormalized!norm(input); - }while (anchors[0] != input.length); + } while (anchors[0] != input.length); app.put(input[0 .. anchors[0]]); return () @trusted inout { return cast(inout(C)[]) app.data; } (); } /// -@safe unittest +@safe pure unittest { // any encoding works wstring greet = "Hello world"; @@ -8817,7 +8829,7 @@ inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu assert(normalize!NFKD("ϓ") == "\u03A5\u0301"); } -@safe unittest +@safe pure unittest { import std.conv : text; @@ -8825,18 +8837,9 @@ inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu assert(normalize!NFKD("2¹⁰") == "210", normalize!NFKD("2¹⁰")); assert(normalize!NFD("Äffin") == "A\u0308ffin"); - // check example - - // any encoding works - wstring greet = "Hello world"; + // test with dstring + dstring greet = "Hello world"; assert(normalize(greet) is greet); // the same exact slice - - // An example of a character with all 4 forms being different: - // Greek upsilon with acute and hook symbol (code point 0x03D3) - assert(normalize!NFC("ϓ") == "\u03D3"); - assert(normalize!NFD("ϓ") == "\u03D2\u0301"); - assert(normalize!NFKC("ϓ") == "\u038E"); - assert(normalize!NFKD("ϓ") == "\u03A5\u0301"); } // canonically recompose given slice of code points, works in-place and mutates data |