aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-07-10 17:16:17 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2023-07-10 23:31:29 +0200
commite9251fea2debebfebe1f762a4a8d5b3b1d4c75ef (patch)
tree09b47f4d760019131aa27d19bfb8e5ee0f1ed31f /libphobos/src/std
parent2d7c95e31431a297060c94697af84f498abf97a2 (diff)
downloadgcc-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.d4
-rw-r--r--libphobos/src/std/algorithm/mutation.d2
-rw-r--r--libphobos/src/std/algorithm/searching.d48
-rw-r--r--libphobos/src/std/complex.d4
-rw-r--r--libphobos/src/std/container/array.d2
-rw-r--r--libphobos/src/std/conv.d22
-rw-r--r--libphobos/src/std/exception.d2
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d2
-rw-r--r--libphobos/src/std/format/internal/floats.d12
-rw-r--r--libphobos/src/std/format/internal/write.d8
-rw-r--r--libphobos/src/std/math/operations.d15
-rw-r--r--libphobos/src/std/path.d22
-rw-r--r--libphobos/src/std/random.d4
-rw-r--r--libphobos/src/std/range/package.d41
-rw-r--r--libphobos/src/std/regex/internal/ir.d25
-rw-r--r--libphobos/src/std/signals.d4
-rw-r--r--libphobos/src/std/stdio.d90
-rw-r--r--libphobos/src/std/traits.d6
-rw-r--r--libphobos/src/std/typecons.d134
-rw-r--r--libphobos/src/std/uni/package.d39
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*) &copy;
+ }
+ }
+
+ 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