From aba8660d757e12c3982c8c6427c8e04b6b634ecd Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Wed, 5 Sep 2018 14:16:09 -0400 Subject: [PATCH 01/77] Fix Issue 19226 - std.typecons.Nullable(T, T nullValue) doesn't fully handle non-self-equal nullValue --- std/typecons.d | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/std/typecons.d b/std/typecons.d index f3a0c4b0d25..9ba8ba2fad4 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -3542,7 +3542,7 @@ Returns: } //Need to use 'is' if T is a float type //because NaN != NaN - else static if (isFloatingPoint!T) + else static if (__traits(isFloating, T) || __traits(compiles, { static assert(!(nullValue == nullValue)); })) { return _value is nullValue; } @@ -3563,6 +3563,14 @@ Returns: assert(!ni.isNull); } +@system unittest +{ + assert(typeof(this).init.isNull, typeof(this).stringof ~ + ".isNull does not work correctly because " ~ T.stringof ~ + " has an == operator that is non-reflexive and could not be" ~ + " determined before runtime to be non-reflexive!"); +} + // https://issues.dlang.org/show_bug.cgi?id=11135 // disable test until https://issues.dlang.org/show_bug.cgi?id=15316 gets fixed version (none) @system unittest @@ -3737,6 +3745,25 @@ if (is (typeof(nullValue) == T)) assert(a.isNull); } +@nogc nothrow pure @safe unittest +{ + // issue 19226 - fully handle non-self-equal nullValue + static struct Fraction + { + int denominator; + bool isNaN() const + { + return denominator == 0; + } + bool opEquals(const Fraction rhs) const + { + return !isNaN && denominator == rhs.denominator; + } + } + alias N = Nullable!(Fraction, Fraction.init); + assert(N.init.isNull); +} + @safe unittest { static int f(scope const Nullable!(int, int.min) x) { From fb82c219b7ca229aacf8377c97e1ae9ce0cf752a Mon Sep 17 00:00:00 2001 From: Johannes Pfau Date: Sat, 27 Apr 2019 09:58:32 +0200 Subject: [PATCH 02/77] MinGW build fixes --- std/math.d | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/std/math.d b/std/math.d index e3c60d8193a..c02e26dfdf9 100644 --- a/std/math.d +++ b/std/math.d @@ -164,6 +164,12 @@ else version (D_InlineAsm_X86_64) version = InlineAsm_X86_Any; } +version (CRuntime_Microsoft) +{ + version (InlineAsm_X86_Any) + version = MSVC_InlineAsm; +} + version (X86_64) version = StaticallyHaveSSE; version (X86) version (OSX) version = StaticallyHaveSSE; @@ -4387,7 +4393,7 @@ real logb(real x) @trusted nothrow @nogc ret ; } } - else version (CRuntime_Microsoft) + else version (MSVC_InlineAsm) { asm pure nothrow @nogc { @@ -4728,7 +4734,7 @@ real ceil(real x) @trusted pure nothrow @nogc ret ; } } - else version (CRuntime_Microsoft) + else version (MSVC_InlineAsm) { short cw; asm pure nothrow @nogc @@ -4856,7 +4862,7 @@ real floor(real x) @trusted pure nothrow @nogc ret ; } } - else version (CRuntime_Microsoft) + else version (MSVC_InlineAsm) { short cw; asm pure nothrow @nogc @@ -5420,7 +5426,7 @@ real trunc(real x) @trusted nothrow @nogc pure ret ; } } - else version (CRuntime_Microsoft) + else version (MSVC_InlineAsm) { short cw; asm pure nothrow @nogc From 03ce27d1d41f2c69afb63798f8ba5501508d663b Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 28 Apr 2019 09:12:17 +0200 Subject: [PATCH 03/77] [S390] std.math: Use IBMZ_Any for SystemZ bindings --- std/math.d | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/std/math.d b/std/math.d index c02e26dfdf9..601f3137023 100644 --- a/std/math.d +++ b/std/math.d @@ -150,8 +150,10 @@ version (MIPS32) version = MIPS_Any; version (MIPS64) version = MIPS_Any; version (AArch64) version = ARM_Any; version (ARM) version = ARM_Any; +version (S390) version = IBMZ_Any; version (SPARC) version = SPARC_Any; version (SPARC64) version = SPARC_Any; +version (SystemZ) version = IBMZ_Any; version (RISCV32) version = RISCV_Any; version (RISCV64) version = RISCV_Any; @@ -6009,7 +6011,7 @@ nothrow @nogc: | inexactException, } } - else version (SystemZ) + else version (IBMZ_Any) { enum : ExceptionMask { @@ -6159,7 +6161,7 @@ private: { alias ControlState = ulong; } - else version (SystemZ) + else version (IBMZ_Any) { alias ControlState = uint; } From 8430584344dc75c715d5db6442ad7aa336837659 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Sun, 28 Apr 2019 14:24:03 +0200 Subject: [PATCH 04/77] fix Issue 19777 - SortedRange.opSlice should infer safety - unittests did fail with DIP1000 due to missing return scope inference in chained range, thus leading to a scope violation which prevented `@safe` inference - fixed unittests by adding return scope to chain.Result - would still fail under dip1000 with other ranges that miss return scope on their opSlice - should not have any effect on non-DIP1000 usage --- std/range/package.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/range/package.d b/std/range/package.d index b2a01c11746..4dd67c4a159 100644 --- a/std/range/package.d +++ b/std/range/package.d @@ -1170,7 +1170,7 @@ if (Ranges.length > 0 && } static if (allSatisfy!(hasLength, R) && allSatisfy!(hasSlicing, R)) - auto opSlice(size_t begin, size_t end) + auto opSlice(size_t begin, size_t end) return scope { auto result = this; foreach (i, Unused; R) @@ -10661,7 +10661,7 @@ if (isInputRange!Range && !isInstanceOf!(SortedRange, Range)) /// Ditto static if (hasSlicing!Range) - auto opSlice(size_t a, size_t b) return scope @trusted + auto opSlice(size_t a, size_t b) return scope { assert( a <= b, From 5d0f1d3471b95d6d22406001f3e7ba52b4691aa2 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Sun, 28 Apr 2019 14:02:24 -0400 Subject: [PATCH 05/77] Fix Issue 19836 - Excessive probability of UUID collisions in std.uuid.randomUUID On 64-bit architectures use 64 bits of entropy to initialize thread-local `rndGen`. The motivation for this change is std.uuid defaults to using `rndGen` to generate UUIDs. If every `rndGen` starts in one of 2^^32 states then if 77000 independent programs each generate a single UUID there is a 50% chance that at least two of them generate the same initial UUID (and all subsequent UUIDs would be identical as well). Not just Phobos but also C++ boost::uuids::random_generator defaults to generating UUIDs with a Mersenne Twister initialized from a 32-bit seed, exacerbating the collision problem further. If instead there are 2^^64 possible initial states of `rndGen` there can be over 5 billion independent `rndGen`s before there is a 50% chance of two having identical initial states. This change is limited to 64-bit architectures to avoid a measurable performance decrease, because many programs are not generating UUIDs. --- std/random.d | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/std/random.d b/std/random.d index f2d7f9b4899..b21b184b692 100644 --- a/std/random.d +++ b/std/random.d @@ -1813,6 +1813,8 @@ A singleton instance of the default random number generator { static if (isSeedable!(Random, ulong)) result.seed(unpredictableSeed!ulong); // Avoid unnecessary copy. + else static if (size_t.sizeof >= ulong.sizeof && is(Random : MersenneTwisterEngine!Params, Params...)) + initMTEngine(result); // 64-bit multiplication is fast, so use a 64-bit seed. else static if (isSeedable!(Random, uint)) result.seed(unpredictableSeed!uint); // Avoid unnecessary copy. else @@ -1831,6 +1833,34 @@ A singleton instance of the default random number generator assert(rnd.take(3).sum > 0); } +/+ +Initialize a 32-bit MersenneTwisterEngine from 64 bits of entropy. +This is private and accepts no seed as a parameter, freeing the internal +implementaton from any need for stability across releases. ++/ +private void initMTEngine(MTEngine)(scope ref MTEngine mt) +if (is(MTEngine : MersenneTwisterEngine!Params, Params...)) +{ + pragma(inline, false); // Called no more than once per thread by rndGen. + ulong x = unpredictableSeed!ulong; + alias UIntType = typeof(mt.front()); + foreach (size_t i, ref e; mt.state.data) + { + x = (x ^ (x >> 62)) * 6_364_136_223_846_793_005UL + i; + e = cast(UIntType) x; + static if (MTEngine.max != UIntType.max) + { + e &= MTEngine.max; + } + } + mt.state.index = mt.state.data.length - 1; + // double popFront() to guarantee both `mt.state.z` + // and `mt.state.front` are derived from the newly + // set values in `mt.state.data`. + mt.popFront(); + mt.popFront(); +} + /** Generates a number between `a` and `b`. The `boundaries` parameter controls the shape of the interval (open vs. closed on From 712545cc800c081a9b7111be5bb1f2b68b725d7b Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 29 Apr 2019 23:42:41 +0200 Subject: [PATCH 06/77] std.mmfile: MAP_ANON is only defined in core.sys.posix.sys.mman --- std/mmfile.d | 1 - 1 file changed, 1 deletion(-) diff --git a/std/mmfile.d b/std/mmfile.d index bb46c15776e..29dedccd034 100644 --- a/std/mmfile.d +++ b/std/mmfile.d @@ -335,7 +335,6 @@ class MmFile else { fd = -1; - version (CRuntime_Glibc) import core.sys.linux.sys.mman : MAP_ANON; flags |= MAP_ANON; } this.size = size; From d4102819f680e487b1f0b06c8f3d95b7a2afecc3 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Wed, 1 May 2019 11:19:06 -0400 Subject: [PATCH 07/77] Revert "Decrease template instantiation in std.algorithm.searching : all & any" --- std/algorithm/searching.d | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/std/algorithm/searching.d b/std/algorithm/searching.d index ece608e0e78..ceb46bd3824 100644 --- a/std/algorithm/searching.d +++ b/std/algorithm/searching.d @@ -124,10 +124,9 @@ template all(alias pred = "a") { static assert(is(typeof(unaryFun!pred(range.front))), "`" ~ pred.stringof[1..$-1] ~ "` isn't a unary predicate function for range.front"); - foreach (ref e; range) - if (!unaryFun!pred(e)) - return false; - return true; + import std.functional : not; + + return find!(not!(unaryFun!pred))(range).empty; } } @@ -154,6 +153,7 @@ are true. { int x = 1; assert(all!(a => a > x)([2, 3])); + assert(all!"a == 0x00c9"("\xc3\x89")); // Test that `all` auto-decodes. } /++ @@ -172,10 +172,7 @@ template any(alias pred = "a") bool any(Range)(Range range) if (isInputRange!Range && is(typeof(unaryFun!pred(range.front)))) { - foreach (ref e; range) - if (unaryFun!pred(e)) - return true; - return false; + return !find!pred(range).empty; } } @@ -211,6 +208,7 @@ evaluate to true. { auto a = [ 1, 2, 0, 4 ]; assert(any!"a == 2"(a)); + assert(any!"a == 0x3000"("\xe3\x80\x80")); // Test that `any` auto-decodes. } // balancedParens From c334d376011a04356dc150f765a54e7ad1c05810 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Tue, 30 Apr 2019 18:57:59 -0400 Subject: [PATCH 08/77] Fix Issue 6657 - dotProduct overload for small fixed size arrays --- std/numeric.d | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/std/numeric.d b/std/numeric.d index a4c70619e8e..e21304ddd5c 100644 --- a/std/numeric.d +++ b/std/numeric.d @@ -1774,6 +1774,24 @@ dotProduct(F1, F2)(in F1[] avector, in F2[] bvector) return sum0; } +/// ditto +F dotProduct(F, uint N)(const ref scope F[N] a, const ref scope F[N] b) +if (N <= 16) +{ + F sum0 = 0; + F sum1 = 0; + static foreach (i; 0 .. N / 2) + { + sum0 += a[i*2] * b[i*2]; + sum1 += a[i*2+1] * b[i*2+1]; + } + static if (N % 2 == 1) + { + sum0 += a[N-1] * b[N-1]; + } + return sum0 + sum1; +} + @system unittest { // @system due to dotProduct and assertCTFEable @@ -1785,6 +1803,13 @@ dotProduct(F1, F2)(in F1[] avector, in F2[] bvector) T[] b = [ 4.0, 6.0, ]; assert(dotProduct(a, b) == 16); assert(dotProduct([1, 3, -5], [4, -2, -1]) == 3); + // Test with fixed-length arrays. + T[2] c = [ 1.0, 2.0, ]; + T[2] d = [ 4.0, 6.0, ]; + assert(dotProduct(c, d) == 16); + T[3] e = [1, 3, -5]; + T[3] f = [4, -2, -1]; + assert(dotProduct(e, f) == 3); }} // Make sure the unrolled loop codepath gets tested. From cc5f89f524749f0849f59205e1a4b07374c3eb89 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Sat, 4 May 2019 16:36:43 -0400 Subject: [PATCH 09/77] Fix wrong code formatting --- std/algorithm/iteration.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/algorithm/iteration.d b/std/algorithm/iteration.d index 7888fa29eb8..9ed24c335f9 100644 --- a/std/algorithm/iteration.d +++ b/std/algorithm/iteration.d @@ -6320,7 +6320,7 @@ b)(r, 0), `sum` uses specialized algorithms to maximize accuracy, as follows. $(UL -$(LI If `$(REF ElementType, std,range,primitives)!R` is a floating-point +$(LI If $(REF ElementType, std,range,primitives)!R is a floating-point type and `R` is a $(REF_ALTTEXT random-access range, isRandomAccessRange, std,range,primitives) with length and slicing, then `sum` uses the From c75d29af5268cfdebddfdb2679b09eca1176cf32 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Sun, 5 May 2019 02:13:35 +0200 Subject: [PATCH 10/77] purge changelog --- changelog/comparison_bug.dd | 6 ------ changelog/std-all.dd | 43 ------------------------------------- 2 files changed, 49 deletions(-) delete mode 100644 changelog/comparison_bug.dd delete mode 100644 changelog/std-all.dd diff --git a/changelog/comparison_bug.dd b/changelog/comparison_bug.dd deleted file mode 100644 index fbdc59da973..00000000000 --- a/changelog/comparison_bug.dd +++ /dev/null @@ -1,6 +0,0 @@ -Fixed comparison bug in `std.algorithm.comparison.levenshteinDistance` - -Previously the algorithm was allocating the amount of memory which was equal to -the size of the biggest range, that is $(BIGOH max(s.length, t.length)). -This is now fixed to be $(BIGOH min(s.length, t.length)). -For more details see $(REF levenshteinDistance, std, algorithm, comparison). diff --git a/changelog/std-all.dd b/changelog/std-all.dd deleted file mode 100644 index 366ecbf7f75..00000000000 --- a/changelog/std-all.dd +++ /dev/null @@ -1,43 +0,0 @@ -`std.experimental.all` has been moved to `std` - -`std.experimental.all` allowed the convenient use of all Phobos modules -with one import (`import std.experimental.all;`). With this release, this -convenience module has been stabilized and moved to `std`. From now on, the -convenience module can be accessed with `import std;`: - ---- -import std; -void main() -{ - 5f.iota.map!exp2.sum; // 31 -} ---- - -Scripts and experimental code often use long and frequently changing -lists of imports from the standard library. - -With this release it is possible to use `import std;` for importing the entire -standard library at once. This can be used for fast prototyping or REPLs: - ---- -import std; -void main() -{ - 6.iota - .filter!(a => a % 2) // 1 3 5 - .map!(a => a * 2) // 2 6 10 - .tee!writeln // peek into the processed stream - .substitute(6, -6) // 2 -6 10 - .mean // (2 - 6 + 10) / 3 - .reverseArgs!writefln("Sum: %.2f"); // 2 -} ---- - -As before, symbol conflicts will only arise if a symbol with collisions is used. -In this case, $(LINK2 $(ROOT)spec/module.html#static_imports, static imports) or -$(LINK2 $(ROOT)spec/module.html#renamed_imports, renamed imports) can be used -to uniquely select a specific symbol. - -The baseline cost for `import std;` -is less than half a second (varying from system to system) and -work is in progress to reduce this overhead even further. From 8d499765142b2bb7c97ca07d7f8b9afc17cb5776 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Mon, 6 May 2019 04:55:54 -0400 Subject: [PATCH 11/77] Issue 19836 followup - also fix on 32 bit machines Changed the private enhanced seeding method for `rndGen` to something that is fast on both 64 bit and 32 bit machines so can be enabled regardless of architecture. When compiled with LDC it is about 1.35x the speed of public `Mt19937.seed(uint)`. --- std/random.d | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/std/random.d b/std/random.d index b21b184b692..92223a03a62 100644 --- a/std/random.d +++ b/std/random.d @@ -1813,8 +1813,8 @@ A singleton instance of the default random number generator { static if (isSeedable!(Random, ulong)) result.seed(unpredictableSeed!ulong); // Avoid unnecessary copy. - else static if (size_t.sizeof >= ulong.sizeof && is(Random : MersenneTwisterEngine!Params, Params...)) - initMTEngine(result); // 64-bit multiplication is fast, so use a 64-bit seed. + else static if (is(Random : MersenneTwisterEngine!Params, Params...)) + initMTEngine(result); else static if (isSeedable!(Random, uint)) result.seed(unpredictableSeed!uint); // Avoid unnecessary copy. else @@ -1842,23 +1842,36 @@ private void initMTEngine(MTEngine)(scope ref MTEngine mt) if (is(MTEngine : MersenneTwisterEngine!Params, Params...)) { pragma(inline, false); // Called no more than once per thread by rndGen. - ulong x = unpredictableSeed!ulong; - alias UIntType = typeof(mt.front()); - foreach (size_t i, ref e; mt.state.data) + ulong seed = unpredictableSeed!ulong; + static if (is(typeof(mt.seed(seed)))) { - x = (x ^ (x >> 62)) * 6_364_136_223_846_793_005UL + i; - e = cast(UIntType) x; - static if (MTEngine.max != UIntType.max) + mt.seed(seed); + } + else + { + alias UIntType = typeof(mt.front()); + if (seed == 0) seed = -1; // Any number but 0 is fine. + uint s0 = cast(uint) seed; + uint s1 = cast(uint) (seed >> 32); + foreach (ref e; mt.state.data) { - e &= MTEngine.max; + //http://xoshiro.di.unimi.it/xoroshiro64starstar.c + const tmp = s0 * 0x9E3779BB; + e = ((tmp << 5) | (tmp >> (32 - 5))) * 5; + static if (MTEngine.max != UIntType.max) { e &= MTEngine.max; } + + const tmp1 = s0 ^ s1; + s0 = ((s0 << 26) | (s0 >> (32 - 26))) ^ tmp1 ^ (tmp1 << 9); + s1 = (tmp1 << 13) | (tmp1 >> (32 - 13)); } + + mt.state.index = mt.state.data.length - 1; + // double popFront() to guarantee both `mt.state.z` + // and `mt.state.front` are derived from the newly + // set values in `mt.state.data`. + mt.popFront(); + mt.popFront(); } - mt.state.index = mt.state.data.length - 1; - // double popFront() to guarantee both `mt.state.z` - // and `mt.state.front` are derived from the newly - // set values in `mt.state.data`. - mt.popFront(); - mt.popFront(); } /** From e2ab79408bd176ad438928faabcd76ee9e9bdbcc Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Wed, 13 Mar 2019 16:53:59 +0800 Subject: [PATCH 12/77] Issue 3525 was fixed --- std/typecons.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/typecons.d b/std/typecons.d index ee46a30fbe5..7010cc3ffe2 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -4514,7 +4514,7 @@ $(UL $(LI Variadic arguments to constructors are not forwarded to super.) $(LI Deep interface inheritance causes compile error with messages like "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar - does not override any function". [$(BUGZILLA 2525), $(BUGZILLA 3525)] ) + does not override any function". [$(BUGZILLA 2525)] ) $(LI The `parent` keyword is actually a delegate to the super class' corresponding member function. [$(BUGZILLA 2540)] ) $(LI Using alias template parameter in `how` and/or `what` may cause From 53bdd83de7f525d794ac2c982f76054dc497da54 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 9 Jun 2018 01:01:43 -0700 Subject: [PATCH 13/77] primitives: add scope --- std/range/primitives.d | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/std/range/primitives.d b/std/range/primitives.d index 942cab66da9..cbeebdbb38f 100644 --- a/std/range/primitives.d +++ b/std/range/primitives.d @@ -498,7 +498,7 @@ void put(R, E)(ref R r, E e) @safe pure nothrow @nogc unittest { - static struct R() { void put(in char[]) {} } + static struct R() { void put(scope const(char)[]) {} } R!() r; put(r, 'a'); } @@ -559,7 +559,7 @@ pure @safe unittest @safe pure unittest { - static struct R() { void put(in char[]) {} } + static struct R() { void put(scope const(char)[]) {} } R!() r; putChar(r, 'a'); } @@ -586,7 +586,7 @@ pure @safe unittest @safe unittest { - void myprint(in char[] s) { } + void myprint(scope const(char)[] s) { } auto r = &myprint; put(r, 'a'); } @@ -812,7 +812,7 @@ pure @safe unittest // issue 10571 import std.format; string buf; - formattedWrite((in char[] s) { buf ~= s; }, "%s", "hello"); + formattedWrite((scope const(char)[] s) { buf ~= s; }, "%s", "hello"); assert(buf == "hello"); } @@ -912,7 +912,7 @@ enum bool isOutputRange(R, E) = /// @safe unittest { - void myprint(in char[] s) { } + void myprint(scope const(char)[] s) { } static assert(isOutputRange!(typeof(&myprint), char)); static assert( isOutputRange!(char[], char)); From 7b357e2eb2a4a57d9073792f17006bf3aa6f33aa Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 1 Nov 2018 17:23:51 +0200 Subject: [PATCH 14/77] Move std.numeric.CustomFloat.ToBinary to top-level --- std/numeric.d | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/std/numeric.d b/std/numeric.d index e21304ddd5c..5251317c4c8 100644 --- a/std/numeric.d +++ b/std/numeric.d @@ -145,6 +145,27 @@ if (((flags & flags.signed) + precision + exponentWidth) % 8 == 0 && precision + auto p = Probability(0.5); } +// Facilitate converting numeric types to custom float +private union ToBinary(F) +if (is(typeof(CustomFloatParams!(F.sizeof*8))) || is(F == real)) +{ + F set; + + // If on Linux or Mac, where 80-bit reals are padded, ignore the + // padding. + import std.algorithm.comparison : min; + CustomFloat!(CustomFloatParams!(min(F.sizeof*8, 80))) get; + + // Convert F to the correct binary type. + static typeof(get) opCall(F value) + { + ToBinary r; + r.set = value; + return r.get; + } + alias get this; +} + /// ditto struct CustomFloat(uint precision, // fraction bits (23 for float) uint exponentWidth, // exponent bits (8 for float) Exponent width @@ -176,27 +197,6 @@ private: alias Flags = CustomFloatFlags; - // Facilitate converting numeric types to custom float - union ToBinary(F) - if (is(typeof(CustomFloatParams!(F.sizeof*8))) || is(F == real)) - { - F set; - - // If on Linux or Mac, where 80-bit reals are padded, ignore the - // padding. - import std.algorithm.comparison : min; - CustomFloat!(CustomFloatParams!(min(F.sizeof*8, 80))) get; - - // Convert F to the correct binary type. - static typeof(get) opCall(F value) - { - ToBinary r; - r.set = value; - return r.get; - } - alias get this; - } - // Perform IEEE rounding with round to nearest detection void roundedShift(T,U)(ref T sig, U shift) { From 2c56956d4d62effd661007e44973750ecead121a Mon Sep 17 00:00:00 2001 From: John Colvin Date: Tue, 18 Jul 2017 23:04:20 +0100 Subject: [PATCH 15/77] implement aliasSeqOf for all iterables --- std/meta.d | 58 +++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/std/meta.d b/std/meta.d index c1685d2bc2f..dbb29bccf56 100644 --- a/std/meta.d +++ b/std/meta.d @@ -1086,43 +1086,24 @@ template templateOr(Preds...) } } +import std.traits : isIterable; + /** - * Converts an $(REF_ALTTEXT input range, isInputRange, std,range,primitives) - * `range` to an alias sequence. + * Converts any foreach iterable (e.g. an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)) + * to an alias sequence. */ -template aliasSeqOf(alias range) +template aliasSeqOf(alias iter) +if (isIterable!(typeof(iter))) { - import std.traits : isArray, isNarrowString; + import std.traits : isNarrowString; + import std.array : array; - alias ArrT = typeof(range); - static if (isArray!ArrT && !isNarrowString!ArrT) + struct Impl { - static if (range.length == 0) - { - alias aliasSeqOf = AliasSeq!(); - } - else static if (range.length == 1) - { - alias aliasSeqOf = AliasSeq!(range[0]); - } - else - { - alias aliasSeqOf = AliasSeq!(aliasSeqOf!(range[0 .. $/2]), aliasSeqOf!(range[$/2 .. $])); - } - } - else - { - import std.range.primitives : isInputRange; - static if (isInputRange!ArrT) - { - import std.array : array; - alias aliasSeqOf = aliasSeqOf!(array(range)); - } - else - { - static assert(false, "Cannot transform range of type " ~ ArrT.stringof ~ " into a AliasSeq."); - } + static foreach (size_t i, el; iter.array) + mixin(`auto e` ~ i.stringof ~ ` = el;`); } + enum aliasSeqOf = Impl.init.tupleof; } /// @@ -1181,6 +1162,21 @@ template aliasSeqOf(alias range) } } +@safe unittest +{ + struct S + { + int opApply(scope int delegate(ref int) dg) + { + foreach(int i; 3 .. 5) + if (auto r = dg(i)) + return r; + return 0; + } + } + static assert(aliasSeqOf!(S.init) == AliasSeq!(3, 4)); +} + /** * $(LINK2 http://en.wikipedia.org/wiki/Partial_application, Partially applies) * $(D_PARAM Template) by binding its first (left) or last (right) arguments From f24698554e5af2040fe82d921eac639ba58a23de Mon Sep 17 00:00:00 2001 From: John Colvin Date: Wed, 19 Jul 2017 01:41:28 +0100 Subject: [PATCH 16/77] Remove unnecessary import --- std/meta.d | 1 - 1 file changed, 1 deletion(-) diff --git a/std/meta.d b/std/meta.d index dbb29bccf56..38bc9ff1bae 100644 --- a/std/meta.d +++ b/std/meta.d @@ -1095,7 +1095,6 @@ import std.traits : isIterable; template aliasSeqOf(alias iter) if (isIterable!(typeof(iter))) { - import std.traits : isNarrowString; import std.array : array; struct Impl From 9a05c1d50f67a55244b83a5b2847602f251cc6a0 Mon Sep 17 00:00:00 2001 From: John Colvin Date: Tue, 3 Apr 2018 12:10:21 +0100 Subject: [PATCH 17/77] fix param name in docs --- std/meta.d | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/std/meta.d b/std/meta.d index 38bc9ff1bae..5f7669aa65d 100644 --- a/std/meta.d +++ b/std/meta.d @@ -1089,8 +1089,7 @@ template templateOr(Preds...) import std.traits : isIterable; /** - * Converts any foreach iterable (e.g. an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)) - * to an alias sequence. + * Converts any foreach-iterable (e.g. an input range) `iter` to an alias sequence. */ template aliasSeqOf(alias iter) if (isIterable!(typeof(iter))) From c3ebee93cdb25ff18783c56760a68c888d66c36c Mon Sep 17 00:00:00 2001 From: John Colvin Date: Tue, 3 Apr 2018 21:44:44 +0100 Subject: [PATCH 18/77] test for infinite ranges --- std/meta.d | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/std/meta.d b/std/meta.d index 5f7669aa65d..3b6f4f934d0 100644 --- a/std/meta.d +++ b/std/meta.d @@ -1087,12 +1087,13 @@ template templateOr(Preds...) } import std.traits : isIterable; +import std.range.primitives : isInfinite; /** * Converts any foreach-iterable (e.g. an input range) `iter` to an alias sequence. */ template aliasSeqOf(alias iter) -if (isIterable!(typeof(iter))) +if (isIterable!(typeof(iter)) && !isInfinite!(typeof(iter))) { import std.array : array; @@ -1175,6 +1176,19 @@ if (isIterable!(typeof(iter))) static assert(aliasSeqOf!(S.init) == AliasSeq!(3, 4)); } +@safe unittest +{ + struct Infinite + { + int front(); + void popFront(); + enum empty = false; + } + enum infinite = Infinite(); + static assert(isInfinite!Infinite); + static assert(!__traits(compiles, aliasSeqOf!infinite)); +} + /** * $(LINK2 http://en.wikipedia.org/wiki/Partial_application, Partially applies) * $(D_PARAM Template) by binding its first (left) or last (right) arguments From 13fcd0c0833e29a3fb77b7587ddba2b26d22b25a Mon Sep 17 00:00:00 2001 From: John Colvin Date: Tue, 3 Apr 2018 21:57:19 +0100 Subject: [PATCH 19/77] formatting --- std/meta.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/meta.d b/std/meta.d index 3b6f4f934d0..70dfbd6c33e 100644 --- a/std/meta.d +++ b/std/meta.d @@ -1167,7 +1167,7 @@ if (isIterable!(typeof(iter)) && !isInfinite!(typeof(iter))) { int opApply(scope int delegate(ref int) dg) { - foreach(int i; 3 .. 5) + foreach (int i; 3 .. 5) if (auto r = dg(i)) return r; return 0; From 0998483fb24931160d43afaa5945fa7fcaf35208 Mon Sep 17 00:00:00 2001 From: John Colvin Date: Tue, 3 Apr 2018 22:29:50 +0100 Subject: [PATCH 20/77] move imports to top --- std/meta.d | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/std/meta.d b/std/meta.d index 70dfbd6c33e..f39a0ff1431 100644 --- a/std/meta.d +++ b/std/meta.d @@ -77,6 +77,9 @@ module std.meta; +import std.traits : isAggregateType, Unqual, isIterable; +import std.range.primitives : isInfinite; + /** * Creates a sequence of zero or more aliases. This is most commonly * used as template parameters or arguments. @@ -252,8 +255,6 @@ package template OldAlias(alias a) static assert(0, "Cannot alias " ~ a.stringof); } -import std.traits : isAggregateType, Unqual; - package template OldAlias(T) if (!isAggregateType!T || is(Unqual!T == T)) { @@ -1086,9 +1087,6 @@ template templateOr(Preds...) } } -import std.traits : isIterable; -import std.range.primitives : isInfinite; - /** * Converts any foreach-iterable (e.g. an input range) `iter` to an alias sequence. */ From 6140c01ed2e89e700bf8b74cbe0ef9887d9e28ec Mon Sep 17 00:00:00 2001 From: MetaLang Date: Wed, 4 Apr 2018 00:40:03 -0300 Subject: [PATCH 21/77] Add Params and Returns sections, and fix typo --- std/meta.d | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/std/meta.d b/std/meta.d index f39a0ff1431..736dc04f2cc 100644 --- a/std/meta.d +++ b/std/meta.d @@ -1088,7 +1088,14 @@ template templateOr(Preds...) } /** - * Converts any foreach-iterable (e.g. an input range) `iter` to an alias sequence. + * Converts any foreach-iterable entity (e.g. an input range) to an alias sequence. + * + * Params: + * iter = the entity to convert into an `AliasSeq`. It must be able to be able to be iterated over using + * a $(LINK2 https://dlang.org/spec/statement.html#foreach-statement, foreach-statement). + * + * Returns: + * An `AliasSeq` containing the values produced by iterating over `iter`. */ template aliasSeqOf(alias iter) if (isIterable!(typeof(iter)) && !isInfinite!(typeof(iter))) From 4bfcd207642a8bf081485ba67d56e1fed8523850 Mon Sep 17 00:00:00 2001 From: MetaLang Date: Wed, 4 Apr 2018 00:45:57 -0300 Subject: [PATCH 22/77] Remove trailing whitespace --- std/meta.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/meta.d b/std/meta.d index 736dc04f2cc..e0d8544dd63 100644 --- a/std/meta.d +++ b/std/meta.d @@ -1089,9 +1089,9 @@ template templateOr(Preds...) /** * Converts any foreach-iterable entity (e.g. an input range) to an alias sequence. - * + * * Params: - * iter = the entity to convert into an `AliasSeq`. It must be able to be able to be iterated over using + * iter = the entity to convert into an `AliasSeq`. It must be able to be able to be iterated over using * a $(LINK2 https://dlang.org/spec/statement.html#foreach-statement, foreach-statement). * * Returns: From 32346c8ded852bcfc0488b78b962b7b509367627 Mon Sep 17 00:00:00 2001 From: Aurelien Fredouelle Date: Fri, 10 May 2019 17:27:12 +0100 Subject: [PATCH 23/77] Fixed Issue 13965 - More handy schwartzSort --- changelog/new_schwartzSort_overload.dd | 12 ++++++++++++ std/algorithm/sorting.d | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 changelog/new_schwartzSort_overload.dd diff --git a/changelog/new_schwartzSort_overload.dd b/changelog/new_schwartzSort_overload.dd new file mode 100644 index 00000000000..3bd1fca4c39 --- /dev/null +++ b/changelog/new_schwartzSort_overload.dd @@ -0,0 +1,12 @@ +Add overload `std.algorithm.sorting.schwartzSort!(alias transform, SwapStrategy ss, R)` + +$(REF schwartzSort, std,algorithm,sorting) now has an overloaded version that can be +used to provide a `SwapStrategy` without also explicitly specifying the predicate to +sort by. + +------- +auto s1 = a.schwartzSort!(abs, SwapStrategy.stable); + +// The old syntax still works. +auto s2 = a.schwartzSort!(abs, "a < b", SwapStrategy.stable); +------- diff --git a/std/algorithm/sorting.d b/std/algorithm/sorting.d index a0357bdc366..6f69b51fa0a 100644 --- a/std/algorithm/sorting.d +++ b/std/algorithm/sorting.d @@ -2910,7 +2910,8 @@ SortedRange!(R, ((a, b) => binaryFun!less(unaryFun!transform(a), unaryFun!transform(b)))) schwartzSort(alias transform, alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, R)(R r) -if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R) +if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R && + !is(typeof(binaryFun!less) == SwapStrategy)) { import std.conv : emplace; import std.range : zip, SortedRange; @@ -2960,6 +2961,13 @@ if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R) return typeof(return)(r); } +/// ditto +auto schwartzSort(alias transform, SwapStrategy ss, R)(R r) +if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R) +{ + return schwartzSort!(transform, "a < b", ss, R)(r); +} + /// @safe unittest { @@ -3019,6 +3027,14 @@ if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R) schwartzSort!((Tuple!(char) c){ return c[0]; })(chars); } +@safe unittest +{ + // issue 13965 + import std.typecons : Tuple; + Tuple!(char)[] chars; + schwartzSort!("a[0]", SwapStrategy.stable)(chars); +} + // partialSort /** Reorders the random-access range `r` such that the range `r[0 .. mid]` From f03f7ac18970549e638f405aca4a8ae099183f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Fredouelle?= Date: Sat, 11 May 2019 09:15:52 +0100 Subject: [PATCH 24/77] schwartzSort: added test actually checking the ordering --- std/algorithm/sorting.d | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/std/algorithm/sorting.d b/std/algorithm/sorting.d index 6f69b51fa0a..3a73648d203 100644 --- a/std/algorithm/sorting.d +++ b/std/algorithm/sorting.d @@ -3035,6 +3035,28 @@ if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R) schwartzSort!("a[0]", SwapStrategy.stable)(chars); } +@safe unittest +{ + // issue 13965 + import std.algorithm.iteration : map; + import std.numeric : entropy; + + auto lowEnt = [ 1.0, 0, 0 ], + midEnt = [ 0.1, 0.1, 0.8 ], + highEnt = [ 0.31, 0.29, 0.4 ]; + auto arr = new double[][3]; + arr[0] = midEnt; + arr[1] = lowEnt; + arr[2] = highEnt; + + schwartzSort!(entropy, SwapStrategy.stable)(arr); + + assert(arr[0] == lowEnt); + assert(arr[1] == midEnt); + assert(arr[2] == highEnt); + assert(isSorted!("a < b")(map!(entropy)(arr))); +} + // partialSort /** Reorders the random-access range `r` such that the range `r[0 .. mid]` From d33c1ebc1004c2daad8948f6f3bea1e4b924b916 Mon Sep 17 00:00:00 2001 From: FeepingCreature Date: Sat, 11 May 2019 12:55:57 +0100 Subject: [PATCH 25/77] Fix issues arising from the DMD 9029 fix (types match to alias) --- std/conv.d | 2 +- std/typecons.d | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/std/conv.d b/std/conv.d index 05e59587030..765e0e8f34a 100644 --- a/std/conv.d +++ b/std/conv.d @@ -4076,7 +4076,7 @@ if (isOctalLiteral(num)) /// Ditto template octal(alias decimalInteger) -if (isIntegral!(typeof(decimalInteger))) +if (is(typeof(decimalInteger)) && isIntegral!(typeof(decimalInteger))) { enum octal = octal!(typeof(decimalInteger))(to!string(decimalInteger)); } diff --git a/std/typecons.d b/std/typecons.d index d068cd82158..e45ffcd8899 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -5022,10 +5022,11 @@ package template OverloadSet(string nam, T...) /* Used by MemberFunctionGenerator. */ -package template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) +package template FuncInfo(alias func) +if (is(typeof(&func))) { - alias RT = ReturnType!T; - alias PT = Parameters!T; + alias RT = ReturnType!(typeof(&func)); + alias PT = Parameters!(typeof(&func)); } package template FuncInfo(Func) { From b4756c2f5f01364f78d91d38124b4a873da40e2e Mon Sep 17 00:00:00 2001 From: Marco de Wild Date: Sun, 12 May 2019 00:19:38 +0200 Subject: [PATCH 26/77] Improved error message when an assocArray can't be created --- std/array.d | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/std/array.d b/std/array.d index aa6c28bc5f7..dfb4f76c5a7 100644 --- a/std/array.d +++ b/std/array.d @@ -442,7 +442,8 @@ if (isInputRange!Range) import std.typecons : isTuple; alias E = ElementType!Range; - static assert(isTuple!E, "assocArray: argument must be a range of tuples"); + static assert(isTuple!E, "assocArray: argument must be a range of tuples," + ~" but was a range of "~E.stringof); static assert(E.length == 2, "assocArray: tuple dimension must be 2"); alias KeyType = E.Types[0]; alias ValueType = E.Types[1]; @@ -552,6 +553,7 @@ if (isInputRange!Values && isInputRange!Keys) @safe unittest { import std.typecons; + static assert(!__traits(compiles, [ 1, 2, 3 ].assocArray())); static assert(!__traits(compiles, [ tuple("foo", "bar", "baz") ].assocArray())); static assert(!__traits(compiles, [ tuple("foo") ].assocArray())); assert([ tuple("foo", "bar") ].assocArray() == ["foo": "bar"]); From db843f18822ba676642173d1e8277a5caeaad40b Mon Sep 17 00:00:00 2001 From: Marco de Wild Date: Tue, 14 May 2019 09:30:37 +0200 Subject: [PATCH 27/77] Explicitly stated that the enum name can be retrieved with __traits --- std/traits.d | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/std/traits.d b/std/traits.d index 13d4cb06cdc..22bd6b8fe29 100644 --- a/std/traits.d +++ b/std/traits.d @@ -4072,6 +4072,9 @@ Params: Returns: Static tuple composed of the members of the enumerated type `E`. The members are arranged in the same order as declared in `E`. + The name of the enum can be found by querying the compiler for the + name of the identifier, i.e. `__traits(identifier, EnumMembers!MyEnum[i])`. + For enumerations with unique values, $(REF to, std,conv) can also be used. Note: An enum can have multiple members which have the same value. If you want @@ -4180,6 +4183,39 @@ template for finding a member `e` in an enumerated type `E`. assert(rank(Mode.map) == 2); } +/** +Use EnumMembers to generate a switch statement using static foreach. +*/ + +@safe unittest +{ + import std.conv : to; + class FooClass + { + string calledMethod; + void foo() @safe { calledMethod = "foo"; } + void bar() @safe { calledMethod = "bar"; } + void baz() @safe { calledMethod = "baz"; } + } + + enum FooEnum { foo, bar, baz } + + auto var = FooEnum.bar; + auto fooObj = new FooClass(); + s: final switch (var) + { + static foreach (member; EnumMembers!FooEnum) + { + case member: // Generate a case for each enum value. + // Call fooObj.{name of enum value}(). + __traits(getMember, fooObj, to!string(member))(); + break s; + } + } + // As we pass in FooEnum.bar, the bar() method gets called. + assert(fooObj.calledMethod == "bar"); +} + @safe unittest { enum A { a } From 4b3537980fd811bb108dabb684aadc2fa194754f Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Sat, 23 Mar 2019 10:52:49 +0100 Subject: [PATCH 28/77] Build entire Phobos with -preview=dip1000 --- posix.mak | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/posix.mak b/posix.mak index 6126b8aa84e..32c11d0d2e3 100644 --- a/posix.mak +++ b/posix.mak @@ -138,7 +138,7 @@ endif # Set DFLAGS DFLAGS= -override DFLAGS+=-conf= -I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS) -w -de -preview=dip25 $(MODEL_FLAG) $(PIC) -transition=complex +override DFLAGS+=-conf= -I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS) -w -de -preview=dip1000 $(MODEL_FLAG) $(PIC) -transition=complex ifeq ($(BUILD),debug) override DFLAGS += -g -debug else @@ -362,7 +362,7 @@ UT_D_OBJS:=$(addprefix $(ROOT)/unittest/,$(addsuffix $(DOTOBJ),$(D_MODULES))) $(UT_D_OBJS): $(ALL_D_FILES) $(UT_D_OBJS): $(ROOT)/unittest/%$(DOTOBJ): %.d @mkdir -p $(dir $@) - $(DMD) $(DFLAGS) $(UDFLAGS) -preview=dip1000 -c -of$@ $< + $(DMD) $(DFLAGS) $(UDFLAGS) -c -of$@ $< ifneq (1,$(SHARED)) @@ -647,7 +647,7 @@ betterc: betterc-phobos-tests @[ -f "$(TESTS_EXTRACTOR)" ] || ${MAKE} -f posix.mak "$(TESTS_EXTRACTOR)" @$(TESTS_EXTRACTOR) --betterC --attributes betterC \ --inputdir $< --outputdir $(BETTERCTESTS_DIR) - @$(DMD) $(DFLAGS) $(NODEFAULTLIB) -betterC $(UDFLAGS) -preview=dip1000 -run $(BETTERCTESTS_DIR)/$(subst /,_,$<) + @$(DMD) $(DFLAGS) $(NODEFAULTLIB) -betterC $(UDFLAGS) -run $(BETTERCTESTS_DIR)/$(subst /,_,$<) ################################################################################ From 03f19cf3d2dd2dfd36c72b2f34bb2b90f9079f33 Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Wed, 15 May 2019 10:41:19 +0900 Subject: [PATCH 29/77] regex/internal/parser.d: remove unreachable statement --- std/regex/internal/parser.d | 1 - 1 file changed, 1 deletion(-) diff --git a/std/regex/internal/parser.d b/std/regex/internal/parser.d index a4706b997f0..74068d7a2df 100644 --- a/std/regex/internal/parser.d +++ b/std/regex/internal/parser.d @@ -842,7 +842,6 @@ if (isForwardRange!R && is(ElementType!R : dchar)) { case '*', '?', '+', '|', '{', '}': error("'*', '+', '?', '{', '}' not allowed in atom"); - break; case '.': if (re_flags & RegexOption.singleline) g.put(Bytecode(IR.Any, 0)); From b77691c2e2cafce2ff7747fbfe620f95228b6e1e Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Wed, 15 May 2019 08:58:54 +0200 Subject: [PATCH 30/77] Add changelog entry for -dip1000 --- changelog/phobos-dip1000.dd | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelog/phobos-dip1000.dd diff --git a/changelog/phobos-dip1000.dd b/changelog/phobos-dip1000.dd new file mode 100644 index 00000000000..812f3c6c275 --- /dev/null +++ b/changelog/phobos-dip1000.dd @@ -0,0 +1,7 @@ +Phobos is now compiled with -preview=dip1000 + +Phobos and Druntime are now compiled with -preview=dip1000. + +This is a major milestone in the transition to $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md, DIP1000). Hence, end users can now start using `-preview=dip1000` in their own code bases. + +As always, any encountered issue should be reported to the $(LINK2 https://issues.dlang.org, issue tracker). From 6af0f680583f954596d25cc9aee1794d0fa10eec Mon Sep 17 00:00:00 2001 From: dukc Date: Thu, 16 May 2019 18:19:06 +0300 Subject: [PATCH 31/77] Added an enumerated type of ASCII control character. --- changelog/asciicontroltable.dd | 10 ++++++ std/ascii.d | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 changelog/asciicontroltable.dd diff --git a/changelog/asciicontroltable.dd b/changelog/asciicontroltable.dd new file mode 100644 index 00000000000..774514c5e82 --- /dev/null +++ b/changelog/asciicontroltable.dd @@ -0,0 +1,10 @@ +Added a table of control characters in ASCII table + +There is a new enumerated type $(REF ControlChar, std, ascii). It has +values for every control character in ASCII table and has a base type +of `char`, allowing for alternative markup of strings with control +characters: +------- +import std.ascii, std.conv; +with (ControlChar) assert(text("Phobos", US, "Deimos", US, "Tango", RS) == "Phobos\x1FDeimos\x1FTango\x1E"); +------- diff --git a/std/ascii.d b/std/ascii.d index 9b0f547caa1..6436afd77be 100644 --- a/std/ascii.d +++ b/std/ascii.d @@ -46,6 +46,7 @@ $(TR $(TD Constants) $(TD $(LREF whitespace) )) $(TR $(TD Enums) $(TD + $(LREF ControlChar) $(LREF LetterCase) )) )) @@ -102,6 +103,70 @@ enum LetterCase : bool assert(sha1HMAC == "49f2073c7bf58577e8c9ae59fe8cfd37c9ab94e5"); } +/++ + All the control characters in ASCII table ++/ +enum ControlChar : char +{ + NUL = '\x00', /// Null + SOH = '\x01', /// Start of heading + STX = '\x02', /// Start of text + ETX = '\x03', /// End of text + EOT = '\x04', /// End of transmission + ENQ = '\x05', /// Enquiry + ACK = '\x06', /// Acknowledge + BEL = '\x07', /// Bell + BS = '\x08', /// Backspace + TAB = '\x09', /// Horizontal tab + LF = '\x0A', /// NL line feed, new line + VT = '\x0B', /// Vertical tab + FF = '\x0C', /// NP form feed, new page + CR = '\x0D', /// Carriage return + SO = '\x0E', /// Shift out + SI = '\x0F', /// Shift in + DLE = '\x10', /// Data link escape + DC1 = '\x11', /// Device control 1 + DC2 = '\x12', /// Device control 2 + DC3 = '\x13', /// Device control 3 + DC4 = '\x14', /// Device control 4 + NAK = '\x15', /// Negative acknowledge + SYN = '\x16', /// Synchronous idle + ETB = '\x17', /// End of transmission block + CAN = '\x18', /// Cancel + EM = '\x19', /// End of medium + SUB = '\x1A', /// Substitute + ESC = '\x1B', /// Escape + FS = '\x1C', /// File separator + GS = '\x1D', /// Group separator + RS = '\x1E', /// Record separator + US = '\x1F', /// Unit separator + DEL = '\x7F' /// Delete +} + +/// +@safe pure nothrow @nogc unittest +{ + // Because all ASCII characters fit in char, so do these + static assert(ControlChar.ACK.sizeof == 1); + + static assert(ControlChar.NUL == '\0'); + static assert(ControlChar.BEL == '\a'); + static assert(ControlChar.BS == '\b'); + static assert(ControlChar.FF == '\f'); + static assert(ControlChar.LF == '\n'); + static assert(ControlChar.CR == '\r'); + static assert(ControlChar.TAB == '\t'); + static assert(ControlChar.VT == '\v'); +} + +/// +@safe pure nothrow unittest +{ + import std.conv; + //Control character table can be used in place of hexcodes. + with (ControlChar) assert(text("Phobos", US, "Deimos", US, "Tango", RS) == "Phobos\x1FDeimos\x1FTango\x1E"); +} + /// Newline sequence for this system. version (Windows) immutable newline = "\r\n"; From 778e30781672965ce947608b00ccc6bf56a5169e Mon Sep 17 00:00:00 2001 From: dukc Date: Thu, 16 May 2019 22:53:47 +0300 Subject: [PATCH 32/77] Character abbveriation to lowercase according to style guide. --- changelog/asciicontroltable.dd | 2 +- std/ascii.d | 86 +++++++++++++++++----------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/changelog/asciicontroltable.dd b/changelog/asciicontroltable.dd index 774514c5e82..b0517b37407 100644 --- a/changelog/asciicontroltable.dd +++ b/changelog/asciicontroltable.dd @@ -6,5 +6,5 @@ of `char`, allowing for alternative markup of strings with control characters: ------- import std.ascii, std.conv; -with (ControlChar) assert(text("Phobos", US, "Deimos", US, "Tango", RS) == "Phobos\x1FDeimos\x1FTango\x1E"); +with (ControlChar) assert(text("Phobos", us, "Deimos", us, "Tango", rs) == "Phobos\x1FDeimos\x1FTango\x1E"); ------- diff --git a/std/ascii.d b/std/ascii.d index 6436afd77be..07f4a6a00ca 100644 --- a/std/ascii.d +++ b/std/ascii.d @@ -108,55 +108,55 @@ enum LetterCase : bool +/ enum ControlChar : char { - NUL = '\x00', /// Null - SOH = '\x01', /// Start of heading - STX = '\x02', /// Start of text - ETX = '\x03', /// End of text - EOT = '\x04', /// End of transmission - ENQ = '\x05', /// Enquiry - ACK = '\x06', /// Acknowledge - BEL = '\x07', /// Bell - BS = '\x08', /// Backspace - TAB = '\x09', /// Horizontal tab - LF = '\x0A', /// NL line feed, new line - VT = '\x0B', /// Vertical tab - FF = '\x0C', /// NP form feed, new page - CR = '\x0D', /// Carriage return - SO = '\x0E', /// Shift out - SI = '\x0F', /// Shift in - DLE = '\x10', /// Data link escape - DC1 = '\x11', /// Device control 1 - DC2 = '\x12', /// Device control 2 - DC3 = '\x13', /// Device control 3 - DC4 = '\x14', /// Device control 4 - NAK = '\x15', /// Negative acknowledge - SYN = '\x16', /// Synchronous idle - ETB = '\x17', /// End of transmission block - CAN = '\x18', /// Cancel - EM = '\x19', /// End of medium - SUB = '\x1A', /// Substitute - ESC = '\x1B', /// Escape - FS = '\x1C', /// File separator - GS = '\x1D', /// Group separator - RS = '\x1E', /// Record separator - US = '\x1F', /// Unit separator - DEL = '\x7F' /// Delete + nul = '\x00', /// Null + soh = '\x01', /// Start of heading + stx = '\x02', /// Start of text + etx = '\x03', /// End of text + eot = '\x04', /// End of transmission + enq = '\x05', /// Enquiry + ack = '\x06', /// Acknowledge + bel = '\x07', /// Bell + bs = '\x08', /// Backspace + tab = '\x09', /// Horizontal tab + lf = '\x0A', /// NL line feed, new line + vt = '\x0B', /// Vertical tab + ff = '\x0C', /// NP form feed, new page + cr = '\x0D', /// Carriage return + sO = '\x0E', /// Shift out + sI = '\x0F', /// Shift in + dle = '\x10', /// Data link escape + dc1 = '\x11', /// Device control 1 + dc2 = '\x12', /// Device control 2 + dc3 = '\x13', /// Device control 3 + dc4 = '\x14', /// Device control 4 + nak = '\x15', /// Negative acknowledge + syn = '\x16', /// Synchronous idle + etb = '\x17', /// End of transmission block + can = '\x18', /// Cancel + em = '\x19', /// End of medium + sub = '\x1A', /// Substitute + esc = '\x1B', /// Escape + fs = '\x1C', /// File separator + gs = '\x1D', /// Group separator + rs = '\x1E', /// Record separator + us = '\x1F', /// Unit separator + del = '\x7F' /// Delete } /// @safe pure nothrow @nogc unittest { // Because all ASCII characters fit in char, so do these - static assert(ControlChar.ACK.sizeof == 1); + static assert(ControlChar.ack.sizeof == 1); - static assert(ControlChar.NUL == '\0'); - static assert(ControlChar.BEL == '\a'); - static assert(ControlChar.BS == '\b'); - static assert(ControlChar.FF == '\f'); - static assert(ControlChar.LF == '\n'); - static assert(ControlChar.CR == '\r'); - static assert(ControlChar.TAB == '\t'); - static assert(ControlChar.VT == '\v'); + static assert(ControlChar.nul == '\0'); + static assert(ControlChar.bel == '\a'); + static assert(ControlChar.bs == '\b'); + static assert(ControlChar.ff == '\f'); + static assert(ControlChar.lf == '\n'); + static assert(ControlChar.cr == '\r'); + static assert(ControlChar.tab == '\t'); + static assert(ControlChar.vt == '\v'); } /// @@ -164,7 +164,7 @@ enum ControlChar : char { import std.conv; //Control character table can be used in place of hexcodes. - with (ControlChar) assert(text("Phobos", US, "Deimos", US, "Tango", RS) == "Phobos\x1FDeimos\x1FTango\x1E"); + with (ControlChar) assert(text("Phobos", us, "Deimos", us, "Tango", rs) == "Phobos\x1FDeimos\x1FTango\x1E"); } /// Newline sequence for this system. From bbd0b3ebf7b7775c59cba4cb47af82c594717b70 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Fri, 17 May 2019 14:08:36 +0800 Subject: [PATCH 33/77] Fix broken unittest --- std/experimental/allocator/mallocator.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/experimental/allocator/mallocator.d b/std/experimental/allocator/mallocator.d index 2b015ca811c..6d529cc60bb 100644 --- a/std/experimental/allocator/mallocator.d +++ b/std/experimental/allocator/mallocator.d @@ -82,7 +82,7 @@ struct Mallocator } /// -@nogc @system nothrow pure unittest +@nogc @system nothrow unittest { auto buffer = Mallocator.instance.allocate(1024 * 1024 * 4); scope(exit) Mallocator.instance.deallocate(buffer); From c36d609f0113a73f3ebce0b43c2d2dbfb6faa8bc Mon Sep 17 00:00:00 2001 From: dukc Date: Fri, 17 May 2019 14:30:57 +0300 Subject: [PATCH 34/77] Unittest loop over first 32 control chars to ensure they are lined up. --- std/ascii.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/std/ascii.d b/std/ascii.d index 07f4a6a00ca..847466e63f7 100644 --- a/std/ascii.d +++ b/std/ascii.d @@ -146,9 +146,14 @@ enum ControlChar : char /// @safe pure nothrow @nogc unittest { + import std.algorithm.comparison, std.algorithm.searching, std.range, std.traits; + // Because all ASCII characters fit in char, so do these static assert(ControlChar.ack.sizeof == 1); + // All control characters except del are in row starting from 0 + static assert(EnumMembers!ControlChar.only.until(ControlChar.del).equal(iota(32))); + static assert(ControlChar.nul == '\0'); static assert(ControlChar.bel == '\a'); static assert(ControlChar.bs == '\b'); From a724c9a042cd7a060b5f8811eb96f081bdce99b8 Mon Sep 17 00:00:00 2001 From: Ernesto Castellotti Date: Fri, 17 May 2019 18:14:15 +0200 Subject: [PATCH 35/77] Update SQLite3 to 3.28.0 --- etc/c/sqlite3.d | 918 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 819 insertions(+), 99 deletions(-) diff --git a/etc/c/sqlite3.d b/etc/c/sqlite3.d index 43a72f52887..4ac020f59db 100644 --- a/etc/c/sqlite3.d +++ b/etc/c/sqlite3.d @@ -1,6 +1,6 @@ module etc.c.sqlite3; /* -** 2001 September 15 +** 2001-09-15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -33,17 +33,18 @@ module etc.c.sqlite3; */ import core.stdc.stdarg : va_list; +import core.stdc.config : c_ulong; extern (C) __gshared nothrow: /** ** CAPI3REF: Compile-Time Library Version Numbers */ -enum SQLITE_VERSION = "3.10.2"; +enum SQLITE_VERSION = "3.28.0"; /// Ditto -enum SQLITE_VERSION_NUMBER = 3_010_002; +enum SQLITE_VERSION_NUMBER = 3028000; /// Ditto -enum SQLITE_SOURCE_ID = "2016-01-20 15:27:19 17efb4209f97fb4971656086b138599a91a75ff9"; +enum SQLITE_SOURCE_ID = "2019-04-16 19:49:53 884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f83156b50"; /** ** CAPI3REF: Run-Time Library Version Numbers @@ -111,7 +112,7 @@ enum SQLITE_OK = 0, /** Successful result */ /* beginning-of-error-codes */ /// Ditto - SQLITE_ERROR = 1, /** SQL error or missing database */ + SQLITE_ERROR = 1, /** Generic error */ SQLITE_INTERNAL = 2, /** Internal logic error in SQLite */ SQLITE_PERM = 3, /** Access permission denied */ SQLITE_ABORT = 4, /** Callback routine requested an abort */ @@ -126,7 +127,7 @@ enum SQLITE_FULL = 13, /** Insertion failed because database is full */ SQLITE_CANTOPEN = 14, /** Unable to open the database file */ SQLITE_PROTOCOL = 15, /** Database lock protocol error */ - SQLITE_EMPTY = 16, /** Database is empty */ + SQLITE_EMPTY = 16, /** Internal use only */ SQLITE_SCHEMA = 17, /** The database schema changed */ SQLITE_TOOBIG = 18, /** String or BLOB exceeds size limit */ SQLITE_CONSTRAINT = 19, /** Abort due to constraint violation */ @@ -134,7 +135,7 @@ enum SQLITE_MISUSE = 21, /** Library used incorrectly */ SQLITE_NOLFS = 22, /** Uses OS features not supported on host */ SQLITE_AUTH = 23, /** Authorization denied */ - SQLITE_FORMAT = 24, /** Auxiliary database format error */ + SQLITE_FORMAT = 24, /** Not used */ SQLITE_RANGE = 25, /** 2nd parameter to sqlite3_bind out of range */ SQLITE_NOTADB = 26, /** File opened that is not a database file */ SQLITE_NOTICE = 27, @@ -149,6 +150,9 @@ enum */ enum { + SQLITE_ERROR_MISSING_COLLSEQ = (SQLITE_ERROR | (1 << 8)), + SQLITE_ERROR_RETRY = (SQLITE_ERROR | (2 << 8)), + SQLITE_ERROR_SNAPSHOT = (SQLITE_ERROR | (3 << 8)), SQLITE_IOERR_READ = (SQLITE_IOERR | (1 << 8)), SQLITE_IOERR_SHORT_READ = (SQLITE_IOERR | (2 << 8)), SQLITE_IOERR_WRITE = (SQLITE_IOERR | (3 << 8)), @@ -173,20 +177,30 @@ enum SQLITE_IOERR_SEEK = (SQLITE_IOERR | (22 << 8)), SQLITE_IOERR_DELETE_NOENT = (SQLITE_IOERR | (23 << 8)), SQLITE_IOERR_MMAP = (SQLITE_IOERR | (24 << 8)), - SQLITE_LOCKED_SHAREDCACHE = (SQLITE_LOCKED | (1 << 8)), - SQLITE_BUSY_RECOVERY = (SQLITE_BUSY | (1 << 8)), - SQLITE_CANTOPEN_NOTEMPDIR = (SQLITE_CANTOPEN | (1 << 8)), SQLITE_IOERR_GETTEMPPATH = (SQLITE_IOERR | (25 << 8)), SQLITE_IOERR_CONVPATH = (SQLITE_IOERR | (26 << 8)), + SQLITE_IOERR_VNODE = (SQLITE_IOERR | (27 << 8)), + SQLITE_IOERR_AUTH = (SQLITE_IOERR | (28 << 8)), + SQLITE_IOERR_BEGIN_ATOMIC = (SQLITE_IOERR | (29 << 8)), + SQLITE_IOERR_COMMIT_ATOMIC = (SQLITE_IOERR | (30 << 8)), + SQLITE_IOERR_ROLLBACK_ATOMIC = (SQLITE_IOERR | (31 << 8)), + SQLITE_LOCKED_SHAREDCACHE = (SQLITE_LOCKED | (1 << 8)), + SQLITE_LOCKED_VTAB = (SQLITE_LOCKED | (2 << 8)), + SQLITE_BUSY_RECOVERY = (SQLITE_BUSY | (1 << 8)), SQLITE_BUSY_SNAPSHOT = (SQLITE_BUSY | (2 << 8)), + SQLITE_CANTOPEN_NOTEMPDIR = (SQLITE_CANTOPEN | (1 << 8)), SQLITE_CANTOPEN_ISDIR = (SQLITE_CANTOPEN | (2 << 8)), SQLITE_CANTOPEN_FULLPATH = (SQLITE_CANTOPEN | (3 << 8)), SQLITE_CANTOPEN_CONVPATH = (SQLITE_CANTOPEN | (4 << 8)), + SQLITE_CANTOPEN_DIRTYWAL = (SQLITE_CANTOPEN | (5 << 8)), /* Not Used */ SQLITE_CORRUPT_VTAB = (SQLITE_CORRUPT | (1 << 8)), + SQLITE_CORRUPT_SEQUENCE = (SQLITE_CORRUPT | (2 << 8)), SQLITE_READONLY_RECOVERY = (SQLITE_READONLY | (1 << 8)), SQLITE_READONLY_CANTLOCK = (SQLITE_READONLY | (2 << 8)), SQLITE_READONLY_ROLLBACK = (SQLITE_READONLY | (3 << 8)), SQLITE_READONLY_DBMOVED = (SQLITE_READONLY | (4 << 8)), + SQLITE_READONLY_CANTINIT = (SQLITE_READONLY | (5 << 8)), + SQLITE_READONLY_DIRECTORY = (SQLITE_READONLY | (6 << 8)), SQLITE_ABORT_ROLLBACK = (SQLITE_ABORT | (2 << 8)), SQLITE_CONSTRAINT_CHECK = (SQLITE_CONSTRAINT | (1 << 8)), SQLITE_CONSTRAINT_COMMITHOOK = (SQLITE_CONSTRAINT | (2 << 8)), @@ -201,7 +215,8 @@ enum SQLITE_NOTICE_RECOVER_WAL = (SQLITE_NOTICE | (1 << 8)), SQLITE_NOTICE_RECOVER_ROLLBACK = (SQLITE_NOTICE | (2 << 8)), SQLITE_WARNING_AUTOINDEX = (SQLITE_WARNING | (1 << 8)), - SQLITE_AUTH_USER = (SQLITE_AUTH | (1 << 8)) + SQLITE_AUTH_USER = (SQLITE_AUTH | (1 << 8)), + SQLITE_OK_LOAD_PERMANENTLY = (SQLITE_OK | (1 << 8)) } /** @@ -249,7 +264,8 @@ enum SQLITE_IOCAP_SEQUENTIAL = 0x00000400, SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN = 0x00000800, SQLITE_IOCAP_POWERSAFE_OVERWRITE = 0x00001000, - SQLITE_IOCAP_IMMUTABLE = 0x00002000 + SQLITE_IOCAP_IMMUTABLE = 0x00002000, + SQLITE_IOCAP_BATCH_ATOMIC = 0x00004000 } /** @@ -317,32 +333,48 @@ struct sqlite3_io_methods */ enum { - SQLITE_FCNTL_LOCKSTATE = 1, - SQLITE_GET_LOCKPROXYFILE = 2, - SQLITE_SET_LOCKPROXYFILE = 3, - SQLITE_LAST_ERRNO = 4, - SQLITE_FCNTL_SIZE_HINT = 5, - SQLITE_FCNTL_CHUNK_SIZE = 6, - SQLITE_FCNTL_FILE_POINTER = 7, - SQLITE_FCNTL_SYNC_OMITTED = 8, - SQLITE_FCNTL_WIN32_AV_RETRY = 9, - SQLITE_FCNTL_PERSIST_WAL = 10, - SQLITE_FCNTL_OVERWRITE = 11, - SQLITE_FCNTL_VFSNAME = 12, - SQLITE_FCNTL_POWERSAFE_OVERWRITE = 13, - SQLITE_FCNTL_PRAGMA = 14, - SQLITE_FCNTL_BUSYHANDLER = 15, - SQLITE_FCNTL_TEMPFILENAME = 16, - SQLITE_FCNTL_MMAP_SIZE = 18, - SQLITE_FCNTL_TRACE = 19, - SQLITE_FCNTL_HAS_MOVED = 20, - SQLITE_FCNTL_SYNC = 21, - SQLITE_FCNTL_COMMIT_PHASETWO = 22, - SQLITE_FCNTL_WIN32_SET_HANDLE = 23, - SQLITE_FCNTL_WAL_BLOCK = 24, - SQLITE_FCNTL_ZIPVFS = 25, - SQLITE_FCNTL_RBU = 26, - SQLITE_FCNTL_VFS_POINTER = 27, + SQLITE_FCNTL_LOCKSTATE = 1, + SQLITE_FCNTL_GET_LOCKPROXYFILE = 2, + SQLITE_FCNTL_SET_LOCKPROXYFILE = 3, + SQLITE_FCNTL_LAST_ERRNO = 4, + SQLITE_FCNTL_SIZE_HINT = 5, + SQLITE_FCNTL_CHUNK_SIZE = 6, + SQLITE_FCNTL_FILE_POINTER = 7, + SQLITE_FCNTL_SYNC_OMITTED = 8, + SQLITE_FCNTL_WIN32_AV_RETRY = 9, + SQLITE_FCNTL_PERSIST_WAL = 10, + SQLITE_FCNTL_OVERWRITE = 11, + SQLITE_FCNTL_VFSNAME = 12, + SQLITE_FCNTL_POWERSAFE_OVERWRITE = 13, + SQLITE_FCNTL_PRAGMA = 14, + SQLITE_FCNTL_BUSYHANDLER = 15, + SQLITE_FCNTL_TEMPFILENAME = 16, + SQLITE_FCNTL_MMAP_SIZE = 18, + SQLITE_FCNTL_TRACE = 19, + SQLITE_FCNTL_HAS_MOVED = 20, + SQLITE_FCNTL_SYNC = 21, + SQLITE_FCNTL_COMMIT_PHASETWO = 22, + SQLITE_FCNTL_WIN32_SET_HANDLE = 23, + SQLITE_FCNTL_WAL_BLOCK = 24, + SQLITE_FCNTL_ZIPVFS = 25, + SQLITE_FCNTL_RBU = 26, + SQLITE_FCNTL_VFS_POINTER = 27, + SQLITE_FCNTL_JOURNAL_POINTER = 28, + SQLITE_FCNTL_WIN32_GET_HANDLE = 29, + SQLITE_FCNTL_PDB = 30, + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE = 31, + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE = 32, + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE = 33, + SQLITE_FCNTL_LOCK_TIMEOUT = 34, + SQLITE_FCNTL_DATA_VERSION = 35, + SQLITE_FCNTL_SIZE_LIMIT = 36 +} + +deprecated ("deprecated names") +{ + alias SQLITE_GET_LOCKPROXYFILE = SQLITE_FCNTL_GET_LOCKPROXYFILE; + alias SQLITE_SET_LOCKPROXYFILE = SQLITE_FCNTL_SET_LOCKPROXYFILE; + alias SQLITE_LAST_ERRNO = SQLITE_FCNTL_LAST_ERRNO; } /** @@ -350,6 +382,11 @@ enum */ struct sqlite3_mutex; +/** +** CAPI3REF: Loadable Extension Thunk +*/ +struct sqlite3_api_routines; + /** ** CAPI3REF: OS Interface Object */ @@ -472,26 +509,30 @@ enum SQLITE_CONFIG_SERIALIZED = 3, /** nil */ SQLITE_CONFIG_MALLOC = 4, /** sqlite3_mem_methods* */ SQLITE_CONFIG_GETMALLOC = 5, /** sqlite3_mem_methods* */ - SQLITE_CONFIG_SCRATCH = 6, /** void*, int sz, int N */ + SQLITE_CONFIG_SCRATCH = 6, /** No longer used */ SQLITE_CONFIG_PAGECACHE = 7, /** void*, int sz, int N */ SQLITE_CONFIG_HEAP = 8, /** void*, int nByte, int min */ SQLITE_CONFIG_MEMSTATUS = 9, /** boolean */ SQLITE_CONFIG_MUTEX = 10, /** sqlite3_mutex_methods* */ SQLITE_CONFIG_GETMUTEX = 11, /** sqlite3_mutex_methods* */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ - SQLITE_CONFIG_LOOKASIDE = 13, /** int int */ - SQLITE_CONFIG_PCACHE = 14, /** sqlite3_pcache_methods* */ - SQLITE_CONFIG_GETPCACHE = 15, /** sqlite3_pcache_methods* */ + SQLITE_CONFIG_LOOKASIDE = 13, /** int int */ + SQLITE_CONFIG_PCACHE = 14, /** no-op */ + SQLITE_CONFIG_GETPCACHE = 15, /** no-op */ SQLITE_CONFIG_LOG = 16, /** xFunc, void* */ - SQLITE_CONFIG_URI = 17, - SQLITE_CONFIG_PCACHE2 = 18, - SQLITE_CONFIG_GETPCACHE2 = 19, - SQLITE_CONFIG_COVERING_INDEX_SCAN = 20, - SQLITE_CONFIG_SQLLOG = 21, - SQLITE_CONFIG_MMAP_SIZE = 22, - SQLITE_CONFIG_WIN32_HEAPSIZE = 23, - SQLITE_CONFIG_PCACHE_HDRSZ = 24, - SQLITE_CONFIG_PMASZ = 25, + SQLITE_CONFIG_URI = 17, /** int */ + SQLITE_CONFIG_PCACHE2 = 18, /** sqlite3_pcache_methods2* */ + SQLITE_CONFIG_GETPCACHE2 = 19, /** sqlite3_pcache_methods2* */ + SQLITE_CONFIG_COVERING_INDEX_SCAN = 20, /** int */ + SQLITE_CONFIG_SQLLOG = 21, /** xSqllog, void* */ + SQLITE_CONFIG_MMAP_SIZE = 22, /** sqlite3_int64, sqlite3_int64 */ + SQLITE_CONFIG_WIN32_HEAPSIZE = 23, /** int nByte */ + SQLITE_CONFIG_PCACHE_HDRSZ = 24, /** int *psz */ + SQLITE_CONFIG_PMASZ = 25, /** unsigned int szPma */ + SQLITE_CONFIG_STMTJRNL_SPILL = 26, /** int nByte */ + SQLITE_CONFIG_SMALL_MALLOC = 27, /** boolean */ + SQLITE_CONFIG_SORTERREF_SIZE = 28, /** int nByte */ + SQLITE_CONFIG_MEMDB_MAXSIZE = 29 /** sqlite3_int64 */ } /** @@ -499,9 +540,19 @@ enum */ enum { - SQLITE_DBCONFIG_LOOKASIDE = 1001, /** void* int int */ - SQLITE_DBCONFIG_ENABLE_FKEY = 1002, /** int int* */ - SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003 /** int int* */ + SQLITE_DBCONFIG_MAINDBNAME = 1000, /** const char* */ + SQLITE_DBCONFIG_LOOKASIDE = 1001, /** void* int int */ + SQLITE_DBCONFIG_ENABLE_FKEY = 1002, /** int int* */ + SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003, /** int int* */ + SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = 1004, /** int int* */ + SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005, /** int int* */ + SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE = 1006, /** int int* */ + SQLITE_DBCONFIG_ENABLE_QPSG = 1007, /** int int* */ + SQLITE_DBCONFIG_TRIGGER_EQP = 1008, /** int int* */ + SQLITE_DBCONFIG_RESET_DATABASE = 1009, /** int int* */ + SQLITE_DBCONFIG_DEFENSIVE = 1010, /** int int* */ + SQLITE_DBCONFIG_WRITABLE_SCHEMA = 1011, /** int int* */ + SQLITE_DBCONFIG_MAX = 1011 /** Largest DBCONFIG */ } @@ -515,6 +566,11 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff); */ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); +/** +** CAPI3REF: Set the Last Insert Rowid value +*/ +void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); + /** ** CAPI3REF: Count The Number Of Rows Modified */ @@ -652,15 +708,36 @@ enum SQLITE_FUNCTION = 31, /** NULL Function Name */ SQLITE_SAVEPOINT = 32, /** Operation Savepoint Name */ SQLITE_COPY = 0, /** No longer used */ - SQLITE_RECURSIVE = 33 + SQLITE_RECURSIVE = 33 /** NULL NULL */ } /** ** CAPI3REF: Tracing And Profiling Functions */ -void *sqlite3_trace(sqlite3*, void function (void*,const char*) xTrace, void*); +deprecated void *sqlite3_trace(sqlite3*, void function (void*,const char*) xTrace, void*); /// Ditto -void *sqlite3_profile(sqlite3*, void function (void*,const char*,sqlite3_uint64) xProfile, void*); +deprecated void *sqlite3_profile(sqlite3*, void function (void*,const char*,sqlite3_uint64) xProfile, void*); + +/** +** CAPI3REF: SQL Trace Event Codes +*/ +enum +{ + SQLITE_TRACE_STMT = 0x01, + SQLITE_TRACE_PROFILE = 0x02, + SQLITE_TRACE_ROW = 0x04, + SQLITE_TRACE_CLOSE = 0x08 +} + +/** +** CAPI3REF: SQL Trace Hook +*/ +int sqlite3_trace_v2( + sqlite3*, + uint uMask, + int function (uint, void*, void*, void*) xCallback, + void* pCtx +); /** ** CAPI3REF: Query Progress Callbacks @@ -735,7 +812,17 @@ enum SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8, SQLITE_LIMIT_VARIABLE_NUMBER = 9, SQLITE_LIMIT_TRIGGER_DEPTH = 10, - SQLITE_LIMIT_WORKER_THREADS = 11, + SQLITE_LIMIT_WORKER_THREADS = 11 +} + +/** +** CAPI3REF: Prepare Flags +*/ +enum +{ + SQLITE_PREPARE_PERSISTENT = 0x01, + SQLITE_PREPARE_NORMALIZE = 0x02, + SQLITE_PREPARE_NO_VTAB = 0x04 } /** @@ -757,6 +844,15 @@ int sqlite3_prepare_v2( const(char*)*pzTail /** OUT: Pointer to unused portion of zSql */ ); /// Ditto +int sqlite3_prepare_v3( + sqlite3 *db, /** Database handle */ + const(char)* zSql, /** SQL statement, UTF-8 encoded */ + int nByte, /** Maximum length of zSql in bytes. */ + uint prepFlags, /** Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const(char*)*pzTail /* OUT: Pointer to unused portion of zSql */ +); +/// Ditto int sqlite3_prepare16( sqlite3 *db, /** Database handle */ const(void)*zSql, /** SQL statement, UTF-16 encoded */ @@ -772,17 +868,34 @@ int sqlite3_prepare16_v2( sqlite3_stmt **ppStmt, /** OUT: Statement handle */ const(void*)*pzTail /** OUT: Pointer to unused portion of zSql */ ); +/// Ditto +int sqlite3_prepare16_v3( + sqlite3 *db, /** Database handle */ + const(void)*zSql, /** SQL statement, UTF-16 encoded */ + int nByte, /** Maximum length of zSql in bytes. */ + uint prepFlags, /** Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /** OUT: Statement handle */ + const(void*)*pzTail /** OUT: Pointer to unused portion of zSql */ +); /** ** CAPI3REF: Retrieving Statement SQL */ const(char)* sqlite3_sql(sqlite3_stmt *pStmt); +/// Ditto +char* sqlite3_expanded_sql(sqlite3_stmt *pStmt); +const(char)* sqlite3_normalized_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database */ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +/* +** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement +*/ +int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); + /** ** CAPI3REF: Determine If A Prepared Statement Has Been Reset */ @@ -907,10 +1020,6 @@ enum */ const (void)* sqlite3_column_blob(sqlite3_stmt*, int iCol); /// Ditto -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -/// Ditto -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -/// Ditto double sqlite3_column_double(sqlite3_stmt*, int iCol); /// Ditto int sqlite3_column_int(sqlite3_stmt*, int iCol); @@ -921,9 +1030,13 @@ const (char)* sqlite3_column_text(sqlite3_stmt*, int iCol); /// Ditto const (void)* sqlite3_column_text16(sqlite3_stmt*, int iCol); /// Ditto -int sqlite3_column_type(sqlite3_stmt*, int iCol); -/// Ditto sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); +/// Ditto +int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +/// Ditto +int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +/// Ditto +int sqlite3_column_type(sqlite3_stmt*, int iCol); /** ** CAPI3REF: Destroy A Prepared Statement Object @@ -971,6 +1084,19 @@ int sqlite3_create_function_v2( void function (sqlite3_context*) xFinal, void function (void*) xDestroy ); +/// Ditto +int sqlite3_create_window_function( + sqlite3 *db, + const(char)*zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void function (sqlite3_context*,int,sqlite3_value**) xStep, + void function (sqlite3_context*) xFinal, + void function (sqlite3_context*) xValue, + void function (sqlite3_context*,int,sqlite3_value**) xInverse, + void function (void*) xDestroy +); /** ** CAPI3REF: Text Encodings @@ -980,13 +1106,9 @@ int sqlite3_create_function_v2( */ enum { - SQLITE_UTF8 = 1, - SQLITE_UTF16LE = 2, - SQLITE_UTF16BE = 3 -} -/// Ditto -enum -{ + SQLITE_UTF8 = 1, /** IMP: R-37514-35566 */ + SQLITE_UTF16LE = 2, /** IMP: R-03371-37637 */ + SQLITE_UTF16BE = 3, /** IMP: R-51971-34154 */ SQLITE_UTF16 = 4, /** Use native byte order */ SQLITE_ANY = 5, /** sqlite3_create_function only */ SQLITE_UTF16_ALIGNED = 8 /** sqlite3_create_collation only */ @@ -1033,6 +1155,10 @@ const (void)* sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); /// Ditto int sqlite3_value_numeric_type(sqlite3_value*); +/// Ditto +int sqlite3_value_nochange(sqlite3_value*); +/// Ditto +int sqlite3_value_frombind(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -1229,6 +1355,33 @@ extern char *sqlite3_temp_directory; */ extern char *sqlite3_data_directory; +/** +** CAPI3REF: Win32 Specific Interface +*/ +int sqlite3_win32_set_directory( + c_ulong type, /** Identifier for directory being set or reset */ + void* zValue /** New value for directory being set or reset */ +); +/// Ditto +int sqlite3_win32_set_directory8( + c_ulong type, /** Identifier for directory being set or reset */ + void* zValue /** New value for directory being set or reset */ +); +/// Ditto +int sqlite3_win32_set_directory16( + c_ulong type, /** Identifier for directory being set or reset */ + void* zValue /** New value for directory being set or reset */ +); + +/** +** CAPI3REF: Win32 Directory Types +*/ +enum +{ + SQLITE_WIN32_DATA_DIRECTORY_TYPE = 1, + SQLITE_WIN32_TEMP_DIRECTORY_TYPE = 2 +} + /** ** CAPI3REF: Test For Auto-Commit Mode */ @@ -1388,6 +1541,7 @@ struct sqlite3_module int function (sqlite3_vtab *pVTab, int) xSavepoint; int function (sqlite3_vtab *pVTab, int) xRelease; int function (sqlite3_vtab *pVTab, int) xRollbackTo; + int function (const char*) xShadowName; } /** @@ -1397,7 +1551,7 @@ struct sqlite3_index_info { struct sqlite3_index_constraint { - int iColumn; /** Column on left-hand side of constraint */ + int iColumn; /** constrained. -1 for ROWID */ char op; /** Constraint operator */ char usable; /** True if this constraint is usable */ int iTermOffset; /** Used internally - xBestIndex should ignore */ @@ -1429,21 +1583,34 @@ struct sqlite3_index_info sqlite3_uint64 colUsed; } +/** +** CAPI3REF: Virtual Table Scan Flags +*/ +enum +{ + SQLITE_INDEX_SCAN_UNIQUE = 1 +} + /** ** CAPI3REF: Virtual Table Constraint Operator Codes */ enum { - SQLITE_INDEX_SCAN_UNIQUE = 1, - SQLITE_INDEX_CONSTRAINT_EQ = 2, - SQLITE_INDEX_CONSTRAINT_GT = 4, - SQLITE_INDEX_CONSTRAINT_LE = 8, - SQLITE_INDEX_CONSTRAINT_LT = 16, - SQLITE_INDEX_CONSTRAINT_GE = 32, - SQLITE_INDEX_CONSTRAINT_MATCH = 64, - SQLITE_INDEX_CONSTRAINT_LIKE = 65, - SQLITE_INDEX_CONSTRAINT_GLOB = 66, - SQLITE_INDEX_CONSTRAINT_REGEXP = 67, + SQLITE_INDEX_CONSTRAINT_EQ = 2, + SQLITE_INDEX_CONSTRAINT_GT = 4, + SQLITE_INDEX_CONSTRAINT_LE = 8, + SQLITE_INDEX_CONSTRAINT_LT = 16, + SQLITE_INDEX_CONSTRAINT_GE = 32, + SQLITE_INDEX_CONSTRAINT_MATCH = 64, + SQLITE_INDEX_CONSTRAINT_LIKE = 65, + SQLITE_INDEX_CONSTRAINT_GLOB = 66, + SQLITE_INDEX_CONSTRAINT_REGEXP = 67, + SQLITE_INDEX_CONSTRAINT_NE = 68, + SQLITE_INDEX_CONSTRAINT_ISNOT = 69, + SQLITE_INDEX_CONSTRAINT_ISNOTNULL = 70, + SQLITE_INDEX_CONSTRAINT_ISNULL = 71, + SQLITE_INDEX_CONSTRAINT_IS = 72, + SQLITE_INDEX_CONSTRAINT_FUNCTION = 150 } /** @@ -1606,7 +1773,7 @@ enum SQLITE_MUTEX_STATIC_MEM = 3, /** sqlite3_malloc() */ SQLITE_MUTEX_STATIC_MEM2 = 4, /** NOT USED */ SQLITE_MUTEX_STATIC_OPEN = 4, /** sqlite3BtreeOpen() */ - SQLITE_MUTEX_STATIC_PRNG = 5, /** sqlite3_random() */ + SQLITE_MUTEX_STATIC_PRNG = 5, /** sqlite3_randomness() */ SQLITE_MUTEX_STATIC_LRU = 6, /** lru page list */ SQLITE_MUTEX_STATIC_LRU2 = 7, /** NOT USED */ SQLITE_MUTEX_STATIC_PMEM = 7, /** sqlite3PageMalloc() */ @@ -1650,19 +1817,68 @@ enum SQLITE_TESTCTRL_ALWAYS = 13, SQLITE_TESTCTRL_RESERVE = 14, SQLITE_TESTCTRL_OPTIMIZATIONS = 15, - SQLITE_TESTCTRL_ISKEYWORD = 16, - SQLITE_TESTCTRL_SCRATCHMALLOC = 17, + SQLITE_TESTCTRL_ISKEYWORD = 16, /** NOT USED */ + SQLITE_TESTCTRL_SCRATCHMALLOC = 17, /** NOT USED */ + SQLITE_TESTCTRL_INTERNAL_FUNCTIONS = 17, SQLITE_TESTCTRL_LOCALTIME_FAULT = 18, - SQLITE_TESTCTRL_EXPLAIN_STMT = 19, + SQLITE_TESTCTRL_EXPLAIN_STMT = 19, /** NOT USED */ + SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD = 19, SQLITE_TESTCTRL_NEVER_CORRUPT = 20, SQLITE_TESTCTRL_VDBE_COVERAGE = 21, SQLITE_TESTCTRL_BYTEORDER = 22, SQLITE_TESTCTRL_ISINIT = 23, SQLITE_TESTCTRL_SORTER_MMAP = 24, SQLITE_TESTCTRL_IMPOSTER = 25, - SQLITE_TESTCTRL_LAST = 25, + SQLITE_TESTCTRL_PARSER_COVERAGE = 26, + SQLITE_TESTCTRL_LAST = 26, /** NOT USED */ } +/** +** CAPI3REF: SQL Keyword Checking +*/ +int sqlite3_keyword_count(); +/// Ditto +int sqlite3_keyword_name(int, const(char*)*, int*); +/// Ditto +int sqlite3_keyword_check(const(char)*, int); + +/** +** CAPI3REF: Dynamic String Object +*/ +struct sqlite3_str; + +/** +** CAPI3REF: Create A New Dynamic String Object +*/ +sqlite3_str* sqlite3_str_new(sqlite3*); + +/** +** CAPI3REF: Finalize A Dynamic String +*/ +char* sqlite3_str_finish(sqlite3_str*); + +/** +** CAPI3REF: Add Content To A Dynamic String +*/ +void sqlite3_str_appendf(sqlite3_str*, const(char)* zFormat, ...); +/// Ditto +void sqlite3_str_vappendf(sqlite3_str*, const(char)* zFormat, va_list); +/// Ditto +void sqlite3_str_append(sqlite3_str*, const(char)* zIn, int N); +/// Ditto +void sqlite3_str_appendall(sqlite3_str*, const(char)* zIn); +/// Ditto +void sqlite3_str_appendchar(sqlite3_str*, int N, char C); +/// Ditto +void sqlite3_str_reset(sqlite3_str*); + +/** +** CAPI3REF: Status Of A Dynamic String +*/ +int sqlite3_str_errcode(sqlite3_str*); +int sqlite3_str_length(sqlite3_str*); +char* sqlite3_str_value(sqlite3_str*); + /** ** CAPI3REF: SQLite Runtime Status */ @@ -1678,12 +1894,12 @@ enum SQLITE_STATUS_MEMORY_USED = 0, SQLITE_STATUS_PAGECACHE_USED = 1, SQLITE_STATUS_PAGECACHE_OVERFLOW = 2, - SQLITE_STATUS_SCRATCH_USED = 3, - SQLITE_STATUS_SCRATCH_OVERFLOW = 4, + SQLITE_STATUS_SCRATCH_USED = 3, /** NOT USED */ + SQLITE_STATUS_SCRATCH_OVERFLOW = 4, /** NOT USED */ SQLITE_STATUS_MALLOC_SIZE = 5, SQLITE_STATUS_PARSER_STACK = 6, SQLITE_STATUS_PAGECACHE_SIZE = 7, - SQLITE_STATUS_SCRATCH_SIZE = 8, + SQLITE_STATUS_SCRATCH_SIZE = 8, /** NOT USED */ SQLITE_STATUS_MALLOC_COUNT = 9 } @@ -1708,7 +1924,9 @@ enum SQLITE_DBSTATUS_CACHE_MISS = 8, SQLITE_DBSTATUS_CACHE_WRITE = 9, SQLITE_DBSTATUS_DEFERRED_FKS = 10, - SQLITE_DBSTATUS_MAX = 10 /** Largest defined DBSTATUS */ + SQLITE_DBSTATUS_CACHE_USED_SHARED = 11, + SQLITE_DBSTATUS_CACHE_SPILL = 12, + SQLITE_DBSTATUS_MAX = 12 /** Largest defined DBSTATUS */ } /** @@ -1724,7 +1942,10 @@ enum SQLITE_STMTSTATUS_FULLSCAN_STEP = 1, SQLITE_STMTSTATUS_SORT = 2, SQLITE_STMTSTATUS_AUTOINDEX = 3, - SQLITE_STMTSTATUS_VM_STEP = 4 + SQLITE_STMTSTATUS_VM_STEP = 4, + SQLITE_STMTSTATUS_REPREPARE = 5, + SQLITE_STMTSTATUS_RUN = 6, + SQLITE_STMTSTATUS_MEMUSED = 99 } /** @@ -1904,6 +2125,16 @@ enum SQLITE_VTAB_CONSTRAINT_SUPPORT = 1; */ int sqlite3_vtab_on_conflict(sqlite3 *); +/* +** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE +*/ +int sqlite3_vtab_nochange(sqlite3_context*); + +/* +** CAPI3REF: Determine The Collation For a Virtual Table Constraint +*/ +const(char)* sqlite3_vtab_collation (sqlite3_index_info*, int); + /* ** CAPI3REF: Conflict resolution modes */ @@ -1942,7 +2173,38 @@ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *); */ int sqlite3_db_cacheflush(sqlite3 *); -struct sqlite3_snapshot; +/* +** CAPI3REF: The pre-update hook +*/ +void* sqlite3_preupdate_hook( + sqlite3* db, + void function( + void* pCtx, + sqlite3* db, /** Database handle */ + int op, /** SQLITE_UPDATE, DELETE or INSERT */ + const(char)* zDb, /** Database name */ + const(char)* zName, /** Table name */ + sqlite3_int64 iKey1, /** Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 + ) xPreUpdate, + void* +); +/// Ditto +int sqlite3_preupdate_old(sqlite3*, int, sqlite3_value**); +/// Ditto +int sqlite3_preupdate_count(sqlite3*); +/// Ditto +int sqlite3_preupdate_depth(sqlite3*); +/// Ditto +int sqlite3_preupdate_new(sqlite3*, int, sqlite3_value**); + +/* +** CAPI3REF: Database Snapshot +*/ +struct sqlite3_snapshot +{ + ubyte[48] hidden; +} /* ** CAPI3REF: Record A Database Snapshot @@ -1959,6 +2221,56 @@ int sqlite3_snapshot_open(sqlite3 *db, char *zSchema, sqlite3_snapshot *pSnapsho */ void sqlite3_snapshot_free(sqlite3_snapshot *); +/* +** CAPI3REF: Compare the ages of two snapshot handles +*/ +int sqlite3_snapshot_cmp(sqlite3_snapshot* p1, sqlite3_snapshot* p2); + +/* +** CAPI3REF: Recover snapshots from a wal file +*/ +int sqlite3_snapshot_recover (sqlite3* db, const(char)* zDb); + +/* +** CAPI3REF: Serialize a database +*/ +ubyte* sqlite3_serialize( + sqlite3* db, + const(char)* zSchema, + sqlite3_int64* piSize, + uint mFlags +); + +/* +** CAPI3REF: Serialize a database +*/ +enum +{ + SQLITE_SERIALIZE_NOCOPY = 0x001 +} + +/* +** CAPI3REF: Deserialize a database +*/ +int sqlite3_deserialize ( + sqlite3* db, + const(char)* zSchema, + ubyte* pData, + sqlite3_int64 szDb, + sqlite3_int64 szBuf, + uint mFlags +); + +/* +** CAPI3REF: Flags for sqlite3_deserialize() +*/ +enum +{ + SQLITE_DESERIALIZE_FREEONCLOSE = 1, + SQLITE_DESERIALIZE_RESIZEABLE = 2, + SQLITE_DESERIALIZE_READONLY = 4 +} + /** ** Register a geometry callback named zGeom that can be used as part of an ** R-Tree geometry query as follows: @@ -2008,16 +2320,422 @@ struct sqlite3_rtree_query_info sqlite3_int64 iRowid; /* Rowid for current entry */ double rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visiblity */ + int eWithin; /* OUT: Visibility */ double rScore; /* OUT: Write the score here */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */ } enum { - NOT_WITHIN = 0, - PARTLY_WITHIN = 1, - FULLY_WITHIN = 2 + NOT_WITHIN = 0, /** Object completely outside of query region */ + PARTLY_WITHIN = 1, /** Object partially overlaps query region */ + FULLY_WITHIN = 2 /** Object fully contained within query region */ +} + +/* +** CAPI3REF: Session Object Handle +*/ +struct sqlite3_session; + +/* +** CAPI3REF: Session Object Handle +*/ +struct sqlite3_changeset_iter; + +/* +** CAPI3REF: Create A New Session Object +*/ +int sqlite3session_create ( + sqlite3* db, + const(char)* zDb, + sqlite3_session** ppSession +); + +/* +** CAPI3REF: Delete A Session Object +*/ +void sqlite3session_delete(sqlite3_session* pSession); + +/* +** CAPI3REF: Enable Or Disable A Session Object +*/ +int sqlite3session_enable(sqlite3_session* pSession, int bEnable); + +/* +** CAPI3REF: Set Or Clear the Indirect Change Flag +*/ +int sqlite3session_indirect(sqlite3_session* pSession, int bIndirect); + +/* +** CAPI3REF: Attach A Table To A Session Object +*/ +int sqlite3session_attach(sqlite3_session* pSession, const(char)* zTab); + +/* +** CAPI3REF: Set a table filter on a Session Object +*/ +void sqlite3session_table_filter( + sqlite3_session* pSession, + int function (void* pCtx, const(char)* zTab) xFilter, + void* pCtx +); + +/* +** CAPI3REF: Generate A Changeset From A Session Object +*/ +int sqlite3session_changeset( + sqlite3_session* pSession, + int* pnChangeset, + void** ppChangeset +); + +/* +** CAPI3REF: Load The Difference Between Tables Into A Session +*/ +int sqlite3session_diff( + sqlite3_session* pSession, + const(char)* zFromDb, + const(char)* zTbl, + char** pzErrMsg +); + +/* +** CAPI3REF: Generate A Patchset From A Session Object +*/ +int sqlite3session_patchset( + sqlite3_session* pSession, + int* pnPatchset, + void** ppPatchset +); + +/* +** CAPI3REF: Test if a changeset has recorded any changes +*/ +int sqlite3session_isempty (sqlite3_session* pSession); + +/* +** CAPI3REF: Create An Iterator To Traverse A Changeset +*/ +int sqlite3changeset_start( + sqlite3_changeset_iter** pp, + int nChangeset, + void* pChangeset +); +/// Ditto +int sqlite3changeset_start_v2( + sqlite3_changeset_iter** pp, + int nChangeset, + void* pChangeset, + int flags +); + +/* +** CAPI3REF: Flags for sqlite3changeset_start_v2 +*/ +enum +{ + SQLITE_CHANGESETSTART_INVERT = 0x0002 +} + +/* +** CAPI3REF: Advance A Changeset Iterator +*/ +int sqlite3changeset_next(sqlite3_changeset_iter* pIter); + +/* +** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +*/ +int sqlite3changeset_op( + sqlite3_changeset_iter* pIter, + const(char*)* pzTab, + int* pnCol, + int* pOp, + int* pbIndirect +); + +/* +** CAPI3REF: Obtain The Primary Key Definition Of A Table +*/ +int sqlite3changeset_pk( + sqlite3_changeset_iter* pIter, + ubyte** pabPK, + int* pnCol +); + +/* +** CAPI3REF: Obtain old.* Values From A Changeset Iterator +*/ +int sqlite3changeset_old( + sqlite3_changeset_iter* pIter, + int iVal, + sqlite3_value** ppValue +); + +/* +** CAPI3REF: Obtain new.* Values From A Changeset Iterator +*/ +int sqlite3changeset_new( + sqlite3_changeset_iter* pIter, + int iVal, + sqlite3_value** ppValue +); + +/* +** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +*/ +int sqlite3changeset_conflict( + sqlite3_changeset_iter* pIter, + int iVal, + sqlite3_value** ppValue +); + +/* +** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +*/ +int sqlite3changeset_fk_conflicts(sqlite3_changeset_iter* pIter, int* pnOut); + +/* +** CAPI3REF: Finalize A Changeset Iterator +*/ +int sqlite3changeset_finalize (sqlite3_changeset_iter* pIter); + +/* +** CAPI3REF: Invert A Changeset +*/ +int sqlite3changeset_invert( + int nIn, + const(void)* pIn, + int* pnOut, + void** ppOut +); + +/* +** CAPI3REF: Concatenate Two Changeset Objects +*/ +int sqlite3changeset_concat( + int nA, + void* pA, + int nB, + void* pB, + int* pnOut, + void** ppOut +); + +/* +** CAPI3REF: Changegroup Handle +*/ +struct sqlite3_changegroup; + +/* +** CAPI3REF: Create A New Changegroup Object +*/ +int sqlite3changegroup_new(sqlite3_changegroup** pp); + +/* +** CAPI3REF: Add A Changeset To A Changegroup +*/ +int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void* pData); + +/* +** CAPI3REF: Obtain A Composite Changeset From A Changegroup +*/ +int sqlite3changegroup_output( + sqlite3_changegroup*, + int* pnData, + void** ppData +); + +/* +** CAPI3REF: Delete A Changegroup Object +*/ +void sqlite3changegroup_delete (sqlite3_changegroup*); + +/* +** CAPI3REF: Apply A Changeset To A Database +*/ +int sqlite3changeset_apply( + sqlite3* db, + int nChangeset, + void* pChangeset, + int function(void* pCtx, const(char)* zTab) xFilter, + int function(void* pCtx, int eConflict, sqlite3_changeset_iter* p) xConflict, + void* pCtx +); +/// Ditto +int sqlite3changeset_apply_v2( + sqlite3* db, + int nChangeset, + void* pChangeset, + int function(void* pCtx, const(char)* zTab) xFilter, + int function(void* pCtx, int eConflict, sqlite3_changeset_iter* p) xConflict, + void* pCtx, + void** ppRebase, + int* pnRebase, + int flags +); + +/* +** CAPI3REF: Flags for sqlite3changeset_apply_v2 +*/ +enum +{ + SQLITE_CHANGESETAPPLY_NOSAVEPOINT = 0x0001, + SQLITE_CHANGESETAPPLY_INVERT = 0x0002 +} + +/* +** CAPI3REF: Constants Passed To The Conflict Handler +*/ +enum +{ + SQLITE_CHANGESET_DATA = 1, + SQLITE_CHANGESET_NOTFOUND = 2, + SQLITE_CHANGESET_CONFLICT = 3, + SQLITE_CHANGESET_CONSTRAINT = 4, + SQLITE_CHANGESET_FOREIGN_KEY = 5 +} + +/* +** CAPI3REF: Constants Returned By The Conflict Handler +*/ +enum +{ + SQLITE_CHANGESET_OMIT = 0, + SQLITE_CHANGESET_REPLACE = 1, + SQLITE_CHANGESET_ABORT = 2 +} + +/* +** CAPI3REF: Rebasing changesets +*/ +struct sqlite3_rebaser; + +/* +** CAPI3REF: Create a changeset rebaser object +*/ +int sqlite3rebaser_create(sqlite3_rebaser** ppNew); + +/* +** CAPI3REF: Configure a changeset rebaser object +*/ +int sqlite3rebaser_configure( + sqlite3_rebaser*, + int nRebase, + const(void)* pRebase +); + +/* +** CAPI3REF: Rebase a changeset +*/ +int sqlite3rebaser_rebase( + sqlite3_rebaser*, + int nIn, + const(void)* pIn, + int* pnOut, + void** ppOut +); + +/* +** CAPI3REF: Delete a changeset rebaser object +*/ +void sqlite3rebaser_delete(sqlite3_rebaser* p); + +/* +** CAPI3REF: Streaming Versions of API functions +*/ +int sqlite3changeset_apply_strm( + sqlite3* db, + int function (void* pIn, void* pData, int* pnData) xInput, + void* pIn, + int function (void* pCtx, const(char)* zTab) xFilter, + int function (void* pCtx, int eConflict, sqlite3_changeset_iter* p) xConflict, + void* pCtx +); +/// Ditto +int sqlite3changeset_apply_v2_strm( + sqlite3* db, + int function (void* pIn, void* pData, int* pnData) xInput, + void* pIn, + int function (void* pCtx, const(char)* zTab) xFilter, + int function (void* pCtx, int eConflict, sqlite3_changeset_iter* p) xConflict, + void* pCtx, + void** ppRebase, + int* pnRebase, + int flags +); +/// Ditto +int sqlite3changeset_concat_strm( + int function (void* pIn, void* pData, int* pnData) xInputA, + void* pInA, + int function (void* pIn, void* pData, int* pnData) xInputB, + void* pInB, + int function (void* pOut, const(void)* pData, int nData) xOutput, + void* pOut +); +/// Ditto +int sqlite3changeset_invert_strm( + int function (void* pIn, void* pData, int* pnData) xInput, + void* pIn, + int function (void* pOut, const(void)* pData, int nData) xOutput, + void* pOut +); +/// Ditto +int sqlite3changeset_start_strm( + sqlite3_changeset_iter** pp, + int function (void* pIn, void* pData, int* pnData) xInput, + void* pIn +); +/// Ditto +int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter** pp, + int function (void* pIn, void* pData, int* pnData) xInput, + void* pIn, + int flags +); +/// Ditto +int sqlite3session_changeset_strm( + sqlite3_session* pSession, + int function (void* pOut, const(void)* pData, int nData) xOutput, + void* pOut +); +/// Ditto +int sqlite3session_patchset_strm( + sqlite3_session* pSession, + int function (void* pOut, const(void)* pData, int nData) xOutput, + void* pOut +); +/// Ditto +int sqlite3changegroup_add_strm( + sqlite3_changegroup*, + int function (void* pIn, void* pData, int* pnData) xInput, + void* pIn +); +/// Ditto +int sqlite3changegroup_output_strm( + sqlite3_changegroup*, + int function (void* pOut, const(void)* pData, int nData) xOutput, + void* pOut +); +/// Ditto +int sqlite3rebaser_rebase_strm( + sqlite3_rebaser* pRebaser, + int function (void* pIn, void* pData, int* pnData) xInput, + void* pIn, + int function (void* pOut, const(void)* pData, int nData) xOutput, + void* pOut +); + +/* +** CAPI3REF: Configure global parameters +*/ +int sqlite3session_config(int op, void* pArg); + +/* +** CAPI3REF: Values for sqlite3session_config() +*/ +enum +{ + SQLITE_SESSION_CONFIG_STRMSIZE = 1 } /****************************************************************************** @@ -2041,7 +2759,7 @@ struct Fts5PhraseIter /// Ditto struct Fts5ExtensionApi { - int iVersion; + int iVersion; /** Currently always set to 3 */ void* function(Fts5Context*) xUserData; int function(Fts5Context*) xColumnCount; int function(Fts5Context*, sqlite3_int64 *pnRow) xRowCount; @@ -2063,8 +2781,10 @@ struct Fts5ExtensionApi ) xQueryPhrase; int function(Fts5Context*, void *pAux, void function(void*) xDelete) xSetAuxdata; void* function(Fts5Context*, int bClear) xGetAuxdata; - void function(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*) xPhraseFirst; + int function(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*) xPhraseFirst; void function(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff) xPhraseNext; + int function(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*) xPhraseFirstColumn; + void function(Fts5Context*, Fts5PhraseIter*, int* piCol) xPhraseNextColumn; } /// Ditto struct Fts5Tokenizer; From e4a38e8ea569f93ef782c4006860259cf2e54aa5 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Fri, 17 May 2019 19:49:58 -0400 Subject: [PATCH 36/77] Remove unused imports from std.random.rndGen --- std/random.d | 3 --- 1 file changed, 3 deletions(-) diff --git a/std/random.d b/std/random.d index b21b184b692..66d3f2ea82b 100644 --- a/std/random.d +++ b/std/random.d @@ -1804,9 +1804,6 @@ A singleton instance of the default random number generator */ @property ref Random rndGen() @safe nothrow @nogc { - import std.algorithm.iteration : map; - import std.range : repeat; - static Random result; static bool initialized; if (!initialized) From d2be19720897026dbd5e9f7812ebd2c292527eeb Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Fri, 17 May 2019 19:55:02 -0400 Subject: [PATCH 37/77] Remove unnecessary check-and-initialize in std.alorithm.internal.rndstuff The check-and-initialize pattern dates back to when `rnd` was seeded with `unpredictableSeed`. With a fixed seed that's unnecessary. --- std/algorithm/internal.d | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/std/algorithm/internal.d b/std/algorithm/internal.d index 666584f820a..71d72cff1b6 100644 --- a/std/algorithm/internal.d +++ b/std/algorithm/internal.d @@ -21,15 +21,9 @@ version (unittest) package string[] rndstuff(T : string)() { - import std.random : Random = Xorshift, uniform; + import std.random : Xorshift, uniform; - static Random rnd; - static bool first = true; - if (first) - { - rnd.seed(234_567_891); - first = false; - } + static rnd = Xorshift(234_567_891); string[] result = new string[uniform(minArraySize, maxArraySize, rnd)]; string alpha = "abcdefghijABCDEFGHIJ"; @@ -46,15 +40,9 @@ version (unittest) package int[] rndstuff(T : int)() { - import std.random : Random = Xorshift, uniform; + import std.random : Xorshift, uniform; - static Random rnd; - static bool first = true; - if (first) - { - rnd = Random(345_678_912); - first = false; - } + static rnd = Xorshift(345_678_912); int[] result = new int[uniform(minArraySize, maxArraySize, rnd)]; foreach (ref i; result) { From ae16dadfaa35f76a5f5041649a32f3579320d3ed Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 18 May 2019 17:23:05 -0700 Subject: [PATCH 38/77] add isLvalue() to prepare for rvalue ref --- std/parallelism.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/parallelism.d b/std/parallelism.d index 15f20219048..139b34c2999 100644 --- a/std/parallelism.d +++ b/std/parallelism.d @@ -443,7 +443,7 @@ struct Task(alias fun, Args...) { fun(myCastedTask._args); } - else static if (is(typeof(addressOf(fun(myCastedTask._args))))) + else static if (is(typeof(&(fun(myCastedTask._args))))) { myCastedTask.returnVal = addressOf(fun(myCastedTask._args)); } From 11ebb6474b714a2c9c6a5ee0cb40038eceff5b43 Mon Sep 17 00:00:00 2001 From: Flying-Toast <38232168+Flying-Toast@users.noreply.github.com> Date: Sat, 18 May 2019 21:23:42 -0400 Subject: [PATCH 39/77] remove deprecated stuff in std.json --- std/json.d | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/std/json.d b/std/json.d index 3e943d2cb18..cebb48f3ab5 100644 --- a/std/json.d +++ b/std/json.d @@ -95,20 +95,18 @@ enum JSONType : byte object, /// ditto true_, /// ditto false_, /// ditto - /// These symbols will be deprecated after 2.082. - NULL = null_, - STRING = string, - INTEGER = integer, - UINTEGER = uinteger, - FLOAT = float_, - ARRAY = array, - OBJECT = object, - TRUE = true_, - FALSE = false_, + deprecated("Use .null_") NULL = null_, + deprecated("Use .string") STRING = string, + deprecated("Use .integer") INTEGER = integer, + deprecated("Use .uinteger") UINTEGER = uinteger, + deprecated("Use .float_") FLOAT = float_, + deprecated("Use .array") ARRAY = array, + deprecated("Use .object") OBJECT = object, + deprecated("Use .true_") TRUE = true_, + deprecated("Use .false_") FALSE = false_, } -/// This alias will be deprecated after 2.082. -alias JSON_TYPE = JSONType; +deprecated("Use JSONType") alias JSON_TYPE = JSONType; /** JSON value node From 7bf6a6d0d1e9a0f51b054265e115addea572ff98 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Sun, 19 May 2019 04:36:20 +0200 Subject: [PATCH 40/77] fix issue 19883 - Cyclic constructor call for BigInt(dstring) --- std/bigint.d | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/std/bigint.d b/std/bigint.d index 321ea8e8959..33e06100af5 100644 --- a/std/bigint.d +++ b/std/bigint.d @@ -65,7 +65,7 @@ public: isBidirectionalRange!Range && isSomeChar!(ElementType!Range) && !isInfinite!Range && - !isSomeString!Range) + !isNarrowString!Range) { import std.algorithm.iteration : filterBidirectional; import std.algorithm.searching : startsWith; @@ -116,7 +116,8 @@ public: } /// ditto - this(Range)(Range s) pure if (isSomeString!Range) + this(Range)(Range s) pure + if (isNarrowString!Range) { import std.utf : byCodeUnit; this(s.byCodeUnit); @@ -1920,3 +1921,8 @@ void divMod(const BigInt dividend, const BigInt divisor, out BigInt quotient, ou "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ~ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); } + +@system unittest +{ + auto n = BigInt("1234"d); +} From 8d404f967842357638a3767e8c10e0b3ee8311a1 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 20 May 2019 02:26:22 -0700 Subject: [PATCH 41/77] hasLvalueElements(): use overloading to detect lvalue --- std/range/primitives.d | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/std/range/primitives.d b/std/range/primitives.d index cbeebdbb38f..d2d391d1b3e 100644 --- a/std/range/primitives.d +++ b/std/range/primitives.d @@ -1486,11 +1486,19 @@ static if (isRandomAccessRange!R) passByRef(r[0]); ---- */ enum bool hasLvalueElements(R) = isInputRange!R - && is(typeof(((ref x) => x)(lvalueOf!R.front))) + && is(typeof(isLvalue(lvalueOf!R.front))) && (!isBidirectionalRange!R - || is(typeof(((ref x) => x)(lvalueOf!R.back)))) + || is(typeof(isLvalue(lvalueOf!R.back)))) && (!isRandomAccessRange!R - || is(typeof(((ref x) => x)(lvalueOf!R[0])))); + || is(typeof(isLvalue(lvalueOf!R[0])))); + +/* Compile successfully if argument of type T is an lvalue + */ +private void isLvalue(T)(T) +if (0); + +private void isLvalue(T)(ref T) +if (1); /// @safe unittest From cf2ca66841d1eb4d15ac07d655de413f67188351 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 20 May 2019 12:42:07 -0700 Subject: [PATCH 42/77] fix rvalue test for Final --- std/experimental/typecons.d | 3 --- 1 file changed, 3 deletions(-) diff --git a/std/experimental/typecons.d b/std/experimental/typecons.d index c80edb12617..36b16a12465 100644 --- a/std/experimental/typecons.d +++ b/std/experimental/typecons.d @@ -978,9 +978,6 @@ pure nothrow @safe unittest Final!A a = new A; static assert(!__traits(compiles, a = new A)); - static void foo(ref A a) pure nothrow @safe @nogc {} - static assert(!__traits(compiles, foo(a))); - assert(a.i == 0); a.i = 42; assert(a.i == 42); From b240c867c17251773807ed376fa812daa14439b2 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Tue, 21 May 2019 19:55:04 -0400 Subject: [PATCH 43/77] Faster isNaN test (#7009) * Faster isNaN test --- std/math.d | 72 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/std/math.d b/std/math.d index 601f3137023..11fe84371f2 100644 --- a/std/math.d +++ b/std/math.d @@ -6360,37 +6360,55 @@ version (D_HardFloat) @safe unittest // rounding bool isNaN(X)(X x) @nogc @trusted pure nothrow if (isFloatingPoint!(X)) { - alias F = floatTraits!(X); - static if (F.realFormat == RealFormat.ieeeSingle) - { - const uint p = *cast(uint *)&x; - return ((p & 0x7F80_0000) == 0x7F80_0000) - && p & 0x007F_FFFF; // not infinity - } - else static if (F.realFormat == RealFormat.ieeeDouble) - { - const ulong p = *cast(ulong *)&x; - return ((p & 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) - && p & 0x000F_FFFF_FFFF_FFFF; // not infinity - } - else static if (F.realFormat == RealFormat.ieeeExtended) + version (all) { - const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; - const ulong ps = *cast(ulong *)&x; - return e == F.EXPMASK && - ps & 0x7FFF_FFFF_FFFF_FFFF; // not infinity - } - else static if (F.realFormat == RealFormat.ieeeQuadruple) - { - const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; - const ulong psLsb = (cast(ulong *)&x)[MANTISSA_LSB]; - const ulong psMsb = (cast(ulong *)&x)[MANTISSA_MSB]; - return e == F.EXPMASK && - (psLsb | (psMsb& 0x0000_FFFF_FFFF_FFFF)) != 0; + return x != x; } else { - return x != x; + /* + Code kept for historical context. At least on Intel, the simple test + x != x uses one dedicated instruction (ucomiss/ucomisd) that runs in one + cycle. Code for 80- and 128-bits is larger but still smaller than the + integrals-based solutions below. Future revisions may enable the code + below conditionally depending on hardware. + */ + alias F = floatTraits!(X); + static if (F.realFormat == RealFormat.ieeeSingle) + { + const uint p = *cast(uint *)&x; + // Sign bit (MSB) is irrelevant so mask it out. + // Next 8 bits should be all set. + // At least one bit among the least significant 23 bits should be set. + return (p & 0x7FFF_FFFF) > 0x7F80_0000; + } + else static if (F.realFormat == RealFormat.ieeeDouble) + { + const ulong p = *cast(ulong *)&x; + // Sign bit (MSB) is irrelevant so mask it out. + // Next 11 bits should be all set. + // At least one bit among the least significant 52 bits should be set. + return (p & 0x7FFF_FFFF_FFFF_FFFF) > 0x7FF0_0000_0000_0000; + } + else static if (F.realFormat == RealFormat.ieeeExtended) + { + const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; + const ulong ps = *cast(ulong *)&x; + return e == F.EXPMASK && + ps & 0x7FFF_FFFF_FFFF_FFFF; // not infinity + } + else static if (F.realFormat == RealFormat.ieeeQuadruple) + { + const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; + const ulong psLsb = (cast(ulong *)&x)[MANTISSA_LSB]; + const ulong psMsb = (cast(ulong *)&x)[MANTISSA_MSB]; + return e == F.EXPMASK && + (psLsb | (psMsb& 0x0000_FFFF_FFFF_FFFF)) != 0; + } + else + { + return x != x; + } } } From 96f98ff38001f855ec45d920d8e9d6bd46693e6e Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Wed, 22 May 2019 14:55:06 -0700 Subject: [PATCH 44/77] Change version(unittest) code to use accessors to wrap the static initializers. This prevents the compiler from executing the initializers using CTFE during importing, when using unittest. --- std/datetime/date.d | 49 ++++++++++++++++++++++++++++++++++-------- std/datetime/systime.d | 49 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/std/datetime/date.d b/std/datetime/date.d index 10359d88268..677593707fb 100644 --- a/std/datetime/date.d +++ b/std/datetime/date.d @@ -10437,9 +10437,12 @@ if (isSomeString!T) } +// NOTE: all the non-simple array literals are wrapped in functions, because +// otherwise importing causes re-evaluation of the static initializers using +// CTFE with unittests enabled version (unittest) { -private: +private @safe: // All of these helper arrays are sorted in ascending order. auto testYearsBC = [-1999, -1200, -600, -4, -1, 0]; auto testYearsAD = [1, 4, 1000, 1999, 2000, 2012]; @@ -10457,31 +10460,43 @@ private: } } - MonthDay[] testMonthDays = [MonthDay(1, 1), + MonthDay[] testMonthDays() + { + static MonthDay[] result = [MonthDay(1, 1), MonthDay(1, 2), MonthDay(3, 17), MonthDay(7, 4), MonthDay(10, 27), MonthDay(12, 30), MonthDay(12, 31)]; + return result; + } auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31]; - auto testTODs = [TimeOfDay(0, 0, 0), + TimeOfDay[] testTODs() + { + static result = [TimeOfDay(0, 0, 0), TimeOfDay(0, 0, 1), TimeOfDay(0, 1, 0), TimeOfDay(1, 0, 0), TimeOfDay(13, 13, 13), TimeOfDay(23, 59, 59)]; + return result; + } auto testHours = [0, 1, 12, 22, 23]; auto testMinSecs = [0, 1, 30, 58, 59]; // Throwing exceptions is incredibly expensive, so we want to use a smaller // set of values for tests using assertThrown. - auto testTODsThrown = [TimeOfDay(0, 0, 0), + TimeOfDay[] testTODsThrown() + { + static result = [TimeOfDay(0, 0, 0), TimeOfDay(13, 13, 13), TimeOfDay(23, 59, 59)]; + return result; + } Date[] testDatesBC; Date[] testDatesAD; @@ -10491,7 +10506,9 @@ private: // I'd use a Tuple, but I get forward reference errors if I try. struct GregDay { int day; Date date; } - auto testGregDaysBC = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar + GregDay[] testGregDaysBC() + { + static result = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar GregDay(-735_233, Date(-2012, 1, 1)), GregDay(-735_202, Date(-2012, 2, 1)), GregDay(-735_175, Date(-2012, 2, 28)), @@ -10573,8 +10590,12 @@ private: GregDay(-30, Date(0, 12, 1)), GregDay(-1, Date(0, 12, 30)), GregDay(0, Date(0, 12, 31))]; + return result; + } - auto testGregDaysAD = [GregDay(1, Date(1, 1, 1)), + GregDay[] testGregDaysAD() + { + static result = [GregDay(1, Date(1, 1, 1)), GregDay(2, Date(1, 1, 2)), GregDay(32, Date(1, 2, 1)), GregDay(365, Date(1, 12, 31)), @@ -10642,10 +10663,14 @@ private: GregDay(734_562, Date(2012, 2, 29)), GregDay(734_563, Date(2012, 3, 1)), GregDay(734_858, Date(2012, 12, 21))]; + return result; + } // I'd use a Tuple, but I get forward reference errors if I try. struct DayOfYear { int day; MonthDay md; } - auto testDaysOfYear = [DayOfYear(1, MonthDay(1, 1)), + DayOfYear[] testDaysOfYear() + { + static result = [DayOfYear(1, MonthDay(1, 1)), DayOfYear(2, MonthDay(1, 2)), DayOfYear(3, MonthDay(1, 3)), DayOfYear(31, MonthDay(1, 31)), @@ -10673,8 +10698,12 @@ private: DayOfYear(363, MonthDay(12, 29)), DayOfYear(364, MonthDay(12, 30)), DayOfYear(365, MonthDay(12, 31))]; + return result; + } - auto testDaysOfLeapYear = [DayOfYear(1, MonthDay(1, 1)), + DayOfYear[] testDaysOfLeapYear() + { + static result = [DayOfYear(1, MonthDay(1, 1)), DayOfYear(2, MonthDay(1, 2)), DayOfYear(3, MonthDay(1, 3)), DayOfYear(31, MonthDay(1, 31)), @@ -10703,8 +10732,10 @@ private: DayOfYear(364, MonthDay(12, 29)), DayOfYear(365, MonthDay(12, 30)), DayOfYear(366, MonthDay(12, 31))]; + return result; + } - void initializeTests() @safe + void initializeTests() { foreach (year; testYearsBC) { diff --git a/std/datetime/systime.d b/std/datetime/systime.d index 1d71aba3a28..a2a1287f747 100644 --- a/std/datetime/systime.d +++ b/std/datetime/systime.d @@ -11400,9 +11400,12 @@ if (isIntegral!T && isSigned!T) // The constraints on R were already covered by } +// NOTE: all the non-simple array literals are wrapped in functions, because +// otherwise importing causes re-evaluation of the static initializers using +// CTFE with unittests enabled version (unittest) { -private: +private @safe: // Variables to help in testing. Duration currLocalDiffFromUTC; immutable (TimeZone)[] testTZs; @@ -11424,31 +11427,43 @@ private: } } - MonthDay[] testMonthDays = [MonthDay(1, 1), + MonthDay[] testMonthDays() + { + static result = [MonthDay(1, 1), MonthDay(1, 2), MonthDay(3, 17), MonthDay(7, 4), MonthDay(10, 27), MonthDay(12, 30), MonthDay(12, 31)]; + return result; + } auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31]; - auto testTODs = [TimeOfDay(0, 0, 0), + TimeOfDay[] testTODs() + { + static result = [TimeOfDay(0, 0, 0), TimeOfDay(0, 0, 1), TimeOfDay(0, 1, 0), TimeOfDay(1, 0, 0), TimeOfDay(13, 13, 13), TimeOfDay(23, 59, 59)]; + return result; + } auto testHours = [0, 1, 12, 22, 23]; auto testMinSecs = [0, 1, 30, 58, 59]; // Throwing exceptions is incredibly expensive, so we want to use a smaller // set of values for tests using assertThrown. - auto testTODsThrown = [TimeOfDay(0, 0, 0), + TimeOfDay[] testTODsThrown() + { + static result = [TimeOfDay(0, 0, 0), TimeOfDay(13, 13, 13), TimeOfDay(23, 59, 59)]; + return result; + } Date[] testDatesBC; Date[] testDatesAD; @@ -11463,7 +11478,9 @@ private: // I'd use a Tuple, but I get forward reference errors if I try. struct GregDay { int day; Date date; } - auto testGregDaysBC = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar + GregDay[] testGregDaysBC() + { + static result = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar GregDay(-735_233, Date(-2012, 1, 1)), GregDay(-735_202, Date(-2012, 2, 1)), GregDay(-735_175, Date(-2012, 2, 28)), @@ -11545,8 +11562,12 @@ private: GregDay(-30, Date(0, 12, 1)), GregDay(-1, Date(0, 12, 30)), GregDay(0, Date(0, 12, 31))]; + return result; + } - auto testGregDaysAD = [GregDay(1, Date(1, 1, 1)), + GregDay[] testGregDaysAD() + { + static result = [GregDay(1, Date(1, 1, 1)), GregDay(2, Date(1, 1, 2)), GregDay(32, Date(1, 2, 1)), GregDay(365, Date(1, 12, 31)), @@ -11614,10 +11635,14 @@ private: GregDay(734_562, Date(2012, 2, 29)), GregDay(734_563, Date(2012, 3, 1)), GregDay(734_858, Date(2012, 12, 21))]; + return result; + } // I'd use a Tuple, but I get forward reference errors if I try. struct DayOfYear { int day; MonthDay md; } - auto testDaysOfYear = [DayOfYear(1, MonthDay(1, 1)), + DayOfYear[] testDaysOfYear() + { + static result = [DayOfYear(1, MonthDay(1, 1)), DayOfYear(2, MonthDay(1, 2)), DayOfYear(3, MonthDay(1, 3)), DayOfYear(31, MonthDay(1, 31)), @@ -11645,8 +11670,12 @@ private: DayOfYear(363, MonthDay(12, 29)), DayOfYear(364, MonthDay(12, 30)), DayOfYear(365, MonthDay(12, 31))]; + return result; + } - auto testDaysOfLeapYear = [DayOfYear(1, MonthDay(1, 1)), + DayOfYear[] testDaysOfLeapYear() + { + static result = [DayOfYear(1, MonthDay(1, 1)), DayOfYear(2, MonthDay(1, 2)), DayOfYear(3, MonthDay(1, 3)), DayOfYear(31, MonthDay(1, 31)), @@ -11675,8 +11704,10 @@ private: DayOfYear(364, MonthDay(12, 29)), DayOfYear(365, MonthDay(12, 30)), DayOfYear(366, MonthDay(12, 31))]; + return result; + } - void initializeTests() @safe + void initializeTests() { import std.algorithm.sorting : sort; import std.typecons : Rebindable; From 8337ed2a3fd819ab80641d0afc8f436db02fe4eb Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Wed, 22 May 2019 16:13:05 -0600 Subject: [PATCH 45/77] Explicitly link to pthread --- posix.mak | 1 + 1 file changed, 1 insertion(+) diff --git a/posix.mak b/posix.mak index 32c11d0d2e3..eeea3c772dc 100644 --- a/posix.mak +++ b/posix.mak @@ -112,6 +112,7 @@ OUTFILEFLAG = -o NODEFAULTLIB=-defaultlib= -debuglib= ifeq (,$(findstring win,$(OS))) CFLAGS=$(MODEL_FLAG) -fPIC -DHAVE_UNISTD_H + NODEFAULTLIB += -L-lpthread ifeq ($(BUILD),debug) CFLAGS += -g else From 3578675d26062635794088c898bc65a521ba2ae6 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Thu, 23 May 2019 00:44:27 -0400 Subject: [PATCH 46/77] Fix Issue 19892 - Add CTFE support for std.bitmanip: nativeToBigEndian, bigEndianToNative, littleEndianToNative, nativeToLittleEndian --- std/bitmanip.d | 184 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 136 insertions(+), 48 deletions(-) diff --git a/std/bitmanip.d b/std/bitmanip.d index 3e544d01b95..0abbeca7787 100644 --- a/std/bitmanip.d +++ b/std/bitmanip.d @@ -2790,6 +2790,9 @@ private ulong swapEndianImpl(ulong val) @trusted pure nothrow @nogc assert(swapEndian(swapEndian(T.min)) == T.min); assert(swapEndian(swapEndian(T.max)) == T.max); + // Check CTFE compiles. + static assert(swapEndian(swapEndian(T(1))) is T(1)); + foreach (i; 2 .. 10) { immutable T maxI = cast(T)(T.max / i); @@ -2836,6 +2839,44 @@ if (canSwapEndianness!T) } +// Can't use EndianSwapper union during CTFE. +private auto ctfeRead(T)(const ubyte[T.sizeof] array) +if (__traits(isIntegral, T)) +{ + Unqual!T result; + version (LittleEndian) + foreach_reverse (b; array) + result = cast(Unqual!T) ((result << 8) | b); + else + foreach (b; array) + result = cast(Unqual!T) ((result << 8) | b); + return cast(T) result; +} + +// Can't use EndianSwapper union during CTFE. +private auto ctfeBytes(T)(const T value) +if (__traits(isIntegral, T)) +{ + ubyte[T.sizeof] result; + Unqual!T tmp = value; + version (LittleEndian) + { + foreach (i; 0 .. T.sizeof) + { + result[i] = cast(ubyte) tmp; + tmp = cast(Unqual!T) (tmp >>> 8); + } + } + else + { + foreach_reverse (i; 0 .. T.sizeof) + { + result[i] = cast(ubyte) tmp; + tmp = cast(Unqual!T) (tmp >>> 8); + } + } + return result; +} /++ Converts the given value from the native endianness to big endian and @@ -2883,14 +2924,20 @@ if (canSwapEndianness!T) private auto nativeToBigEndianImpl(T)(T val) @safe pure nothrow @nogc if (isIntegral!T || isSomeChar!T || isBoolean!T) { - EndianSwapper!T es = void; - - version (LittleEndian) - es.value = swapEndian(val); + if (!__ctfe) + { + version (LittleEndian) + return EndianSwapper!T(swapEndian(val)).array; + else + return EndianSwapper!T(val).array; + } else - es.value = val; - - return es.array; + { + version (LittleEndian) + return ctfeBytes(swapEndian(val)); + else + return ctfeBytes(val); + } } private auto nativeToBigEndianImpl(T)(T val) @safe pure nothrow @nogc @@ -2931,6 +2978,9 @@ if (isFloatOrDouble!T) assert(bigEndianToNative!T(nativeToBigEndian(T.min)) == T.min); assert(bigEndianToNative!T(nativeToBigEndian(T.max)) == T.max); + //Check CTFE compiles. + static assert(bigEndianToNative!T(nativeToBigEndian(T(1))) is T(1)); + static if (isSigned!T) assert(bigEndianToNative!T(nativeToBigEndian(cast(T) 0)) == 0); @@ -3007,15 +3057,21 @@ private T bigEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @n if ((isIntegral!T || isSomeChar!T || isBoolean!T) && n == T.sizeof) { - EndianSwapper!T es = void; - es.array = val; - - version (LittleEndian) - immutable retval = swapEndian(es.value); + if (!__ctfe) + { + EndianSwapper!T es = { array: val }; + version (LittleEndian) + return swapEndian(es.value); + else + return es.value; + } else - immutable retval = es.value; - - return retval; + { + version (LittleEndian) + return swapEndian(ctfeRead!T(val)); + else + return ctfeRead!T(val); + } } private T bigEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc @@ -3058,14 +3114,20 @@ if (canSwapEndianness!T) private auto nativeToLittleEndianImpl(T)(T val) @safe pure nothrow @nogc if (isIntegral!T || isSomeChar!T || isBoolean!T) { - EndianSwapper!T es = void; - - version (BigEndian) - es.value = swapEndian(val); + if (!__ctfe) + { + version (BigEndian) + return EndianSwapper!T(swapEndian(val)).array; + else + return EndianSwapper!T(val).array; + } else - es.value = val; - - return es.array; + { + version (BigEndian) + return ctfeBytes(swapEndian(val)); + else + return ctfeBytes(val); + } } private auto nativeToLittleEndianImpl(T)(T val) @safe pure nothrow @nogc @@ -3097,6 +3159,9 @@ if (isFloatOrDouble!T) assert(littleEndianToNative!T(nativeToLittleEndian(T.min)) == T.min); assert(littleEndianToNative!T(nativeToLittleEndian(T.max)) == T.max); + //Check CTFE compiles. + static assert(littleEndianToNative!T(nativeToLittleEndian(T(1))) is T(1)); + static if (isSigned!T) assert(littleEndianToNative!T(nativeToLittleEndian(cast(T) 0)) == 0); @@ -3155,15 +3220,21 @@ private T littleEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow if ((isIntegral!T || isSomeChar!T || isBoolean!T) && n == T.sizeof) { - EndianSwapper!T es = void; - es.array = val; - - version (BigEndian) - immutable retval = swapEndian(es.value); + if (!__ctfe) + { + EndianSwapper!T es = { array: val }; + version (BigEndian) + return swapEndian(es.value); + else + return es.value; + } else - immutable retval = es.value; - - return retval; + { + version (BigEndian) + return swapEndian(ctfeRead!T(val)); + else + return ctfeRead!T(val); + } } private T littleEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc @@ -3176,30 +3247,47 @@ if (((isFloatOrDouble!T) && return floatEndianImpl!(n, false)(val); } -private auto floatEndianImpl(T, bool swap)(T val) @safe pure nothrow @nogc +private auto floatEndianImpl(T, bool swap)(T val) @trusted pure nothrow @nogc if (isFloatOrDouble!T) { - EndianSwapper!T es = void; - es.value = val; - - static if (swap) - es.intValue = swapEndian(es.intValue); - - return es.array; + if (!__ctfe) + { + EndianSwapper!T es = EndianSwapper!T(val); + static if (swap) + es.intValue = swapEndian(es.intValue); + return es.array; + } + else + { + static if (T.sizeof == 4) + uint intValue = *cast(const uint*) &val; + else static if (T.sizeof == 8) + ulong intValue = *cast(const ulong*) & val; + static if (swap) + intValue = swapEndian(intValue); + return ctfeBytes(intValue); + } } -private auto floatEndianImpl(size_t n, bool swap)(ubyte[n] val) @safe pure nothrow @nogc +private auto floatEndianImpl(size_t n, bool swap)(ubyte[n] val) @trusted pure nothrow @nogc if (n == 4 || n == 8) { - static if (n == 4) EndianSwapper!float es = void; - else static if (n == 8) EndianSwapper!double es = void; - - es.array = val; - - static if (swap) - es.intValue = swapEndian(es.intValue); - - return es.value; + static if (n == 4) { alias Float = float; alias Int = uint; } + else static if (n == 8) { alias Float = double; alias Int = ulong; } + if (!__ctfe) + { + EndianSwapper!Float es = { array: val }; + static if (swap) + es.intValue = swapEndian(es.intValue); + return es.value; + } + else + { + Int x = ctfeRead!Int(val); + static if (swap) + x = swapEndian(x); + return *cast(const Float*) &x; + } } private template isFloatOrDouble(T) From 516432d185bf4ace339f7e571f1b46894e8536aa Mon Sep 17 00:00:00 2001 From: Nicholas Lindsay Wilson Date: Wed, 24 Apr 2019 12:05:03 +0100 Subject: [PATCH 47/77] Fix issue 13471: can't use crc at CTFE --- std/digest/crc.d | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/std/digest/crc.d b/std/digest/crc.d index e3e0b1d0c94..e1e48ff0bc6 100644 --- a/std/digest/crc.d +++ b/std/digest/crc.d @@ -203,15 +203,19 @@ if (N == 32 || N == 64) enum hasLittleEndianUnalignedReads = true; else enum hasLittleEndianUnalignedReads = false; // leave decision to optimizer - static if (hasLittleEndianUnalignedReads) + + uint one = void; + uint two = void; + + if (!__ctfe && hasLittleEndianUnalignedReads) { - uint one = (cast(uint*) data.ptr)[0]; - uint two = (cast(uint*) data.ptr)[1]; + one = (cast(uint*) data.ptr)[0]; + two = (cast(uint*) data.ptr)[1]; } else { - uint one = (data.ptr[3] << 24 | data.ptr[2] << 16 | data.ptr[1] << 8 | data.ptr[0]); - uint two = (data.ptr[7] << 24 | data.ptr[6] << 16 | data.ptr[5] << 8 | data.ptr[4]); + one = (data.ptr[3] << 24 | data.ptr[2] << 16 | data.ptr[1] << 8 | data.ptr[0]); + two = (data.ptr[7] << 24 | data.ptr[6] << 16 | data.ptr[5] << 8 | data.ptr[4]); } static if (N == 32) @@ -279,6 +283,22 @@ if (N == 32 || N == 64) } } +@safe unittest +{ + // https://issues.dlang.org/show_bug.cgi?id=13471 + static ubyte[4] foo(string str) + { + ubyte[4] result = str.crc32Of(); + if (result == (ubyte[4]).init) + throw new Exception("this should not be thrown"); + return result; + } + enum buggy1 = foo("Hello World!"); + enum buggy2 = crc32Of("Hello World!"); + assert(buggy1 == buggy2); + assert(buggy1 == "Hello World!".crc32Of()); +} + /// @safe unittest { From 9092826b2785b9b4b76d0897fcc9f734707936e8 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 23 May 2019 09:51:54 +0200 Subject: [PATCH 48/77] Use selective top-level module imports in std.{base64,csv,datetime} --- std/base64.d | 8 +++++--- std/csv.d | 2 +- std/datetime/date.d | 4 +--- std/datetime/timezone.d | 8 +++----- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/std/base64.d b/std/base64.d index 46b70f1731a..c1f9188e06b 100644 --- a/std/base64.d +++ b/std/base64.d @@ -57,9 +57,10 @@ */ module std.base64; -import std.exception; // enforce -import std.range.primitives; // isInputRange, isOutputRange, isForwardRange, ElementType, hasLength -import std.traits; // isArray +import std.exception : enforce; +import std.range.primitives : empty, front, isInputRange, isOutputRange, + isForwardRange, ElementType, hasLength, popFront, put, save; +import std.traits : isArray; // Make sure module header code examples work correctly. @safe unittest @@ -1764,6 +1765,7 @@ class Base64Exception : Exception import std.algorithm.comparison : equal; import std.algorithm.sorting : sort; import std.conv; + import std.exception : assertThrown; import std.file; import std.stdio; diff --git a/std/csv.d b/std/csv.d index 9c3f8360a8e..4ac14462b9c 100644 --- a/std/csv.d +++ b/std/csv.d @@ -92,7 +92,7 @@ module std.csv; import std.conv; -import std.exception; // basicExceptionCtors +import std.exception : basicExceptionCtors; import std.range.primitives; import std.traits; diff --git a/std/datetime/date.d b/std/datetime/date.d index 10359d88268..2c24141f824 100644 --- a/std/datetime/date.d +++ b/std/datetime/date.d @@ -40,9 +40,7 @@ $(TR $(TD Other) $(TD +/ module std.datetime.date; -// Note: reconsider using specific imports below after -// https://issues.dlang.org/show_bug.cgi?id=17630 has been fixed -import core.time;// : TimeException; +import core.time : TimeException; import std.traits : isSomeString, Unqual; import std.typecons : Flag; import std.range.primitives : isOutputRange; diff --git a/std/datetime/timezone.d b/std/datetime/timezone.d index 9e466b9367b..c5d4b3333aa 100644 --- a/std/datetime/timezone.d +++ b/std/datetime/timezone.d @@ -27,11 +27,9 @@ $(TR $(TD Utilities) $(TD +/ module std.datetime.timezone; -// Note: reconsider using specific imports below after -// https://issues.dlang.org/show_bug.cgi?id=17630 has been fixed -import core.time;// : abs, convert, dur, Duration, hours, minutes; -import std.datetime.systime;// : Clock, stdTimeToUnixTime, SysTime; -import std.range.primitives;// : back, front, empty, popFront; +import core.time : abs, convert, dur, Duration, hours, minutes; +import std.datetime.systime : Clock, stdTimeToUnixTime, SysTime; +import std.range.primitives : back, empty, front, isOutputRange, popFront; import std.traits : isIntegral, isSomeString, Unqual; version (Windows) From 12c5e1ee91be805270145a12119cc0fb0ce501df Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 23 May 2019 09:47:27 +0200 Subject: [PATCH 49/77] Use selective top-level module imports in std.algorithm --- std/algorithm/comparison.d | 6 ++---- std/algorithm/iteration.d | 3 +-- std/algorithm/mutation.d | 3 +-- std/algorithm/searching.d | 7 +++---- std/algorithm/setops.d | 8 +++----- std/algorithm/sorting.d | 23 ++++++++++++++++------- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/std/algorithm/comparison.d b/std/algorithm/comparison.d index b37fb25252c..a4379953443 100644 --- a/std/algorithm/comparison.d +++ b/std/algorithm/comparison.d @@ -58,13 +58,11 @@ T2=$(TR $(TDNW $(LREF $1)) $(TD $+)) */ module std.algorithm.comparison; -// FIXME -import std.functional; // : unaryFun, binaryFun; +import std.functional : unaryFun, binaryFun; import std.range.primitives; import std.traits; -// FIXME import std.meta : allSatisfy; -import std.typecons; // : tuple, Tuple, Flag, Yes; +import std.typecons : tuple, Tuple, Flag, Yes; import std.internal.attributes : betterC; diff --git a/std/algorithm/iteration.d b/std/algorithm/iteration.d index 9ed24c335f9..e4101f76e3b 100644 --- a/std/algorithm/iteration.d +++ b/std/algorithm/iteration.d @@ -70,8 +70,7 @@ T2=$(TR $(TDNW $(LREF $1)) $(TD $+)) */ module std.algorithm.iteration; -// FIXME -import std.functional; // : unaryFun, binaryFun; +import std.functional : unaryFun, binaryFun; import std.range.primitives; import std.traits; import std.typecons : Flag; diff --git a/std/algorithm/mutation.d b/std/algorithm/mutation.d index c8eb6735afc..f0fe03f2668 100644 --- a/std/algorithm/mutation.d +++ b/std/algorithm/mutation.d @@ -81,8 +81,7 @@ import std.range.primitives; import std.traits : isArray, isAssignable, isBlitAssignable, isNarrowString, Unqual, isSomeChar, isMutable; import std.meta : allSatisfy; -// FIXME -import std.typecons; // : tuple, Tuple; +import std.typecons : tuple, Tuple; // bringToFront /** diff --git a/std/algorithm/searching.d b/std/algorithm/searching.d index ceb46bd3824..3c190110da2 100644 --- a/std/algorithm/searching.d +++ b/std/algorithm/searching.d @@ -102,12 +102,10 @@ T2=$(TR $(TDNW $(LREF $1)) $(TD $+)) */ module std.algorithm.searching; -// FIXME -import std.functional; // : unaryFun, binaryFun; +import std.functional : unaryFun, binaryFun; import std.range.primitives; import std.traits; -// FIXME -import std.typecons; // : Tuple, Flag, Yes, No; +import std.typecons : Tuple, Flag, Yes, No, tuple; /++ Checks if $(I _all) of the elements verify `pred`. @@ -1278,6 +1276,7 @@ private enum bool hasConstEmptyMember(T) = is(typeof(((const T* a) => (*a).empty // see: https://github.com/dlang/phobos/pull/6136 private template RebindableOrUnqual(T) { + import std.typecons : Rebindable; static if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T) alias RebindableOrUnqual = Rebindable!T; else diff --git a/std/algorithm/setops.d b/std/algorithm/setops.d index 37dc2b59194..e9ace8eb2a4 100644 --- a/std/algorithm/setops.d +++ b/std/algorithm/setops.d @@ -49,13 +49,11 @@ module std.algorithm.setops; import std.range.primitives; -// FIXME -import std.functional; // : unaryFun, binaryFun; +import std.functional : unaryFun, binaryFun; import std.traits; -// FIXME -import std.meta; // : AliasSeq, staticMap, allSatisfy, anySatisfy; +import std.meta : AliasSeq, staticMap, allSatisfy, anySatisfy; -import std.algorithm.sorting; // : Merge; +import std.algorithm.sorting : Merge; import std.typecons : No; // cartesianProduct diff --git a/std/algorithm/sorting.d b/std/algorithm/sorting.d index a0357bdc366..eb1b952818b 100644 --- a/std/algorithm/sorting.d +++ b/std/algorithm/sorting.d @@ -78,12 +78,11 @@ T2=$(TR $(TDNW $(LREF $1)) $(TD $+)) module std.algorithm.sorting; import std.algorithm.mutation : SwapStrategy; -import std.functional; // : unaryFun, binaryFun; +import std.functional : unaryFun, binaryFun; import std.range.primitives; -import std.typecons : Flag; -// FIXME -import std.meta; // : allSatisfy; -import std.range; // : SortedRange; +import std.typecons : Flag, No, Yes; +import std.meta : allSatisfy; +import std.range : SortedRange; import std.traits; /** @@ -751,8 +750,10 @@ if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && hasAssig assert(a == [ 42, 42 ]); import std.algorithm.iteration : map; + import std.array : array; import std.format : format; - import std.random; + import std.random : Random, uniform, Xorshift; + import std.range : iota; auto s = 123_456_789; auto g = Xorshift(s); a = iota(0, uniform(1, 1000, g)) @@ -1063,6 +1064,7 @@ if (isRandomAccessRange!Range && !isInfinite!Range && @safe unittest { import std.algorithm.comparison : equal; + import std.range : iota; ubyte[256] index = void; iota(256).makeIndex(index[]); @@ -1791,6 +1793,7 @@ private void sort5(alias lt, Range)(Range r) { import std.algorithm.iteration : permutations; import std.algorithm.mutation : copy; + import std.range : iota; int[5] buf; foreach (per; iota(5).permutations) @@ -1931,7 +1934,10 @@ if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range || @safe unittest { // Simple regression benchmark - import std.algorithm.iteration, std.algorithm.mutation, std.random; + import std.algorithm.iteration, std.algorithm.mutation; + import std.array : array; + import std.random : Random, uniform; + import std.range : iota; Random rng; int[] a = iota(20148).map!(_ => uniform(-1000, 1000, rng)).array; static uint comps; @@ -3148,6 +3154,7 @@ if (isRandomAccessRange!(Range) && hasLength!Range && @safe unittest { import std.algorithm.comparison : equal; + import std.range : zip; import std.typecons : tuple; auto a = [10, 30, 20]; auto b = ["c", "b", "a"]; @@ -3456,7 +3463,9 @@ done: assert(expandPartition!((a, b) => a < b)(a, 4, 5, 6) == 9); import std.algorithm.iteration : map; + import std.array : array; import std.random : uniform; + import std.range : iota; auto size = uniform(1, 1000); a = iota(0, size).map!(_ => uniform(0, 1000)).array; if (a.length == 0) return; From 8bc39461aa329efaed3283025d8003ed657cfe30 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 23 May 2019 10:07:26 +0200 Subject: [PATCH 50/77] Use selective top-level module imports in std.{path,range,regex} --- std/path.d | 3 +-- std/range/package.d | 14 +++++++++++--- std/regex/package.d | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/std/path.d b/std/path.d index b9b28f7ca8a..cdb5e106af1 100644 --- a/std/path.d +++ b/std/path.d @@ -96,8 +96,7 @@ $(TR $(TD Other) $(TD module std.path; -// FIXME -import std.file; //: getcwd; +import std.file : getcwd; static import std.meta; import std.range.primitives; import std.traits; diff --git a/std/range/package.d b/std/range/package.d index 4dd67c4a159..19f33da4735 100644 --- a/std/range/package.d +++ b/std/range/package.d @@ -233,9 +233,9 @@ public import std.range.interfaces; public import std.range.primitives; public import std.typecons : Flag, Yes, No; -import std.meta; // allSatisfy, staticMap -import std.traits; // CommonType, isCallable, isFloatingPoint, isIntegral, - // isPointer, isSomeFunction, isStaticArray, Unqual, isInstanceOf +import std.meta : allSatisfy, staticMap; +import std.traits : CommonType, isCallable, isFloatingPoint, isIntegral, + isPointer, isSomeFunction, isStaticArray, Unqual, isInstanceOf; /** @@ -3674,6 +3674,7 @@ private struct Generator(Fun...) { static assert(Fun.length == 1); static assert(isInputRange!Generator); + import std.traits : FunctionAttribute, functionAttributes, ReturnType; private: static if (is(Fun[0])) @@ -4650,6 +4651,7 @@ if (Ranges.length && allSatisfy!(isInputRange, Ranges)) auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)) { + import std.meta : anySatisfy, templateOr; static if (allSatisfy!(isInfinite, Ranges) || Ranges.length == 1) { return ZipShortest!(Ranges)(ranges); @@ -4831,6 +4833,7 @@ package struct ZipShortest(Flag!"allKnownSameLength" allKnownSameLength, Ranges. if (Ranges.length && allSatisfy!(isInputRange, Ranges)) { import std.format : format; //for generic mixins + import std.meta : anySatisfy, templateOr; import std.typecons : Tuple; deprecated("Use of an undocumented alias R.") @@ -6448,6 +6451,7 @@ pure @safe unittest pure nothrow @nogc @safe unittest { + import std.traits : Signed; //float overloads use std.conv.to so can't be @nogc or nothrow alias ssize_t = Signed!size_t; assert(iota(ssize_t.max, 0, -1).length == ssize_t.max); @@ -9603,6 +9607,7 @@ public: } } + import std.meta : Filter, templateNot; alias SliceableDummyRanges = Filter!(hasSlicing, AllDummyRanges); static foreach (Partial; [Yes.withPartial, No.withPartial]) @@ -12109,6 +12114,7 @@ if (isInputRange!R) private struct Bitwise(R) if (isInputRange!R && isIntegral!(ElementType!R)) { + import std.traits : Unsigned; private: alias ElemType = ElementType!R; alias UnsignedElemType = Unsigned!ElemType; @@ -12424,6 +12430,7 @@ if (isInputRange!R && isIntegral!(ElementType!R)) // Test all range types over all integral types @safe pure nothrow unittest { + import std.meta : AliasSeq; import std.internal.test.dummyrange; alias IntegralTypes = AliasSeq!(byte, ubyte, short, ushort, int, uint, @@ -12520,6 +12527,7 @@ if (isInputRange!R && isIntegral!(ElementType!R)) // Test opIndex and opSlice @system unittest { + import std.meta : AliasSeq; alias IntegralTypes = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong); foreach (IntegralType; IntegralTypes) diff --git a/std/regex/package.d b/std/regex/package.d index 15dee8c1859..c7537ce9ce4 100644 --- a/std/regex/package.d +++ b/std/regex/package.d @@ -298,7 +298,7 @@ module std.regex; import std.range.primitives, std.traits; import std.regex.internal.ir; -import std.typecons; // : Flag, Yes, No; +import std.typecons : Flag, Yes, No; /++ `Regex` object holds regular expression pattern in compiled form. @@ -682,6 +682,7 @@ public: @trusted public struct RegexMatch(R) if (isSomeString!R) { + import std.typecons : Rebindable; private: alias Char = BasicElementOf!R; Matcher!Char _engine; From 1386fa253fe6660b20e308108fcd73b3ce754e54 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 23 May 2019 10:29:38 +0200 Subject: [PATCH 51/77] Use selective top-level module imports in std.{stdio,string} --- std/stdio.d | 14 +++++++------- std/string.d | 16 +++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/std/stdio.d b/std/stdio.d index 1d455504f8d..310fdfdbaad 100644 --- a/std/stdio.d +++ b/std/stdio.d @@ -13,14 +13,14 @@ Authors: $(HTTP digitalmars.com, Walter Bright), */ module std.stdio; -import core.stdc.stddef; // wchar_t +import core.stdc.stddef : wchar_t; public import core.stdc.stdio; -import std.algorithm.mutation; // copy -import std.meta; // allSatisfy -import std.range.primitives; // ElementEncodingType, empty, front, - // isBidirectionalRange, isInputRange, put -import std.traits; // isSomeChar, isSomeString, Unqual, isPointer -import std.typecons; // Flag +import std.algorithm.mutation : copy; +import std.meta : allSatisfy; +import std.range.primitives : ElementEncodingType, empty, front, + isBidirectionalRange, isInputRange, put; +import std.traits : isSomeChar, isSomeString, Unqual, isPointer; +import std.typecons : Flag, No, Yes; /++ If flag `KeepTerminator` is set to `KeepTerminator.yes`, then the delimiter diff --git a/std/string.d b/std/string.d index d6170dfc592..12500f12f31 100644 --- a/std/string.d +++ b/std/string.d @@ -175,13 +175,13 @@ public import std.format : format, sformat; import std.typecons : Flag, Yes, No; public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace; -import std.meta; // AliasSeq, staticIndexOf -import std.range.primitives; // back, ElementEncodingType, ElementType, front, - // hasLength, hasSlicing, isBidirectionalRange, isForwardRange, isInfinite, - // isInputRange, isOutputRange, isRandomAccessRange, popBack, popFront, put, - // save; -import std.traits; // isConvertibleToString, isNarrowString, isSomeChar, - // isSomeString, StringTypeOf, Unqual +import std.meta : AliasSeq, staticIndexOf; +import std.range.primitives : back, ElementEncodingType, ElementType, front, + hasLength, hasSlicing, isBidirectionalRange, isForwardRange, isInfinite, + isInputRange, isOutputRange, isRandomAccessRange, popBack, popFront, put, + save; +import std.traits : isConvertibleToString, isNarrowString, isSomeChar, + isSomeString, StringTypeOf, Unqual; //public imports for backward compatibility public import std.algorithm.comparison : cmp; @@ -2997,6 +2997,7 @@ auto stripLeft(Range)(Range input) if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) && !isInfinite!Range && !isConvertibleToString!Range) { + import std.traits : isDynamicArray; static import std.ascii; static import std.uni; @@ -3196,6 +3197,7 @@ if (isSomeString!Range || !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range)) { + import std.traits : isDynamicArray; import std.uni : isWhite; alias C = Unqual!(ElementEncodingType!(typeof(str))); From 66991b4cd7fa41980527f56318799420fcee62d3 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 23 May 2019 10:33:51 +0200 Subject: [PATCH 52/77] Use selective top-level module imports in std.{typecons,uni,utf} --- std/typecons.d | 7 ++++++- std/uni.d | 22 ++++++++++++++++------ std/utf.d | 23 +++++++++++++++++++---- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/std/typecons.d b/std/typecons.d index abc133c97e0..53737632563 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -69,7 +69,7 @@ Authors: $(HTTP erdani.org, Andrei Alexandrescu), module std.typecons; import std.format : singleSpec, FormatSpec, formatValue; -import std.meta; // : AliasSeq, allSatisfy; +import std.meta : AliasSeq, allSatisfy; import std.range.primitives : isOutputRange; import std.traits; import std.internal.attributes : betterC; @@ -949,6 +949,8 @@ if (distinctFieldNames!(Specs)) static assert(nN <= nT, "Cannot have more names than tuple members"); alias allNames = AliasSeq!(names, fieldNames[nN .. $]); + import std.meta : Alias, aliasSeqOf; + template GetItem(size_t idx) { import std.array : empty; @@ -1021,6 +1023,7 @@ if (distinctFieldNames!(Specs)) if (is(typeof(translate) : V[K], V, K) && isSomeString!V && (isSomeString!K || is(K : size_t))) { + import std.meta : aliasSeqOf; import std.range : ElementType; static if (isSomeString!(ElementType!(typeof(translate.keys)))) { @@ -4967,6 +4970,7 @@ private static: } } + import std.meta : templateNot; alias Implementation = AutoImplement!(Issue17177, how, templateNot!isFinalFunction); } @@ -5482,6 +5486,7 @@ if (Targets.length >= 1 && allSatisfy!(isMutable, Targets)) template OnlyVirtual(members...) { enum notFinal(alias T) = !__traits(isFinalFunction, T); + import std.meta : Filter; alias OnlyVirtual = Filter!(notFinal, members); } diff --git a/std/uni.d b/std/uni.d index d934a067efc..1b9bf2ef9c2 100644 --- a/std/uni.d +++ b/std/uni.d @@ -703,12 +703,12 @@ CLUSTER = $(S_LINK Grapheme cluster, grapheme cluster) +/ module std.uni; -import std.meta; // AliasSeq -import std.range.primitives; // back, ElementEncodingType, ElementType, empty, - // front, isForwardRange, isInputRange, isRandomAccessRange, popFront, put, - // save -import std.traits; // isConvertibleToString, isIntegral, isSomeChar, - // isSomeString, Unqual +import std.meta : AliasSeq; +import std.range.primitives : back, ElementEncodingType, ElementType, empty, + front, hasLength, hasSlicing, isForwardRange, isInputRange, + isRandomAccessRange, popFront, put, save; +import std.traits : isConvertibleToString, isIntegral, isSomeChar, + isSomeString, Unqual; // debug = std_uni; debug(std_uni) import std.stdio; // writefln, writeln @@ -2804,6 +2804,8 @@ private: // a random-access range of integral pairs static struct Intervals(Range) { + import std.range.primitives : hasAssignableElements; + this(Range sp) scope { slice = sp; @@ -4943,6 +4945,7 @@ template Utf8Matcher() bool lookup(int size, Mode mode, Range)(ref Range inp) const { + import std.range : popFrontN; if (inp.length < size) { badEncoding(); @@ -5208,6 +5211,7 @@ template Utf16Matcher() } else { + import std.range : popFrontN; static if (sizeFlags & 2) { if (inp.length < 2) @@ -7333,6 +7337,8 @@ if (isInputRange!Range && is(Unqual!(ElementType!Range) == Grapheme)) auto byCodePoint(Range)(Range range) if (isInputRange!Range && is(Unqual!(ElementType!Range) == dchar)) { + import std.range.primitives : isBidirectionalRange, popBack; + import std.traits : isNarrowString; static if (isNarrowString!Range) { static struct Result @@ -7786,7 +7792,9 @@ if (isInputRange!S1 && isSomeChar!(ElementEncodingType!S1) && isInputRange!S2 && isSomeChar!(ElementEncodingType!S2)) { import std.internal.unicode_tables : sTable = simpleCaseTable; // generated file + import std.range.primitives : isInfinite; import std.utf : decodeFront; + import std.traits : isDynamicArray; import std.typecons : Yes; static import std.ascii; @@ -7963,6 +7971,8 @@ int icmp(S1, S2)(S1 r1, S2 r2) if (isForwardRange!S1 && isSomeChar!(ElementEncodingType!S1) && isForwardRange!S2 && isSomeChar!(ElementEncodingType!S2)) { + import std.range.primitives : isInfinite; + import std.traits : isDynamicArray; import std.utf : byDchar; static import std.ascii; diff --git a/std/utf.d b/std/utf.d index 298ae3e6dad..3a84adef2ce 100644 --- a/std/utf.d +++ b/std/utf.d @@ -60,11 +60,12 @@ $(TR $(TD Miscellaneous) $(TD +/ module std.utf; -import std.exception; // basicExceptionCtors -import std.meta; // AliasSeq +import std.exception : basicExceptionCtors; +import std.meta : AliasSeq; import std.range.primitives; -import std.traits; // isSomeChar, isSomeString -import std.typecons; // Flag, Yes, No +import std.traits : isAutodecodableString, isPointer, isSomeChar, + isSomeString, isStaticArray, Unqual; +import std.typecons : Flag, Yes, No; /++ @@ -363,6 +364,7 @@ if (is(S : const char[]) || import std.conv : to; import std.exception; import std.string : format; + import std.traits : FunctionAttribute, functionAttributes, isSafe; static void test(string s, dchar c, size_t i = 0, size_t line = __LINE__) { enforce(stride(s, i) == codeLength!char(c), @@ -471,6 +473,7 @@ if (isInputRange!S && is(Unqual!(ElementType!S) == wchar)) import std.conv : to; import std.exception; import std.string : format; + import std.traits : FunctionAttribute, functionAttributes, isSafe; static void test(wstring s, dchar c, size_t i = 0, size_t line = __LINE__) { enforce(stride(s, i) == codeLength!wchar(c), @@ -560,6 +563,7 @@ if (is(S : const dchar[]) || import std.conv : to; import std.exception; import std.string : format; + import std.traits : FunctionAttribute, functionAttributes, isSafe; static void test(dstring s, dchar c, size_t i = 0, size_t line = __LINE__) { enforce(stride(s, i) == codeLength!dchar(c), @@ -717,6 +721,7 @@ if (isBidirectionalRange!S && is(Unqual!(ElementType!S) == char) && !isRandomAcc import std.conv : to; import std.exception; import std.string : format; + import std.traits : FunctionAttribute, functionAttributes, isSafe; static void test(string s, dchar c, size_t i = size_t.max, size_t line = __LINE__) { enforce(strideBack(s, i == size_t.max ? s.length : i) == codeLength!char(c), @@ -814,6 +819,7 @@ if (is(S : const wchar[]) || import std.conv : to; import std.exception; import std.string : format; + import std.traits : FunctionAttribute, functionAttributes, isSafe; static void test(wstring s, dchar c, size_t i = size_t.max, size_t line = __LINE__) { enforce(strideBack(s, i == size_t.max ? s.length : i) == codeLength!wchar(c), @@ -909,6 +915,7 @@ if (isBidirectionalRange!S && is(Unqual!(ElementEncodingType!S) == dchar)) import std.conv : to; import std.exception; import std.string : format; + import std.traits : FunctionAttribute, functionAttributes, isSafe; static void test(dstring s, dchar c, size_t i = size_t.max, size_t line = __LINE__) { enforce(strideBack(s, i == size_t.max ? s.length : i) == codeLength!dchar(c), @@ -1068,6 +1075,7 @@ alias UseReplacementDchar = Flag!"useReplacementDchar"; // Reduce distinct instantiations of decodeImpl. private template TypeForDecode(T) { + import std.traits : isDynamicArray; static if (isDynamicArray!T && is(T : E[], E) && __traits(isArithmetic, E) && !is(E == shared)) alias TypeForDecode = const(Unqual!E)[]; else @@ -1856,6 +1864,7 @@ version (unittest) private void testDecode(R)(R range, size_t line = __LINE__) { import core.exception : AssertError; + import std.exception : enforce; import std.string : format; static if (hasLength!R) @@ -1884,6 +1893,7 @@ version (unittest) private void testDecodeFront(R)(ref R range, size_t line = __LINE__) { import core.exception : AssertError; + import std.exception : enforce; import std.string : format; static if (hasLength!R) @@ -1914,6 +1924,7 @@ version (unittest) private void testDecodeBack(R)(ref R range, else { import core.exception : AssertError; + import std.exception : enforce; import std.string : format; static if (hasLength!R) @@ -1951,6 +1962,7 @@ version (unittest) private void testAllDecode(R)(R range, version (unittest) private void testBadDecode(R)(R range, size_t index, size_t line = __LINE__) { import core.exception : AssertError; + import std.exception : assertThrown, enforce; import std.string : format; immutable initialIndex = index; @@ -1982,6 +1994,7 @@ version (unittest) private void testBadDecodeBack(R)(R range, size_t line = __LI else { import core.exception : AssertError; + import std.exception : assertThrown, enforce; import std.string : format; static if (hasLength!R) @@ -2198,6 +2211,7 @@ version (unittest) private void testBadDecodeBack(R)(R range, size_t line = __LI @safe unittest { import std.exception; + import std.traits : FunctionAttribute, functionAttributes, isSafe; assertCTFEable!( { foreach (S; AliasSeq!( char[], const( char)[], string, @@ -3535,6 +3549,7 @@ if (isAutodecodableString!R || isInputRange!R && isSomeChar!(ElementEncodingType!R) || (is(R : const dchar[]) && !isStaticArray!R)) { + import std.traits : isNarrowString, StringTypeOf; static if (isNarrowString!R || // This would be cleaner if we had a way to check whether a type // was a range without any implicit conversions. From b56db9a06128072b3a8e52e07bb3ae17892f32f5 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 23 May 2019 10:03:52 +0200 Subject: [PATCH 53/77] Use selective top-level module imports in std.{functional,getopt,math,net,outbuffer} --- std/functional.d | 4 ++-- std/getopt.d | 6 ++++-- std/math.d | 3 ++- std/net/isemail.d | 3 +-- std/outbuffer.d | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/std/functional.d b/std/functional.d index aa833de6272..9e332d2a61c 100644 --- a/std/functional.d +++ b/std/functional.d @@ -61,8 +61,8 @@ Distributed under the Boost Software License, Version 1.0. */ module std.functional; -import std.meta; // AliasSeq, Reverse -import std.traits; // isCallable, Parameters +import std.meta : AliasSeq, Reverse; +import std.traits : isCallable, Parameters; private template needOpCallAlias(alias fun) diff --git a/std/getopt.d b/std/getopt.d index 0393332bcc8..adfcf4cff22 100644 --- a/std/getopt.d +++ b/std/getopt.d @@ -28,7 +28,7 @@ Distributed under the Boost Software License, Version 1.0. */ module std.getopt; -import std.exception; // basicExceptionCtors +import std.exception : basicExceptionCtors; import std.traits; /** @@ -659,6 +659,7 @@ private template optionValidator(A...) @system unittest // bugzilla 15914 { + import std.exception : assertThrown; bool opt; string[] args = ["program", "-a"]; getopt(args, config.passThrough, 'a', &opt); @@ -1743,7 +1744,8 @@ void defaultGetoptFormatter(Output)(Output output, string text, Option[] opt) // throw on duplicate options @system unittest { - import core.exception; + import core.exception : AssertError; + import std.exception : assertNotThrown, assertThrown; auto args = ["prog", "--abc", "1"]; int abc, def; assertThrown!AssertError(getopt(args, "abc", &abc, "abc", &abc)); diff --git a/std/math.d b/std/math.d index 601f3137023..58c2d2807d3 100644 --- a/std/math.d +++ b/std/math.d @@ -130,7 +130,8 @@ version (Win64) static import core.math; static import core.stdc.math; static import core.stdc.fenv; -import std.traits; // CommonType, isFloatingPoint, isIntegral, isSigned, isUnsigned, Largest, Unqual +import std.traits : CommonType, isFloatingPoint, isIntegral, isNumeric, + isSigned, isUnsigned, Largest, Unqual; version (LDC) { diff --git a/std/net/isemail.d b/std/net/isemail.d index ef9982d6ba9..d750e08f03e 100644 --- a/std/net/isemail.d +++ b/std/net/isemail.d @@ -25,8 +25,7 @@ */ module std.net.isemail; -// FIXME -import std.range.primitives; // : ElementType; +import std.range.primitives : back, front, ElementType, popFront, popBack; import std.traits; import std.typecons : Flag, Yes, No; diff --git a/std/outbuffer.d b/std/outbuffer.d index e964255fc9f..c3d14a0f8a4 100644 --- a/std/outbuffer.d +++ b/std/outbuffer.d @@ -12,7 +12,7 @@ Serialize data to `ubyte` arrays. */ module std.outbuffer; -import core.stdc.stdarg; // : va_list; +import core.stdc.stdarg; /********************************************* * OutBuffer provides a way to build up an array of bytes out From d17f2eb9f298b8b4957ee74603445d2211ff41d7 Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Sun, 3 Mar 2019 04:47:41 +0900 Subject: [PATCH 54/77] Fix Issue 19513 - Use sched_getaffinity(2) to get the number of CPU cores if available Currently std.parallelism.totalCPUs is implemented by sysconf(_SC_NPROCESSORS_ONLN) on Posix platoform. However, on GNU/Linux, usable number of processors may be restricted if a process runs in container. In case it's better to use sched_getaffinity(2). ref: http://man7.org/linux/man-pages/man1/nproc.1.html --- .../count_processors_via_sched_affinity_on_linux.dd | 10 ++++++++++ std/parallelism.d | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 changelog/count_processors_via_sched_affinity_on_linux.dd diff --git a/changelog/count_processors_via_sched_affinity_on_linux.dd b/changelog/count_processors_via_sched_affinity_on_linux.dd new file mode 100644 index 00000000000..3ca30a87e2a --- /dev/null +++ b/changelog/count_processors_via_sched_affinity_on_linux.dd @@ -0,0 +1,10 @@ +Count processors via sched_getaffinity on Linux + +On GNU/Linux usable number of processors may be restricted if a process runs in containers. +In case it's better to use sched_getaffinity(2). +------- +import std.parallelism; + +writeln(totalCPUs); // 4 +writeln(totalCPUs); // 1: runs on `taskset -c 0` +------- diff --git a/std/parallelism.d b/std/parallelism.d index 139b34c2999..0b0ec035b5e 100644 --- a/std/parallelism.d +++ b/std/parallelism.d @@ -967,7 +967,16 @@ uint totalCPUsImpl() @nogc nothrow @trusted } else version (linux) { + import core.sys.linux.sched : CPU_COUNT, cpu_set_t, sched_getaffinity; import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf; + + cpu_set_t set = void; + if (sched_getaffinity(0, cpu_set_t.sizeof, &set) == 0) + { + int count = CPU_COUNT(&set); + if (count > 0) + return cast(uint) count; + } return cast(uint) sysconf(_SC_NPROCESSORS_ONLN); } else version (Solaris) From 1d6e35c8a16ad7204ad5e0d54500f0ae11bf79a0 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Fri, 24 May 2019 02:45:39 -0400 Subject: [PATCH 55/77] Pare down std.bitmanip's 13 private impl functions to 4 --- std/bitmanip.d | 167 ++++++++++++------------------------------------- 1 file changed, 41 insertions(+), 126 deletions(-) diff --git a/std/bitmanip.d b/std/bitmanip.d index 0abbeca7787..09a47f2fb13 100644 --- a/std/bitmanip.d +++ b/std/bitmanip.d @@ -2724,16 +2724,15 @@ public: T swapEndian(T)(T val) @safe pure nothrow @nogc if (isIntegral!T || isSomeChar!T || isBoolean!T) { + import core.bitop : bswap; static if (val.sizeof == 1) return val; - else static if (isUnsigned!T) - return swapEndianImpl(val); - else static if (isIntegral!T) - return cast(T) swapEndianImpl(cast(Unsigned!T) val); - else static if (is(Unqual!T == wchar)) - return cast(T) swapEndian(cast(ushort) val); - else static if (is(Unqual!T == dchar)) - return cast(T) swapEndian(cast(uint) val); + else static if (T.sizeof == 2) + return cast(T) (((val & 0xff00U) >> 8) | ((val & 0x00ffU) << 8)); + else static if (T.sizeof == 4) + return cast(T) bswap(cast(uint) val); + else static if (T.sizeof == 8) + return cast(T) bswap(cast(ulong) val); else static assert(0, T.stringof ~ " unsupported by swapEndian."); } @@ -2754,25 +2753,6 @@ if (isIntegral!T || isSomeChar!T || isBoolean!T) assert(ulong(10).swapEndian == 720575940379279360); } -private ushort swapEndianImpl(ushort val) @safe pure nothrow @nogc -{ - return ((val & 0xff00U) >> 8) | - ((val & 0x00ffU) << 8); -} - -private uint swapEndianImpl(uint val) @trusted pure nothrow @nogc -{ - import core.bitop : bswap; - return bswap(val); -} - -private ulong swapEndianImpl(ulong val) @trusted pure nothrow @nogc -{ - import core.bitop : bswap; - immutable ulong res = bswap(cast(uint) val); - return res << 32 | bswap(cast(uint)(val >> 32)); -} - @safe unittest { import std.meta; @@ -2894,7 +2874,10 @@ if (__traits(isIntegral, T)) auto nativeToBigEndian(T)(T val) @safe pure nothrow @nogc if (canSwapEndianness!T) { - return nativeToBigEndianImpl(val); + version (LittleEndian) + return nativeToEndianImpl!true(val); + else + return nativeToEndianImpl!false(val); } /// @@ -2921,34 +2904,26 @@ if (canSwapEndianness!T) assert(cd == bigEndianToNative!double(swappedCD)); } -private auto nativeToBigEndianImpl(T)(T val) @safe pure nothrow @nogc -if (isIntegral!T || isSomeChar!T || isBoolean!T) +private auto nativeToEndianImpl(bool swap, T)(const T val) @safe pure nothrow @nogc +if (__traits(isIntegral, T)) { if (!__ctfe) { - version (LittleEndian) + static if (swap) return EndianSwapper!T(swapEndian(val)).array; else return EndianSwapper!T(val).array; } else { - version (LittleEndian) + // Can't use EndianSwapper in CTFE. + static if (swap) return ctfeBytes(swapEndian(val)); else return ctfeBytes(val); } } -private auto nativeToBigEndianImpl(T)(T val) @safe pure nothrow @nogc -if (isFloatOrDouble!T) -{ - version (LittleEndian) - return floatEndianImpl!(T, true)(val); - else - return floatEndianImpl!(T, false)(val); -} - @safe unittest { import std.meta; @@ -3038,7 +3013,10 @@ if (isFloatOrDouble!T) T bigEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc if (canSwapEndianness!T && n == T.sizeof) { - return bigEndianToNativeImpl!(T, n)(val); + version (LittleEndian) + return endianToNativeImpl!(true, T, n)(val); + else + return endianToNativeImpl!(false, T, n)(val); } /// @@ -3053,37 +3031,6 @@ if (canSwapEndianness!T && n == T.sizeof) assert(c == bigEndianToNative!dchar(swappedC)); } -private T bigEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc -if ((isIntegral!T || isSomeChar!T || isBoolean!T) && - n == T.sizeof) -{ - if (!__ctfe) - { - EndianSwapper!T es = { array: val }; - version (LittleEndian) - return swapEndian(es.value); - else - return es.value; - } - else - { - version (LittleEndian) - return swapEndian(ctfeRead!T(val)); - else - return ctfeRead!T(val); - } -} - -private T bigEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc -if (isFloatOrDouble!T && n == T.sizeof) -{ - version (LittleEndian) - return cast(T) floatEndianImpl!(n, true)(val); - else - return cast(T) floatEndianImpl!(n, false)(val); -} - - /++ Converts the given value from the native endianness to little endian and returns it as a `ubyte[n]` where `n` is the size of the given type. @@ -3096,7 +3043,10 @@ if (isFloatOrDouble!T && n == T.sizeof) auto nativeToLittleEndian(T)(T val) @safe pure nothrow @nogc if (canSwapEndianness!T) { - return nativeToLittleEndianImpl(val); + version (BigEndian) + return nativeToEndianImpl!true(val); + else + return nativeToEndianImpl!false(val); } /// @@ -3111,34 +3061,6 @@ if (canSwapEndianness!T) assert(d == littleEndianToNative!double(swappedD)); } -private auto nativeToLittleEndianImpl(T)(T val) @safe pure nothrow @nogc -if (isIntegral!T || isSomeChar!T || isBoolean!T) -{ - if (!__ctfe) - { - version (BigEndian) - return EndianSwapper!T(swapEndian(val)).array; - else - return EndianSwapper!T(val).array; - } - else - { - version (BigEndian) - return ctfeBytes(swapEndian(val)); - else - return ctfeBytes(val); - } -} - -private auto nativeToLittleEndianImpl(T)(T val) @safe pure nothrow @nogc -if (isFloatOrDouble!T) -{ - version (BigEndian) - return floatEndianImpl!(T, true)(val); - else - return floatEndianImpl!(T, false)(val); -} - @safe unittest { import std.meta; @@ -3201,7 +3123,10 @@ if (isFloatOrDouble!T) T littleEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc if (canSwapEndianness!T && n == T.sizeof) { - return littleEndianToNativeImpl!T(val); + version (BigEndian) + return endianToNativeImpl!(true, T, n)(val); + else + return endianToNativeImpl!(false, T, n)(val); } /// @@ -3216,38 +3141,27 @@ if (canSwapEndianness!T && n == T.sizeof) assert(c == littleEndianToNative!dchar(swappedC)); } -private T littleEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc -if ((isIntegral!T || isSomeChar!T || isBoolean!T) && - n == T.sizeof) +private T endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @nogc nothrow pure @safe +if (__traits(isIntegral, T) && n == T.sizeof) { if (!__ctfe) { EndianSwapper!T es = { array: val }; - version (BigEndian) + static if (swap) return swapEndian(es.value); else return es.value; } else { - version (BigEndian) + static if (swap) return swapEndian(ctfeRead!T(val)); else return ctfeRead!T(val); } } -private T littleEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc -if (((isFloatOrDouble!T) && - n == T.sizeof)) -{ - version (BigEndian) - return floatEndianImpl!(n, true)(val); - else - return floatEndianImpl!(n, false)(val); -} - -private auto floatEndianImpl(T, bool swap)(T val) @trusted pure nothrow @nogc +private auto nativeToEndianImpl(bool swap, T)(const T val) @trusted pure nothrow @nogc if (isFloatOrDouble!T) { if (!__ctfe) @@ -3269,24 +3183,25 @@ if (isFloatOrDouble!T) } } -private auto floatEndianImpl(size_t n, bool swap)(ubyte[n] val) @trusted pure nothrow @nogc -if (n == 4 || n == 8) +private auto endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @trusted pure nothrow @nogc +if (isFloatOrDouble!T && n == T.sizeof) { - static if (n == 4) { alias Float = float; alias Int = uint; } - else static if (n == 8) { alias Float = double; alias Int = ulong; } if (!__ctfe) { - EndianSwapper!Float es = { array: val }; + EndianSwapper!T es = { array: val }; static if (swap) es.intValue = swapEndian(es.intValue); return es.value; } else { - Int x = ctfeRead!Int(val); + static if (n == 4) + uint x = ctfeRead!uint(val); + else static if (n == 8) + ulong x = ctfeRead!ulong(val); static if (swap) x = swapEndian(x); - return *cast(const Float*) &x; + return *cast(T*) &x; } } From 3be1b14f96d74e178eab09df03533fc7664b57a5 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Fri, 24 May 2019 01:45:34 -0400 Subject: [PATCH 56/77] Use core.bitop.popcnt in std.bitmanip.countBitsSet --- std/bitmanip.d | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/std/bitmanip.d b/std/bitmanip.d index 0abbeca7787..e94675a9b13 100644 --- a/std/bitmanip.d +++ b/std/bitmanip.d @@ -4492,24 +4492,17 @@ For signed integers, the sign bit is included in the count. private uint countBitsSet(T)(T value) @nogc pure nothrow if (isIntegral!T) { - // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel static if (T.sizeof == 8) { - T c = value - ((value >> 1) & 0x55555555_55555555); - c = ((c >> 2) & 0x33333333_33333333) + (c & 0x33333333_33333333); - c = ((c >> 4) + c) & 0x0F0F0F0F_0F0F0F0F; - c = ((c >> 8) + c) & 0x00FF00FF_00FF00FF; - c = ((c >> 16) + c) & 0x0000FFFF_0000FFFF; - c = ((c >> 32) + c) & 0x00000000_FFFFFFFF; + import core.bitop : popcnt; + const c = popcnt(cast(ulong) value); } else static if (T.sizeof == 4) { - T c = value - ((value >> 1) & 0x55555555); - c = ((c >> 2) & 0x33333333) + (c & 0x33333333); - c = ((c >> 4) + c) & 0x0F0F0F0F; - c = ((c >> 8) + c) & 0x00FF00FF; - c = ((c >> 16) + c) & 0x0000FFFF; + import core.bitop : popcnt; + const c = popcnt(cast(uint) value); } + // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel else static if (T.sizeof == 2) { uint c = value - ((value >> 1) & 0x5555); @@ -4559,6 +4552,8 @@ if (isIntegral!T) { assert(countBitsSet(T.max) == 8 * T.sizeof); } + // Check CTFE compiles. + static assert(countBitsSet(cast(T) 1) == 1); } assert(countBitsSet(1_000_000) == 7); foreach (i; 0 .. 63) From 0c376b40c4bd0b359a6e54c2c63ccb0ff7ee46bc Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Fri, 24 May 2019 03:01:38 -0400 Subject: [PATCH 57/77] `const`ify scalar arguments in std.bitmanip to reduce IFTI template bloat Fixes Issue 19899 - std.bitmanip.bitsSet should accept const arguments This also makes `swapEndian` not propagate `const` to its return value which is arguably an improvement (see https://github.com/dlang/phobos/pull/6682#discussion_r213024113). --- std/bitmanip.d | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/std/bitmanip.d b/std/bitmanip.d index 0abbeca7787..4ff0d0a5335 100644 --- a/std/bitmanip.d +++ b/std/bitmanip.d @@ -2721,7 +2721,7 @@ public: /++ Swaps the endianness of the given integral value or character. +/ -T swapEndian(T)(T val) @safe pure nothrow @nogc +T swapEndian(T)(const T val) @safe pure nothrow @nogc if (isIntegral!T || isSomeChar!T || isBoolean!T) { static if (val.sizeof == 1) @@ -2891,7 +2891,7 @@ if (__traits(isIntegral, T)) and therefore could vary from machine to machine (which could make it unusable if you tried to transfer it to another machine). +/ -auto nativeToBigEndian(T)(T val) @safe pure nothrow @nogc +auto nativeToBigEndian(T)(const T val) @safe pure nothrow @nogc if (canSwapEndianness!T) { return nativeToBigEndianImpl(val); @@ -3093,7 +3093,7 @@ if (isFloatOrDouble!T && n == T.sizeof) because the FPU will mess up any swapped floating point values. So, you can't actually have swapped floating point values as floating point values). +/ -auto nativeToLittleEndian(T)(T val) @safe pure nothrow @nogc +auto nativeToLittleEndian(T)(const T val) @safe pure nothrow @nogc if (canSwapEndianness!T) { return nativeToLittleEndianImpl(val); @@ -3923,7 +3923,7 @@ if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const ubyte)) index = The index to start writing to. If index is a pointer, then it is updated to the index after the bytes read. +/ -void write(T, Endian endianness = Endian.bigEndian, R)(R range, T value, size_t index) +void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t index) if (canSwapEndianness!T && isForwardRange!R && hasSlicing!R && @@ -3933,7 +3933,7 @@ if (canSwapEndianness!T && } /++ Ditto +/ -void write(T, Endian endianness = Endian.bigEndian, R)(R range, T value, size_t* index) +void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t* index) if (canSwapEndianness!T && isForwardRange!R && hasSlicing!R && @@ -4276,7 +4276,7 @@ if (canSwapEndianness!T && range = The range to _append to. value = The value to _append. +/ -void append(T, Endian endianness = Endian.bigEndian, R)(R range, T value) +void append(T, Endian endianness = Endian.bigEndian, R)(R range, const T value) if (canSwapEndianness!T && isOutputRange!(R, ubyte)) { static if (endianness == Endian.bigEndian) @@ -4489,7 +4489,7 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte)) Counts the number of set bits in the binary representation of `value`. For signed integers, the sign bit is included in the count. */ -private uint countBitsSet(T)(T value) @nogc pure nothrow +private uint countBitsSet(T)(const T value) @nogc pure nothrow if (isIntegral!T) { // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel @@ -4628,7 +4628,7 @@ Range that iterates the indices of the set bits in `value`. Index 0 corresponds to the least significant bit. For signed integers, the highest index corresponds to the sign bit. */ -auto bitsSet(T)(T value) @nogc pure nothrow +auto bitsSet(T)(const T value) @nogc pure nothrow if (isIntegral!T) { return BitsSet!T(value); From 09b847e1f2daefff0b2a40bda89b571c033aba19 Mon Sep 17 00:00:00 2001 From: dukc Date: Fri, 24 May 2019 11:03:09 +0300 Subject: [PATCH 58/77] Link to ascii table --- std/ascii.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/ascii.d b/std/ascii.d index 847466e63f7..68efb192796 100644 --- a/std/ascii.d +++ b/std/ascii.d @@ -104,7 +104,7 @@ enum LetterCase : bool } /++ - All the control characters in ASCII table + All the control characters in ASCII table. Source: http://www.asciitable.com/ +/ enum ControlChar : char { From e962cc7ec558e2cd097756e585f3edc06db9bcbf Mon Sep 17 00:00:00 2001 From: shove Date: Fri, 24 May 2019 19:55:56 +0800 Subject: [PATCH 59/77] Add powmod() for BigInt operands. --- std/bigint.d | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/std/bigint.d b/std/bigint.d index 33e06100af5..e4364f48c3f 100644 --- a/std/bigint.d +++ b/std/bigint.d @@ -1926,3 +1926,41 @@ void divMod(const BigInt dividend, const BigInt divisor, out BigInt quotient, ou { auto n = BigInt("1234"d); } + +/** +Fast power modulus calculation for $(LREF BigInt) operands. +Params: + base = the $(LREF BigInt) is basic operands. + exponent = the $(LREF BigInt) is power exponent of base. + modulus = the $(LREF BigInt) is modules to be modular of base ^ exponent. +Returns: + The power modulus value of (base ^ exponent) % modulus. +*/ +BigInt powmod(BigInt base, BigInt exponent, BigInt modulus) pure nothrow +{ + BigInt result = 1; + + while (exponent) + { + if (exponent & 1) + { + result = (result * base) % modulus; + } + + base = ((base % modulus) * (base % modulus)) % modulus; + exponent >>= 1; + } + + return result; +} + +/// for powmod +@system unittest +{ + BigInt base = BigInt("123456789012345678901234567890"); + BigInt exponent = BigInt("1234567890123456789012345678901234567"); + BigInt modulus = BigInt("1234567"); + + BigInt result = powmod(base, exponent, modulus); + assert(result == 359079); +} From 3fbe0233e389481f8493d4ed8975332744ed8f25 Mon Sep 17 00:00:00 2001 From: Robert Schadek Date: Fri, 24 May 2019 14:38:06 +0100 Subject: [PATCH 60/77] assert messages for std.getopt --- std/getopt.d | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/std/getopt.d b/std/getopt.d index adfcf4cff22..eb29e981a31 100644 --- a/std/getopt.d +++ b/std/getopt.d @@ -911,13 +911,17 @@ private bool handleOption(R)(string option, R receiver, ref string[] args, } else static if (is(typeof(receiver("")) : void)) { - static assert(is(typeof(receiver("")) : void)); + alias RType = typeof(receiver("")); + static assert(is(RType : void), + "Invalid receiver return type " ~ RType.stringof); // boolean-style receiver receiver(option); } else { - static assert(is(typeof(receiver()) : void)); + alias RType = typeof(receiver()); + static assert(is(RType : void), + "Invalid receiver return type " ~ RType.stringof); // boolean-style receiver without argument receiver(); } From f3244d58c1b2f54cb54d8e18fe713db5b4efdbe4 Mon Sep 17 00:00:00 2001 From: Robert Schadek Date: Fri, 24 May 2019 12:18:06 +0100 Subject: [PATCH 61/77] assert messages for std.string starting to work on dlang/phobos/project/2 --- std/string.d | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/std/string.d b/std/string.d index d6170dfc592..5090c6ea832 100644 --- a/std/string.d +++ b/std/string.d @@ -316,8 +316,10 @@ out (result) { auto slen = s.length; while (slen > 0 && s[slen-1] == 0) --slen; - assert(strlen(result) == slen); - assert(result[0 .. slen] == s[0 .. slen]); + assert(strlen(result) == slen, + "The result c string is shorter than the in input string"); + assert(result[0 .. slen] == s[0 .. slen], + "The input and result string are not equal"); } } do @@ -2800,7 +2802,7 @@ public: { if (iStart == _unComputed) { - assert(!empty); + assert(!empty, "Can not popFront an empty range"); front; } iStart = _unComputed; @@ -4306,7 +4308,7 @@ if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) && { // Replace _width with nfill // (use alias instead of union because CTFE cannot deal with unions) - assert(_width); + assert(_width, "width of 0 not allowed"); static if (hasLength!Range) { immutable len = _input.length; @@ -4370,7 +4372,7 @@ if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) && return Result(r, width, fillChar); } else - static assert(0); + static assert(0, "Invalid character type of " ~ C.stringof); } /// @@ -4891,7 +4893,7 @@ if (isForwardRange!Range && !isConvertibleToString!Range) import std.uni : lineSep, paraSep, nelSep; import std.utf : codeUnitLimit, decodeFront; - assert(tabSize > 0); + assert(tabSize > 0, "tabSize must be greater than 0"); alias C = Unqual!(ElementEncodingType!Range); static struct Result @@ -4979,7 +4981,8 @@ if (isForwardRange!Range && !isConvertibleToString!Range) { while (1) { - assert(_input.length); + assert(_input.length, "input did not contain non " + ~ "whitespace character"); cx = _input[0]; if (cx == ' ') ++column; @@ -4994,7 +4997,8 @@ if (isForwardRange!Range && !isConvertibleToString!Range) { while (1) { - assert(!_input.empty); + assert(_input.length, "input did not contain non " + ~ "whitespace character"); cx = _input.front; if (cx == ' ') ++column; @@ -5481,7 +5485,9 @@ C[] translate(C = immutable char)(scope const(char)[] str, scope const(char)[] t if (is(Unqual!C == char)) in { - assert(transTable.length == 256); + import std.conv : to; + assert(transTable.length == 256, "transTable had invalid length of " ~ + to!string(transTable.length)); } do { @@ -5552,12 +5558,14 @@ char[256] makeTransTable(scope const(char)[] from, scope const(char)[] to) @safe in { import std.ascii : isASCII; - assert(from.length == to.length); - assert(from.length <= 256); + assert(from.length == to.length, "from.length must match to.length"); + assert(from.length <= 256, "from.length must be <= 256"); foreach (char c; from) - assert(isASCII(c)); + assert(isASCII(c), + "all characters in from must be valid ascii character"); foreach (char c; to) - assert(isASCII(c)); + assert(isASCII(c), + "all characters in to must be valid ascii character"); } do { @@ -5635,7 +5643,8 @@ void translate(C = immutable char, Buffer)(scope const(char)[] str, scope const( if (is(Unqual!C == char) && isOutputRange!(Buffer, char)) in { - assert(transTable.length == 256); + assert(transTable.length == 256, format! + "transTable.length %s must equal 256"(transTable.length)); } do { @@ -6074,7 +6083,8 @@ C1[] tr(C1, C2, C3, C4 = immutable char) case 'c': mod_c = 1; break; // complement case 'd': mod_d = 1; break; // delete unreplaced chars case 's': mod_s = 1; break; // squeeze duplicated replaced chars - default: assert(0); + default: assert(false, "modifier must be one of ['c', 'd', 's'] not " + ~ c); } } @@ -6157,7 +6167,7 @@ C1[] tr(C1, C2, C3, C4 = immutable char) if (mod_s && modified && newc == lastc) continue; result.put(newc); - assert(newc != dchar.init); + assert(newc != dchar.init, "character must not be dchar.init"); modified = true; lastc = newc; continue; @@ -6686,10 +6696,12 @@ out (result) { if (result !is null) { - assert(result.length == 4); - assert(result[0] >= 'A' && result[0] <= 'Z'); + assert(result.length == 4, "Result must have length of 4"); + assert(result[0] >= 'A' && result[0] <= 'Z', "The first character of " + ~ " the result must be an upper character not " ~ result); foreach (char c; result[1 .. 4]) - assert(c >= '0' && c <= '6'); + assert(c >= '0' && c <= '6', "the last three character of the" + ~ " result must be number between 0 and 6 not " ~ result); } } do From 72d4cc7345f78679457700ffcc6f0ba585e7ecfc Mon Sep 17 00:00:00 2001 From: Robert Schadek Date: Fri, 24 May 2019 13:01:33 +0100 Subject: [PATCH 62/77] assert messages for std.array more work on starting to work on dlang/phobos/project/2 --- std/array.d | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/std/array.d b/std/array.d index dfb4f76c5a7..a8518562606 100644 --- a/std/array.d +++ b/std/array.d @@ -478,7 +478,7 @@ if (isInputRange!Values && isInputRange!Keys) ValueElement.init.__xdtor(); }))) { - scope(failure) assert(0); + scope(failure) assert(false, "aaLiteral must not throw"); } if (values.length > keys.length) values = values[0 .. keys.length]; @@ -911,7 +911,8 @@ private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow static if (I.length != 0) { - static assert(is(I[0] == size_t)); + static assert(is(I[0] == size_t), "I[0] must be of type size_t not " + ~ I[0].stringof); alias size = sizes[0]; } @@ -1152,8 +1153,10 @@ if (is(typeof(a.ptr < b.ptr) == bool)) private void copyBackwards(T)(T[] src, T[] dest) { import core.stdc.string : memmove; + import std.format : format; - assert(src.length == dest.length); + assert(src.length == dest.length, format! + "src.length %s must equal dest.length %s"(src.length, dest.length)); if (!__ctfe || hasElaborateCopyConstructor!T) { @@ -1292,7 +1295,8 @@ if (isSomeString!(T[]) && allSatisfy!(isCharOrStringOrDcharRange, U)) @trusted static void moveToRight(T[] arr, size_t gap) { - static assert(!hasElaborateCopyConstructor!T); + static assert(!hasElaborateCopyConstructor!T, + "T must not have an elaborate copy constructor"); import core.stdc.string : memmove; if (__ctfe) { @@ -2020,6 +2024,7 @@ if (isInputRange!RoR && else { import std.conv : emplaceRef; + import std.format : format; size_t length; size_t rorLength; foreach (r; ror.save) @@ -2043,7 +2048,8 @@ if (isInputRange!RoR && foreach (e; r) emplaceRef(result[len++], e); } - assert(len == result.length); + assert(len == result.length, format! + "len %s must equal result.lenght %s"(len, result.length)); return (() @trusted => cast(RetType) result)(); } } @@ -2114,7 +2120,8 @@ if (isInputRange!RoR && foreach (r; ror) foreach (e; r) emplaceRef!RetTypeElement(result[len++], e); - assert(len == result.length); + assert(len == result.length, + "emplaced an unexpected number of elements"); return (() @trusted => cast(RetType) result)(); } else @@ -2586,7 +2593,7 @@ if (isInputRange!Range && static if (hasLength!Range && is(ElementEncodingType!Range : T)) { import std.algorithm.mutation : copy; - assert(from <= to); + assert(from <= to, "from must be before or equal to to"); immutable sliceLen = to - from; auto retval = new Unqual!(T)[](subject.length - sliceLen + stuff.length); retval[0 .. from] = subject[0 .. from]; @@ -3137,7 +3144,7 @@ inout(T)[] replaceSlice(T)(inout(T)[] s, in T[] slice, in T[] replacement) in { // Verify that slice[] really is a slice of s[] - assert(overlap(s, slice) is slice); + assert(overlap(s, slice) is slice, "slice[] is not a subslice of s[]"); } do { @@ -3325,7 +3332,8 @@ if (isDynamicArray!A) import core.checkedint : mulu; bool overflow; const nbytes = mulu(newlen, T.sizeof, overflow); - if (overflow) assert(0); + if (overflow) assert(false, "the reallocation would exceed the " + ~ "available pointer range"); auto bi = (() @trusted => GC.qalloc(nbytes, blockAttribute!T))(); _data.capacity = bi.size / T.sizeof; @@ -4588,5 +4596,5 @@ nothrow pure @safe unittest version (unittest) private void checkStaticArray(T, T1, T2)(T1 a, T2 b) nothrow @safe pure @nogc { static assert(is(T1 == T[T1.length])); - assert(a == b); + assert(a == b, "a must be equal to b"); } From 40ba89b7f4bc8b5fe5113138245d9764ccda6ff7 Mon Sep 17 00:00:00 2001 From: Flying-Toast <38232168+Flying-Toast@users.noreply.github.com> Date: Sat, 25 May 2019 09:50:32 -0400 Subject: [PATCH 63/77] add messages to some asserts in std/socket.d --- std/socket.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/std/socket.d b/std/socket.d index 20962fbd647..c1bddb63550 100644 --- a/std/socket.d +++ b/std/socket.d @@ -117,7 +117,7 @@ else version (Posix) } else { - static assert(0); // No socket support yet. + static assert(0, "No socket support for this platform yet."); } version (unittest) @@ -268,7 +268,7 @@ bool wouldHaveBlocked() nothrow @nogc else version (Posix) return _lasterr() == EAGAIN; else - static assert(0); + static assert(0, "No socket support for this platform yet."); } @@ -1561,7 +1561,7 @@ public: */ this(sockaddr_in addr) pure nothrow @nogc { - assert(addr.sin_family == AddressFamily.INET); + assert(addr.sin_family == AddressFamily.INET, "Socket address is not of INET family."); sin = addr; } From 859dc49859411aa7aa27991472b84e26e83e5736 Mon Sep 17 00:00:00 2001 From: Diederik de Groot Date: Sat, 25 May 2019 23:58:17 +0200 Subject: [PATCH 64/77] brk support has been removed from DragonFlyBSD sbrk has been declared deprecated mmap() is suggested as a replacement for sbrk() --- .../allocator/building_blocks/region.d | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/std/experimental/allocator/building_blocks/region.d b/std/experimental/allocator/building_blocks/region.d index bac7cba140f..77ded986aa7 100644 --- a/std/experimental/allocator/building_blocks/region.d +++ b/std/experimental/allocator/building_blocks/region.d @@ -717,6 +717,15 @@ version (CRuntime_Musl) // https://git.musl-libc.org/cgit/musl/commit/?id=7a995fe706e519a4f55399776ef0df9596101f93 // https://git.musl-libc.org/cgit/musl/commit/?id=863d628d93ea341b6a32661a1654320ce69f6a07 } +version (DragonFlyBSD) +{ + // sbrk is deprecated in favor of mmap (we could implement a mmap + MAP_NORESERVE + PROT_NONE version) + // brk has been removed + // https://www.dragonflydigest.com/2019/02/22/22586.html + // http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/dc676eaefa61b0f47bbea1c53eab86fd5ccd78c6 + // http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/4b5665564ef37dc939a3a9ffbafaab9894c18885 + // http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/8618d94a0e2ff8303ad93c123a3fa598c26a116e +} else { private extern(C) void* sbrk(long) nothrow @nogc; @@ -734,11 +743,13 @@ SbrkRegion) adversely. */ version (CRuntime_Musl) {} else +version (DragonFlyBSD) {} else version (Posix) struct SbrkRegion(uint minAlign = platformAlignment) { import core.sys.posix.pthread : pthread_mutex_init, pthread_mutex_destroy, pthread_mutex_t, pthread_mutex_lock, pthread_mutex_unlock, - PTHREAD_MUTEX_INITIALIZER; + + PTHREAD_MUTEX_INITIALIZER; private static shared pthread_mutex_t sbrkMutex = PTHREAD_MUTEX_INITIALIZER; import std.typecons : Ternary; @@ -915,6 +926,7 @@ version (Posix) struct SbrkRegion(uint minAlign = platformAlignment) } version (CRuntime_Musl) {} else +version (DragonFlyBSD) {} else version (Posix) @system nothrow @nogc unittest { // Let's test the assumption that sbrk(n) returns the old address @@ -928,6 +940,7 @@ version (Posix) @system nothrow @nogc unittest } version (CRuntime_Musl) {} else +version (DragonFlyBSD) {} else version (Posix) @system nothrow @nogc unittest { import std.typecons : Ternary; From 6a6dff40047322184ad83e3f600d28ef28ed5e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D8=B3=D9=84=D9=8A=D9=85=D8=A7=D9=86=20=D8=A7=D9=84=D8=B3?= =?UTF-8?q?=D9=87=D9=85=D9=8A=20=20=28Suleyman=20Sahmi=29?= Date: Sun, 26 May 2019 02:17:07 +0000 Subject: [PATCH 65/77] Ternary operator doesn't promote characters to integers anymore --- std/range/package.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/range/package.d b/std/range/package.d index 19f33da4735..94e3757ff40 100644 --- a/std/range/package.d +++ b/std/range/package.d @@ -1274,8 +1274,8 @@ pure @safe nothrow unittest auto s3 = "string three".byCodeUnit; static assert(is(typeof(s3.front) == immutable char)); auto r2 = s1.chain(s3); - // type is promoted - static assert(is(typeof(r2.front) == uint)); + //// chaining ranges of mixed character types gives `dchar` + //static assert(is(typeof(r2.front) == dchar)); // use byChar on character ranges to correctly convert them to UTF-8 auto r3 = s1.byChar.chain(s3); From 55328d6ef505338449be01b264b3aaa2388fb7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D8=B3=D9=84=D9=8A=D9=85=D8=A7=D9=86=20=D8=A7=D9=84=D8=B3?= =?UTF-8?q?=D9=87=D9=85=D9=8A=20=20=28Suleyman=20Sahmi=29?= Date: Sun, 26 May 2019 02:17:07 +0000 Subject: [PATCH 66/77] Ternary operator doesn't promote characters to integers anymore --- std/range/package.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/range/package.d b/std/range/package.d index 94e3757ff40..00771b7fe0a 100644 --- a/std/range/package.d +++ b/std/range/package.d @@ -1274,8 +1274,8 @@ pure @safe nothrow unittest auto s3 = "string three".byCodeUnit; static assert(is(typeof(s3.front) == immutable char)); auto r2 = s1.chain(s3); - //// chaining ranges of mixed character types gives `dchar` - //static assert(is(typeof(r2.front) == dchar)); + // chaining ranges of mixed character types gives `dchar` + static assert(is(typeof(r2.front) == dchar)); // use byChar on character ranges to correctly convert them to UTF-8 auto r3 = s1.byChar.chain(s3); From 332cf5b1f32c73b149a375fc963689d6c860d8d1 Mon Sep 17 00:00:00 2001 From: dukc Date: Mon, 27 May 2019 14:44:27 +0300 Subject: [PATCH 67/77] ControlChar member typos: sI -> si, sO -> so --- std/ascii.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/ascii.d b/std/ascii.d index 68efb192796..4db971d4614 100644 --- a/std/ascii.d +++ b/std/ascii.d @@ -122,8 +122,8 @@ enum ControlChar : char vt = '\x0B', /// Vertical tab ff = '\x0C', /// NP form feed, new page cr = '\x0D', /// Carriage return - sO = '\x0E', /// Shift out - sI = '\x0F', /// Shift in + so = '\x0E', /// Shift out + si = '\x0F', /// Shift in dle = '\x10', /// Data link escape dc1 = '\x11', /// Device control 1 dc2 = '\x12', /// Device control 2 From fb2b57b284bf03ff70b87ad0f2754e71fd2e7c8d Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Mon, 27 May 2019 11:35:26 -0400 Subject: [PATCH 68/77] [TRIVIAL] Make link clickable and safe (#7045) [TRIVIAL] Make link clickable and safe merged-on-behalf-of: Nicholas Wilson --- std/ascii.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/ascii.d b/std/ascii.d index 4db971d4614..785cbfab43f 100644 --- a/std/ascii.d +++ b/std/ascii.d @@ -104,7 +104,7 @@ enum LetterCase : bool } /++ - All the control characters in ASCII table. Source: http://www.asciitable.com/ + All control characters in the ASCII table ($(HTTPS www.asciitable.com, source)). +/ enum ControlChar : char { From 001bfe78dc37b8eb331af30c1439289f5d3f6902 Mon Sep 17 00:00:00 2001 From: Robert Schadek Date: Fri, 24 May 2019 15:00:09 +0100 Subject: [PATCH 69/77] std.csv assert messages --- std/csv.d | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/std/csv.d b/std/csv.d index 4ac14462b9c..f29c80e3e94 100644 --- a/std/csv.d +++ b/std/csv.d @@ -989,7 +989,7 @@ public: */ @property auto front() { - assert(!empty); + assert(!empty, "Attempting to fetch the front of an empty CsvReader"); static if (is(Contents == struct) || is(Contents == class)) { return recordContent; @@ -1224,7 +1224,7 @@ public: */ @property Contents front() @safe pure { - assert(!empty); + assert(!empty, "Attempting to fetch the front of an empty CsvRecord"); return curContentsoken; } @@ -1425,7 +1425,8 @@ if (isSomeChar!Separator && isInputRange!Range while (!input.empty) { - assert(!(quoted && escQuote)); + assert(!(quoted && escQuote), + "Invalid quotation state in csvNextToken"); if (!quoted) { // When not quoted the token ends at sep From e0299a41c8a002279cadaf29ce964a72c32c11b6 Mon Sep 17 00:00:00 2001 From: Robert Schadek Date: Tue, 28 May 2019 10:22:27 +0100 Subject: [PATCH 70/77] assert messages for std.format --- std/format.d | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/std/format.d b/std/format.d index 153b0756669..ba7abe264ce 100644 --- a/std/format.d +++ b/std/format.d @@ -503,7 +503,7 @@ uint formattedWrite(Writer, Char, A...)(auto ref Writer w, const scope Char[] fm { // means: get width as a positional parameter auto index = cast(uint) -spec.width; - assert(index > 0); + assert(index > 0, "The index must be greater than zero"); auto width = getNthInt!"integer width"(index - 1, args); if (currentArg < index) currentArg = index; if (width < 0) @@ -526,7 +526,7 @@ uint formattedWrite(Writer, Char, A...)(auto ref Writer w, const scope Char[] fm { // means: get precision as a positional parameter auto index = cast(uint) -spec.precision; - assert(index > 0); + assert(index > 0, "The precision must be greater than zero"); auto precision = getNthInt!"integer precision"(index- 1, args); if (currentArg < index) currentArg = index; if (precision >= 0) spec.precision = precision; @@ -1506,7 +1506,7 @@ if (is(Unqual!Char == Char)) const c2 = trailing[1]; if (c2 == '%') { - assert(!r.empty); + assert(!r.empty, "Required at least one more input"); // Require a '%' if (r.front != '%') break; trailing = trailing[2 .. $]; @@ -2995,7 +2995,7 @@ if (is(DynamicArrayTypeOf!T) && !is(StringTypeOf!T) && !is(T == enum) && !hasToS else static if (!isInputRange!T) { alias U = Unqual!(ArrayTypeOf!T); - static assert(isInputRange!U); + static assert(isInputRange!U, U.stringof ~ " must be an InputRange"); U val = obj; formatValueImpl(w, val, f); } @@ -3853,7 +3853,7 @@ if (hasToString!(T, Char)) } else { - static assert(0); + static assert(0, "No way found to format " ~ T.stringof ~ " as string"); } } @@ -4368,7 +4368,8 @@ if (is(T == enum)) // val is not a member of T, output cast(T) rawValue instead. put(w, "cast(" ~ T.stringof ~ ")"); - static assert(!is(OriginalType!T == T)); + static assert(!is(OriginalType!T == T), "OriginalType!" ~ T.stringof ~ + "must not be equal to " ~ T.stringof); } formatValueImpl(w, cast(OriginalType!T) val, f); } @@ -5552,7 +5553,7 @@ if (isInputRange!Range && isIntegral!T && !is(T == enum) && isSomeChar!(ElementT spec.spec == 'o' ? 8 : spec.spec == 'b' ? 2 : spec.spec == 's' || spec.spec == 'd' || spec.spec == 'u' ? 10 : 0; - assert(base != 0); + assert(base != 0, "base must be not equal to zero"); return parse!T(input, base); @@ -5606,7 +5607,8 @@ if (isInputRange!Range && isSomeChar!T && !is(T == enum) && isSomeChar!(ElementT else static if (T.sizeof == 4) return unformatValue!uint(input, spec); else - static assert(0); + static assert(false, T.stringof ~ ".sizeof must be 1, 2, or 4 not " ~ + to!string(T.sizeof)); } /// ditto @@ -5732,7 +5734,8 @@ if (is(Unqual!(ElementEncodingType!Range) == char) private T unformatRange(T, Range, Char)(ref Range input, scope const ref FormatSpec!Char spec) in { - assert(spec.spec == '('); + const char ss = spec.spec; + assert(ss == '(', "spec.spec must be '(' not " ~ ss); } do { From d25706d30dddf509eb73749a06a63eafdf62fe2d Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Thu, 30 May 2019 20:33:13 -0600 Subject: [PATCH 71/77] Explicitly link to math library --- posix.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posix.mak b/posix.mak index eeea3c772dc..b2fac6b370e 100644 --- a/posix.mak +++ b/posix.mak @@ -112,7 +112,7 @@ OUTFILEFLAG = -o NODEFAULTLIB=-defaultlib= -debuglib= ifeq (,$(findstring win,$(OS))) CFLAGS=$(MODEL_FLAG) -fPIC -DHAVE_UNISTD_H - NODEFAULTLIB += -L-lpthread + NODEFAULTLIB += -L-lpthread -L-lm ifeq ($(BUILD),debug) CFLAGS += -g else From 887294b45078c5a2f8454b3db6e5b90c2c781d6e Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Tue, 4 Jun 2019 20:20:00 +0200 Subject: [PATCH 72/77] Add a sponsorship button --- .github/FUNDING.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000000..a5b705fde13 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository + +open_collective: dlang +custom: https://dlang.org/foundation/donate.html From 3ca8d026b71062df0fb6da50a020108f02bf6475 Mon Sep 17 00:00:00 2001 From: JinShil Date: Wed, 5 Jun 2019 22:04:56 +0900 Subject: [PATCH 73/77] std.process.forkChild cannot be inlined --- std/process.d | 1 - 1 file changed, 1 deletion(-) diff --git a/std/process.d b/std/process.d index 690f3a61fa2..e549896be64 100644 --- a/std/process.d +++ b/std/process.d @@ -468,7 +468,6 @@ private Pid spawnProcessImpl(scope const(char[])[] args, void forkChild() nothrow @nogc { static import core.sys.posix.stdio; - pragma(inline, true); // Child process From 613c0b1f725b7e19295bca0bac9122cc311413de Mon Sep 17 00:00:00 2001 From: Marco de Wild Date: Thu, 6 Jun 2019 10:51:10 +0200 Subject: [PATCH 74/77] fix Issue 11061 - Variant of an array can be compared with another array Fixes 11061 --- std/variant.d | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/std/variant.d b/std/variant.d index 4edc9443ad0..8513ed03732 100644 --- a/std/variant.d +++ b/std/variant.d @@ -285,7 +285,14 @@ private: static bool tryPutting(A* src, TypeInfo targetType, void* target) { alias UA = Unqual!A; - alias MutaTypes = AliasSeq!(UA, ImplicitConversionTargets!UA); + static if (isStaticArray!A && is(typeof(UA.init[0]))) + { + alias MutaTypes = AliasSeq!(UA, typeof(UA.init[0])[], ImplicitConversionTargets!UA); + } + else + { + alias MutaTypes = AliasSeq!(UA, ImplicitConversionTargets!UA); + } alias ConstTypes = staticMap!(ConstOf, MutaTypes); alias SharedTypes = staticMap!(SharedOf, MutaTypes); alias SharedConstTypes = staticMap!(SharedConstOf, MutaTypes); @@ -334,7 +341,15 @@ private: static if (T.sizeof > 0) assert(target, "target must be non-null"); - emplaceRef(*cast(Unqual!T*) zat, *cast(UA*) src); + static if (isStaticArray!A && isDynamicArray!T) + { + auto this_ = (*src)[]; + emplaceRef(*cast(Unqual!T*) zat, cast(Unqual!T) this_); + } + else + { + emplaceRef(*cast(Unqual!T*) zat, *cast(UA*) src); + } } } else @@ -624,7 +639,6 @@ public: VariantN opAssign(T)(T rhs) { - //writeln(typeid(rhs)); static assert(allowed!(T), "Cannot store a " ~ T.stringof ~ " in a " ~ VariantN.stringof ~ ". Valid types are " ~ AllowedTypes.stringof); @@ -3005,3 +3019,33 @@ if (isAlgebraic!VariantType && Handler.length > 0) auto b = v | s; assert(b == 3); } + +@system unittest +{ + // Bugzilla 11061 + int[4] el = [0, 1, 2, 3]; + int[3] nl = [0, 1, 2]; + Variant v1 = el; + assert(v1 == el); // Compare Var(static) to static + assert(v1 != nl); // Compare static arrays of different length + assert(v1 == [0, 1, 2, 3]); // Compare Var(static) to dynamic. + assert(v1 != [0, 1, 2]); + int[] dyn = [0, 1, 2, 3]; + v1 = dyn; + assert(v1 == el); // Compare Var(dynamic) to static. + assert(v1 == [0, 1] ~ [2, 3]); // Compare Var(dynamic) to dynamic +} + +@system unittest +{ + // Test if we don't have scoping issues. + Variant createVariant(int[] input) + { + int[2] el = [input[0], input[1]]; + Variant v = el; + return v; + } + Variant v = createVariant([0, 1]); + createVariant([2, 3]); + assert(v == [0,1]); +} From e5bae1d8394c84ea66d405cef30108ea215957d7 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Tue, 4 Jun 2019 20:38:43 -0400 Subject: [PATCH 75/77] Add `inout` to std.range.front to reduce template proliferation The Win32_64 linker error that prevented this from being included in PR #6743 no longer occurs in CI. --- std/range/primitives.d | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/std/range/primitives.d b/std/range/primitives.d index d2d391d1b3e..1dff0522f94 100644 --- a/std/range/primitives.d +++ b/std/range/primitives.d @@ -2419,15 +2419,8 @@ equivalent to `front(array)`. For $(GLOSSARY narrow strings), $(D front) automatically returns the first $(GLOSSARY code point) as _a $(D dchar). */ -@property ref T front(T)(return scope T[] a) @safe pure nothrow @nogc +@property ref inout(T) front(T)(return scope inout(T)[] a) @safe pure nothrow @nogc if (!(autodecodeStrings && isNarrowString!(T[])) && !is(T[] == void[])) -// We would have preferred to write the function template -// --- -// @property ref inout(T) front(T)(return scope inout(T)[] a) -// if (/* same constraint */) -// --- -// as that would cause fewer distinct functions to be generated with -// IFTI, but that caused a linker error in the test suite on Win32_64. { assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof); return a[0]; From b1413e3cde56cecb6e444f0b60554fca258eff71 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Tue, 11 Jun 2019 09:51:32 +0800 Subject: [PATCH 76/77] function attributes go on the right of function aliases FuncType is actually `@system` because of this, for some reason it is still `pure` and `nothrow`. --- std/datetime/timezone.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/datetime/timezone.d b/std/datetime/timezone.d index c5d4b3333aa..90fdebeb892 100644 --- a/std/datetime/timezone.d +++ b/std/datetime/timezone.d @@ -532,7 +532,7 @@ public: +/ static immutable(LocalTime) opCall() @trusted pure nothrow { - alias FuncType = @safe pure nothrow immutable(LocalTime) function(); + alias FuncType = immutable(LocalTime) function() @safe pure nothrow; return (cast(FuncType)&singleton)(); } From 249853bda47733ca7b895f06c00f1448dc5f95ae Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 11 Jun 2019 16:57:27 +0100 Subject: [PATCH 77/77] [docs][std.range.primitives] Add links to array range primitives It's important to mention this, particularly so the user notices the auto-decoding overloads. --- std/range/primitives.d | 3 +++ 1 file changed, 3 insertions(+) diff --git a/std/range/primitives.d b/std/range/primitives.d index d2d391d1b3e..28172031bdf 100644 --- a/std/range/primitives.d +++ b/std/range/primitives.d @@ -1,6 +1,9 @@ /** This module is a submodule of $(MREF std, range). +It defines the bidirectional and forward range primitives for arrays: +$(LREF empty), $(LREF front), $(LREF back), $(LREF popFront), $(LREF popBack) and $(LREF save). + It provides basic range functionality by defining several templates for testing whether a given object is a range, and what kind of range it is: