Hello community, here is the log from the commit of package dmd for openSUSE:Factory checked in at 2019-04-14 12:23:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/dmd (Old) and /work/SRC/openSUSE:Factory/.dmd.new.27019 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dmd" Sun Apr 14 12:23:33 2019 rev:25 rq:693900 version:2.085.1 Changes: -------- --- /work/SRC/openSUSE:Factory/dmd/dmd.changes 2019-03-18 10:43:47.735117836 +0100 +++ /work/SRC/openSUSE:Factory/.dmd.new.27019/dmd.changes 2019-04-14 12:23:35.131840046 +0200 @@ -1,0 +2,33 @@ +Sat Apr 13 10:01:13 UTC 2019 - Matthias Eliasson <[email protected]> + +- Update to version 2.085.1 + - DMD Compiler regressions: + * DMD generates wrong code for some circular dependencies + * D compiler fails to resolve circular module dependency when modules are compiled separately + * D compiler fails to resolve circular module dependency when modules are compiled together + * ICE on null default value for struct parameter in constructor + * DMD 2.085 changes to gsroa make DCD crashing + * Regression: wrong order of linker arguments, again: -L-l before -L--start-group + * if (auto x) {} isn't properly rejected + * DMD fails to compile some circular dependencies spiced with is (T == super) condition + * [Reg v2.070.2] DMD fails with some circular module refs with Template/Mixin instances + - DMD Compiler bugs: + * wrong codegen for destructor call of unnamed struct instance on 64 bit environments + * case of undetected circular reference in function parameter + * ICE with multiple mixin templates containing conflicting ctor declarations + * Segfault when types are used in array literals + * DMD crash due to circular reference in function return type + * -checkaction=context not working with attributes + * [2.085.0-beta.2] Obj-C wrong code overloading selectors and extern(D) + * case of segfault due to undetected forward reference + * Compiler crash + * crash on invalid initializer at CTFE + * ICE on invalid code + - Phobos regressions: + * VariantN has unittests that are compiled into user modules + - Phobos bugs: + * std.algorithm.searching.findAmong doesn't save like it should + - Druntime bugs: + * wrong time values in GC.profileStats + +------------------------------------------------------------------- Old: ---- dmd-2.085.0.tar.gz druntime-2.085.0.tar.gz phobos-2.085.0.tar.gz New: ---- dmd-2.085.1.tar.gz druntime-2.085.1.tar.gz phobos-2.085.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dmd.spec ++++++ --- /var/tmp/diff_new_pack.oG9woX/_old 2019-04-14 12:23:36.495841317 +0200 +++ /var/tmp/diff_new_pack.oG9woX/_new 2019-04-14 12:23:36.519841339 +0200 @@ -20,7 +20,7 @@ %define sover 0_85 %define auto_bootstrap 1 Name: dmd -Version: 2.085.0 +Version: 2.085.1 Release: 0 Summary: D Programming Language 2.0 License: BSL-1.0 ++++++ dmd-2.085.0.tar.gz -> dmd-2.085.1.tar.gz ++++++ ++++ 1772 lines of diff (skipped) ++++++ druntime-2.085.0.tar.gz -> druntime-2.085.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/.circleci/config.yml new/druntime-2.085.1/.circleci/config.yml --- old/druntime-2.085.0/.circleci/config.yml 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/.circleci/config.yml 2019-03-28 04:39:36.000000000 +0100 @@ -3,8 +3,8 @@ build: working_directory: ~/druntime docker: - - image: circleci/node:4.8.2 - parallelism: 2 + - image: circleci/buildpack-deps:18.04 + parallelism: 1 steps: - checkout - run: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/.circleci/run.sh new/druntime-2.085.1/.circleci/run.sh --- old/druntime-2.085.0/.circleci/run.sh 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/.circleci/run.sh 2019-03-28 04:39:36.000000000 +0100 @@ -10,7 +10,7 @@ case $CIRCLE_NODE_INDEX in 0) MODEL=64 ;; - 1) MODEL=32 ;; + 1) MODEL=32 ;; # broken - https://issues.dlang.org/show_bug.cgi?id=19116 esac download() { @@ -98,8 +98,7 @@ # load environment for bootstrap compiler source "$(CURL_USER_AGENT=\"$CURL_USER_AGENT\" bash ~/dlang/install.sh dmd-$HOST_DMD_VER --activate)" - # build dmd and druntime (in debug and release) - make -j$N -C ../dmd/src -f posix.mak MODEL=$MODEL HOST_DMD=$DMD BUILD="debug" all + # build dmd (release) and druntime (debug) make -j$N -C ../dmd/src -f posix.mak MODEL=$MODEL HOST_DMD=$DMD BUILD="release" all TEST_COVERAGE="1" make -j$N -C . -f posix.mak MODEL=$MODEL unittest-debug } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/core-memory-gc-profile-stats.dd new/druntime-2.085.1/changelog/core-memory-gc-profile-stats.dd --- old/druntime-2.085.0/changelog/core-memory-gc-profile-stats.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/core-memory-gc-profile-stats.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -Added `GC.profileStats()` to `core.memory` - -Allows access to current GC profiling information. -See $(REF GC.ProfileStats, core,memory) for a list of profile stats. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/cpp_new.dd new/druntime-2.085.1/changelog/cpp_new.dd --- old/druntime-2.085.0/changelog/cpp_new.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/cpp_new.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -Added `core.stdcpp.new_` - -Added `core.stdcpp.new_`, which exposes interfaces for C++ global new/delete operators. -This allows D programs to conveniently allocate from the C++ heap, which is useful when sharing memory between languages. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/cpu_count.dd new/druntime-2.085.1/changelog/cpu_count.dd --- old/druntime-2.085.0/changelog/cpu_count.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/cpu_count.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -Added `core.sys.linux.sched.CPU_COUNT`. - -Added `core.sys.linux.sched.CPU_COUNT`, which returns the number of CPUs in set. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/cpu_isset.dd new/druntime-2.085.1/changelog/cpu_isset.dd --- old/druntime-2.085.0/changelog/cpu_isset.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/cpu_isset.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -Added `core.sys.linux.sched.CPU_ISSET`. - -Added `core.sys.linux.sched.CPU_ISSET`, which tests to see if cpu is a member of set. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/emplace.dd new/druntime-2.085.1/changelog/emplace.dd --- old/druntime-2.085.0/changelog/emplace.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/emplace.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -Moved `std.conv.emplace`, `std.algorithm.mutation.move`, `std.algorithm.mutation.moveEmplace`, and `std.functional.forward` to core/lifetime.d - -`emplace` is the counterpart to `destroy`, so it has been moved to also live in druntime (core/lifetime.d) where it is accessible by projects that use a shallow runtime library stack. -`move`, `moveEmplace`, and `forward` are related low-level construction machinery which also belong in `core.lifetime`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/gc_cleanup.dd new/druntime-2.085.1/changelog/gc_cleanup.dd --- old/druntime-2.085.0/changelog/gc_cleanup.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/gc_cleanup.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,26 +0,0 @@ -GC cleanup can now be configured as a DRT GC option - -The default cleanup method for the GC is to unconditionally run a -collection before runtime termination to finalize objects -that are still alive and hold resources that affect system state outside -the current process. This combines the worst of possible alternatives: -it can cause a considerable delay and does not guarantee finalization -of all objects as roots might still exist. - -The cleanup behaviour can now be configured by a DRT option to the -$(LINK2 $(ROOT_DIR)spec/garbage.html, GC configuration), -e.g. by passing `--DRT-gcopt=cleanup:none` on the command -line. Three options are provided: - -$(UL - $(LI collect: run a collection (the default for backward compatibility)) - $(LI none: do nothing) - $(LI finalize: all live objects are finalized unconditionally) -) - -As usual, you can also embed the configuration into the application by -redefining `rt_options`, e.g. - -------- -extern(C) __gshared string[] rt_options = [ "gcopt=cleanup:none" ]; -------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/gc_precise.dd new/druntime-2.085.1/changelog/gc_precise.dd --- old/druntime-2.085.0/changelog/gc_precise.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/gc_precise.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,8 +0,0 @@ -A garbage collector with precise heap scanning can now be selected - -Precise heap scanning can now be enabled by a DRT option to the -$(LINK2 $(ROOT_DIR)spec/garbage.html, GC configuration), -e.g. by passing `--DRT-gcopt=gc:precise` on the command -line or by redefining `rt_options`. See the -$(LINK2 $(ROOT_DIR)spec/garbage.html#precise_gc, documentation) -for details. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/gc_realloc.dd new/druntime-2.085.1/changelog/gc_realloc.dd --- old/druntime-2.085.0/changelog/gc_realloc.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/gc_realloc.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,18 +0,0 @@ -GC.realloc is now more consistent and robust - -The specification of $(REF GC.realloc, core, memory) has changed slightly: - -$(UL - $(LI `GC.realloc` now returns `null` for failure. (It used to return the original pointer but - that is is not a good indication of failure as it might also be returned on success. It can - lead to overwriting memory if an enlargement was requested.)) - $(LI as with `GC.free`, the caller has to ensure that there are no other live pointers to the - memory passed to `GC.realloc` (This used to be required only when passing a new size `0`).) - $(LI as a consequence the GC is allowed to free the memory immediately (the previous - implementation did this for objects larger than 4kB when shrinking).) - $(LI block attribute bits on the existing block are only set if it is reused (the previous - implementation didn't set bits if it reused a small block).) -) - -The implementation now properly verifies that pointers are actually base pointers to allocated -GC memory (passing other pointers could have crashed immediately or corrupt the GC). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/gc_registry.dd new/druntime-2.085.1/changelog/gc_registry.dd --- old/druntime-2.085.0/changelog/gc_registry.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/gc_registry.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -User supplied garbage collectors can now be linked with the runtime - -A GC registry has been implemented that allows to add -garbage collector implementations by just linking them into -the binary. See the -$(LINK2 $(ROOT_DIR)spec/garbage.html#gc_registry, documentation) -for details. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/std_allocator.dd new/druntime-2.085.1/changelog/std_allocator.dd --- old/druntime-2.085.0/changelog/std_allocator.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/std_allocator.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -Added `core.stdcpp.allocator` - -Added `core.stdcpp.allocator`, which exposes the C++ `std::allocator<T>` class. -This is a required foundation for any of the allocating STL container types. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/changelog/zero_init.dd new/druntime-2.085.1/changelog/zero_init.dd --- old/druntime-2.085.0/changelog/zero_init.dd 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/changelog/zero_init.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -`char`/`wchar` fields in most D runtime (`core.*` and `rt.*`) structs are now zero-initialized - -Fields that are single `char`/wchar` or fixed-length arrays of such are now initialized to all zero bits instead of all one bits for most structs in the D runtime (`core.*` and `rt.*` modules). This simplifies initialization and removes the need to store init data when it makes the entire struct zero-initialized. Most affected structs are used for interoperability with C APIs. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/src/core/internal/dassert.d new/druntime-2.085.1/src/core/internal/dassert.d --- old/druntime-2.085.0/src/core/internal/dassert.d 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/src/core/internal/dassert.d 2019-03-28 04:39:36.000000000 +0100 @@ -37,7 +37,7 @@ Minimalistic formatting for use in _d_assert_fail to keep the compilation overhead small and avoid the use of Phobos. */ -auto miniFormat(V)(auto ref V v) +auto miniFormat(V)(V v) { import core.stdc.stdio : sprintf; import core.stdc.string : strlen; @@ -45,14 +45,14 @@ { enum printfFormat = getPrintfFormat!V; char[20] val; - sprintf(val.ptr, printfFormat, v); - return val.idup[0 .. strlen(val.ptr)]; + const len = sprintf(&val[0], printfFormat, v); + return val.idup[0 .. len]; } else static if (__traits(isFloating, V)) { char[60] val; - sprintf(val.ptr, "%g", v); - return val.idup[0 .. strlen(val.ptr)]; + const len = sprintf(&val[0], "%g", v); + return val.idup[0 .. len]; } else static if (__traits(compiles, { string s = V.init.toString(); })) { @@ -145,3 +145,26 @@ } } +private auto assumeFakeAttributes(T)(T t) @trusted +{ + import core.internal.traits : Parameters, ReturnType; + alias RT = ReturnType!T; + alias P = Parameters!T; + alias type = RT function(P) nothrow @nogc @safe pure; + return cast(type) t; +} + +auto miniFormatFakeAttributes(T)(T t) +{ + alias miniT = miniFormat!T; + return assumeFakeAttributes(&miniT)(t); +} + +auto pureAlloc(size_t t) +{ + static auto alloc(size_t len) + { + return new ubyte[len]; + } + return assumeFakeAttributes(&alloc)(t); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/src/core/internal/traits.d new/druntime-2.085.1/src/core/internal/traits.d --- old/druntime-2.085.0/src/core/internal/traits.d 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/src/core/internal/traits.d 2019-03-28 04:39:36.000000000 +0100 @@ -334,3 +334,217 @@ static assert({ cast(void) dg(); return true; }()); cast(void) dg(); } + +// std.traits.FunctionTypeOf +/* +Get the function type from a callable object `func`. + +Using builtin `typeof` on a property function yields the types of the +property value, not of the property function itself. Still, +`FunctionTypeOf` is able to obtain function types of properties. + +Note: +Do not confuse function types with function pointer types; function types are +usually used for compile-time reflection purposes. + */ +template FunctionTypeOf(func...) +if (func.length == 1 /*&& isCallable!func*/) +{ + static if (is(typeof(& func[0]) Fsym : Fsym*) && is(Fsym == function) || is(typeof(& func[0]) Fsym == delegate)) + { + alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol + } + else static if (is(typeof(& func[0].opCall) Fobj == delegate)) + { + alias FunctionTypeOf = Fobj; // HIT: callable object + } + else static if (is(typeof(& func[0].opCall) Ftyp : Ftyp*) && is(Ftyp == function)) + { + alias FunctionTypeOf = Ftyp; // HIT: callable type + } + else static if (is(func[0] T) || is(typeof(func[0]) T)) + { + static if (is(T == function)) + alias FunctionTypeOf = T; // HIT: function + else static if (is(T Fptr : Fptr*) && is(Fptr == function)) + alias FunctionTypeOf = Fptr; // HIT: function pointer + else static if (is(T Fdlg == delegate)) + alias FunctionTypeOf = Fdlg; // HIT: delegate + else + static assert(0); + } + else + static assert(0); +} + +@safe unittest +{ + class C + { + int value() @property { return 0; } + } + static assert(is( typeof(C.value) == int )); + static assert(is( FunctionTypeOf!(C.value) == function )); +} + +@system unittest +{ + int test(int a); + int propGet() @property; + int propSet(int a) @property; + int function(int) test_fp; + int delegate(int) test_dg; + static assert(is( typeof(test) == FunctionTypeOf!(typeof(test)) )); + static assert(is( typeof(test) == FunctionTypeOf!test )); + static assert(is( typeof(test) == FunctionTypeOf!test_fp )); + static assert(is( typeof(test) == FunctionTypeOf!test_dg )); + alias int GetterType() @property; + alias int SetterType(int) @property; + static assert(is( FunctionTypeOf!propGet == GetterType )); + static assert(is( FunctionTypeOf!propSet == SetterType )); + + interface Prop { int prop() @property; } + Prop prop; + static assert(is( FunctionTypeOf!(Prop.prop) == GetterType )); + static assert(is( FunctionTypeOf!(prop.prop) == GetterType )); + + class Callable { int opCall(int) { return 0; } } + auto call = new Callable; + static assert(is( FunctionTypeOf!call == typeof(test) )); + + struct StaticCallable { static int opCall(int) { return 0; } } + StaticCallable stcall_val; + StaticCallable* stcall_ptr; + static assert(is( FunctionTypeOf!stcall_val == typeof(test) )); + static assert(is( FunctionTypeOf!stcall_ptr == typeof(test) )); + + interface Overloads + { + void test(string); + real test(real); + int test(int); + int test() @property; + } + alias ov = __traits(getVirtualFunctions, Overloads, "test"); + alias F_ov0 = FunctionTypeOf!(ov[0]); + alias F_ov1 = FunctionTypeOf!(ov[1]); + alias F_ov2 = FunctionTypeOf!(ov[2]); + alias F_ov3 = FunctionTypeOf!(ov[3]); + static assert(is(F_ov0* == void function(string))); + static assert(is(F_ov1* == real function(real))); + static assert(is(F_ov2* == int function(int))); + static assert(is(F_ov3* == int function() @property)); + + alias F_dglit = FunctionTypeOf!((int a){ return a; }); + static assert(is(F_dglit* : int function(int))); +} + +// std.traits.ReturnType +/* +Get the type of the return value from a function, +a pointer to function, a delegate, a struct +with an opCall, a pointer to a struct with an opCall, +or a class with an `opCall`. Please note that $(D_KEYWORD ref) +is not part of a type, but the attribute of the function +(see template $(LREF functionAttributes)). +*/ +template ReturnType(func...) +if (func.length == 1 /*&& isCallable!func*/) +{ + static if (is(FunctionTypeOf!func R == return)) + alias ReturnType = R; + else + static assert(0, "argument has no return type"); +} + +// +@safe unittest +{ + int foo(); + ReturnType!foo x; // x is declared as int +} + +@safe unittest +{ + struct G + { + int opCall (int i) { return 1;} + } + + alias ShouldBeInt = ReturnType!G; + static assert(is(ShouldBeInt == int)); + + G g; + static assert(is(ReturnType!g == int)); + + G* p; + alias pg = ReturnType!p; + static assert(is(pg == int)); + + class C + { + int opCall (int i) { return 1;} + } + + static assert(is(ReturnType!C == int)); + + C c; + static assert(is(ReturnType!c == int)); + + class Test + { + int prop() @property { return 0; } + } + alias R_Test_prop = ReturnType!(Test.prop); + static assert(is(R_Test_prop == int)); + + alias R_dglit = ReturnType!((int a) { return a; }); + static assert(is(R_dglit == int)); +} + +// std.traits.Parameters +/* +Get, as a tuple, the types of the parameters to a function, a pointer +to function, a delegate, a struct with an `opCall`, a pointer to a +struct with an `opCall`, or a class with an `opCall`. +*/ +template Parameters(func...) +if (func.length == 1 /*&& isCallable!func*/) +{ + static if (is(FunctionTypeOf!func P == function)) + alias Parameters = P; + else + static assert(0, "argument has no parameters"); +} + +// +@safe unittest +{ + int foo(int, long); + void bar(Parameters!foo); // declares void bar(int, long); + void abc(Parameters!foo[1]); // declares void abc(long); +} + +@safe unittest +{ + int foo(int i, bool b) { return 0; } + static assert(is(Parameters!foo == AliasSeq!(int, bool))); + static assert(is(Parameters!(typeof(&foo)) == AliasSeq!(int, bool))); + + struct S { real opCall(real r, int i) { return 0.0; } } + S s; + static assert(is(Parameters!S == AliasSeq!(real, int))); + static assert(is(Parameters!(S*) == AliasSeq!(real, int))); + static assert(is(Parameters!s == AliasSeq!(real, int))); + + class Test + { + int prop() @property { return 0; } + } + alias P_Test_prop = Parameters!(Test.prop); + static assert(P_Test_prop.length == 0); + + alias P_dglit = Parameters!((int a){}); + static assert(P_dglit.length == 1); + static assert(is(P_dglit[0] == int)); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/src/gc/impl/conservative/gc.d new/druntime-2.085.1/src/gc/impl/conservative/gc.d --- old/druntime-2.085.0/src/gc/impl/conservative/gc.d 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/src/gc/impl/conservative/gc.d 2019-03-28 04:39:36.000000000 +0100 @@ -89,8 +89,8 @@ // Declared as an extern instead of importing core.exception // to avoid inlining - see issue 13725. - void onInvalidMemoryOperationError() @nogc nothrow; - void onOutOfMemoryErrorNoGC() @nogc nothrow; + void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; + void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc; } enum @@ -2386,11 +2386,7 @@ return 0; MonoTime start, stop, begin; - - if (config.profile) - { - begin = start = currTime; - } + begin = start = currTime; debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n"); //printf("\tpool address range = %p .. %p\n", minAddr, maxAddr); @@ -3946,3 +3942,20 @@ void* small = GC.malloc(100, BlkAttr.NO_SCAN); test(small); } + +unittest +{ + import core.memory; + + auto now = currTime; + GC.ProfileStats stats1 = GC.profileStats(); + GC.collect(); + GC.ProfileStats stats2 = GC.profileStats(); + auto diff = currTime - now; + + assert(stats2.totalCollectionTime - stats1.totalCollectionTime <= diff); + assert(stats2.totalPauseTime - stats1.totalPauseTime <= stats2.totalCollectionTime - stats1.totalCollectionTime); + + assert(stats2.maxPauseTime >= stats1.maxPauseTime); + assert(stats2.maxCollectionTime >= stats1.maxCollectionTime); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/src/object.d new/druntime-2.085.1/src/object.d --- old/druntime-2.085.0/src/object.d 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/src/object.d 2019-03-28 04:39:36.000000000 +0100 @@ -4158,13 +4158,12 @@ template RTInfoImpl(size_t[] pointers) { - immutable size_t[pointers.length] data = pointers[]; - immutable RTInfoImpl = data.ptr; + immutable size_t[pointers.length] RTInfoImpl = pointers[]; } template RTInfo(T) { - enum RTInfo = RTInfoImpl!(__traits(getPointerBitmap, T)); + enum RTInfo = RTInfoImpl!(__traits(getPointerBitmap, T)).ptr; } /** @@ -4819,11 +4818,29 @@ } // Allows customized assert error messages -string _d_assert_fail(string comp, A, B)(A a, B b) +string _d_assert_fail(string comp, A, B)(A a, B b) @nogc @safe nothrow pure { - import core.internal.dassert : invertCompToken, miniFormat; - auto valA = miniFormat(a); - auto valB = miniFormat(b); + import core.internal.dassert : invertCompToken, miniFormatFakeAttributes, pureAlloc; + /* + The program will be terminated after the assertion error message has + been printed and its not considered part of the "main" program. + Also, catching an AssertError is Undefined Behavior + Hence, we can fake purity and @nogc-ness here. + */ + + auto valA = miniFormatFakeAttributes(a); + auto valB = miniFormatFakeAttributes(b); enum token = invertCompToken(comp); - return valA ~ " " ~ token ~ " " ~ valB; + + const totalLen = valA.length + token.length + valB.length + 2; + char[] buffer = cast(char[]) pureAlloc(totalLen)[0 .. totalLen]; + // @nogc-concat of "<valA> <comp> <valB>" + auto n = valA.length; + buffer[0 .. n] = valA; + buffer[n++] = ' '; + buffer[n .. n + token.length] = token; + n += token.length; + buffer[n++] = ' '; + buffer[n .. n + valB.length] = valB; + return (() @trusted => cast(string) buffer)(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/src/rt/lifetime.d new/druntime-2.085.1/src/rt/lifetime.d --- old/druntime-2.085.0/src/rt/lifetime.d 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/src/rt/lifetime.d 2019-03-28 04:39:36.000000000 +0100 @@ -1420,12 +1420,12 @@ } } -extern (C) void rt_finalize(void* p, bool det = true) +extern (C) void rt_finalize(void* p, bool det = true) nothrow { rt_finalize2(p, det, true); } -extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr) +extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr) nothrow { // to verify: reset memory necessary? if (!(attr & BlkAttr.STRUCTFINAL)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/druntime-2.085.0/test/exceptions/src/assert_fail.d new/druntime-2.085.1/test/exceptions/src/assert_fail.d --- old/druntime-2.085.0/test/exceptions/src/assert_fail.d 2019-02-15 20:09:43.000000000 +0100 +++ new/druntime-2.085.1/test/exceptions/src/assert_fail.d 2019-03-28 04:39:36.000000000 +0100 @@ -110,6 +110,13 @@ test([1:"one"], [2: "two"], `[1: "one"] != [2: "two"]`); } + +void testAttributes() @safe pure @nogc nothrow +{ + int a; + assert(a == 0); +} + void main() { testIntegers(); @@ -120,5 +127,6 @@ testArray(); testStruct(); testAA(); + testAttributes(); fprintf(stderr, "success.\n"); } ++++++ phobos-2.085.0.tar.gz -> phobos-2.085.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/phobos-2.085.0/std/algorithm/iteration.d new/phobos-2.085.1/std/algorithm/iteration.d --- old/phobos-2.085.0/std/algorithm/iteration.d 2019-02-15 20:09:48.000000000 +0100 +++ new/phobos-2.085.1/std/algorithm/iteration.d 2019-04-01 03:32:18.000000000 +0200 @@ -1641,6 +1641,12 @@ if (!_input.empty) popFront(); } + private this(R input, Tuple!(MutableE, uint) current) + { + _input = input; + _current = current; + } + /// void popFront() { @@ -1684,11 +1690,9 @@ static if (isForwardRange!R) { /// - @property typeof(this) save() { - typeof(this) ret = this; - ret._input = this._input.save; - ret._current = this._current; - return ret; + @property typeof(this) save() + { + return Group(_input.save, _current); } } } @@ -1807,6 +1811,15 @@ assert(t.equal([ tuple(3, 1u), tuple(4, 3u), tuple(5, 1u) ])); } +pure @safe unittest // issue 18657 +{ + import std.algorithm.comparison : equal; + import std.range : refRange; + auto r = refRange(&["foo"][0]).group; + assert(equal(r.save, "foo".group)); + assert(equal(r, "foo".group)); +} + // Used by implementation of chunkBy for non-forward input ranges. private struct ChunkByChunkImpl(alias pred, Range) if (isInputRange!Range && !isForwardRange!Range) @@ -5149,6 +5162,24 @@ _end = size_t.max; } + static if (fullSlicing) + { + private this(Range input, size_t end) + { + _input = input; + _end = end; + } + } + else + { + private this(Range input, size_t end, Range next) + { + _input = input; + _end = end; + _next = next; + } + } + static if (isInfinite!Range) { enum bool empty = false; // Propagate infiniteness. @@ -5213,11 +5244,10 @@ @property typeof(this) save() { - auto ret = this; - ret._input = _input.save; - static if (!fullSlicing) - ret._next = _next.save; - return ret; + static if (fullSlicing) + return SplitterResult(_input.save, _end); + else + return SplitterResult(_input.save, _end, _next.save); } } @@ -5314,6 +5344,15 @@ assert(equal(splitter!"a=='本'"("日本語"), ["日", "語"])); } +pure @safe unittest // issue 18657 +{ + import std.algorithm.comparison : equal; + import std.range : refRange; + auto r = refRange(&["foobar"][0]).splitter!(c => c == 'b'); + assert(equal!equal(r.save, ["foo", "ar"])); + assert(equal!equal(r.save, ["foo", "ar"])); +} + /++ Lazily splits the character-based range `s` into words, using whitespace as the delimiter. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/phobos-2.085.0/std/algorithm/searching.d new/phobos-2.085.1/std/algorithm/searching.d --- old/phobos-2.085.0/std/algorithm/searching.d 2019-02-15 20:09:48.000000000 +0100 +++ new/phobos-2.085.1/std/algorithm/searching.d 2019-04-01 03:32:18.000000000 +0200 @@ -2684,7 +2684,7 @@ InputRange seq, ForwardRange choices) if (isInputRange!InputRange && isForwardRange!ForwardRange) { - for (; !seq.empty && find!pred(choices, seq.front).empty; seq.popFront()) + for (; !seq.empty && find!pred(choices.save, seq.front).empty; seq.popFront()) { } return seq; @@ -2708,6 +2708,14 @@ assert(findAmong!("a == b")(b, [ 4, 6, 7 ][]).empty); } +@system unittest // issue 19765 +{ + import std.range.interfaces : inputRangeObject; + auto choices = inputRangeObject("b"); + auto f = "foobar".findAmong(choices); + assert(f == "bar"); +} + // findSkip /** * Finds `needle` in `haystack` and positions `haystack` @@ -4913,6 +4921,7 @@ private bool _done; static if (!is(Sentinel == void)) + { /// this(Range input, Sentinel sentinel, OpenRight openRight = Yes.openRight) @@ -4922,7 +4931,17 @@ _openRight = openRight; _done = _input.empty || openRight && predSatisfied(); } + private this(Range input, Sentinel sentinel, OpenRight openRight, + bool done) + { + _input = input; + _sentinel = sentinel; + _openRight = openRight; + _done = done; + } + } else + { /// this(Range input, OpenRight openRight = Yes.openRight) { @@ -4930,6 +4949,13 @@ _openRight = openRight; _done = _input.empty || openRight && predSatisfied(); } + private this(Range input, OpenRight openRight, bool done) + { + _input = input; + _openRight = openRight; + _done = done; + } + } /// @property bool empty() @@ -4971,27 +4997,14 @@ static if (isForwardRange!Range) { - static if (!is(Sentinel == void)) - /// - @property Until save() - { - Until result = this; - result._input = _input.save; - result._sentinel = _sentinel; - result._openRight = _openRight; - result._done = _done; - return result; - } - else - /// - @property Until save() - { - Until result = this; - result._input = _input.save; - result._openRight = _openRight; - result._done = _done; - return result; - } + /// + @property Until save() + { + static if (is(Sentinel == void)) + return Until(_input.save, _openRight, _done); + else + return Until(_input.save, _sentinel, _openRight, _done); + } } } @@ -5043,3 +5056,19 @@ auto s = "hello how\nare you"; assert(equal(s.until!(c => c.among!('\n', '\r')), "hello how")); } + +pure @safe unittest // issue 18657 +{ + import std.algorithm.comparison : equal; + import std.range : refRange; + { + auto r = refRange(&["foobar"][0]).until("bar"); + assert(equal(r.save, "foo")); + assert(equal(r.save, "foo")); + } + { + auto r = refRange(&["foobar"][0]).until!(e => e == 'b'); + assert(equal(r.save, "foo")); + assert(equal(r.save, "foo")); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/phobos-2.085.0/std/range/package.d new/phobos-2.085.1/std/range/package.d --- old/phobos-2.085.0/std/range/package.d 2019-02-15 20:09:48.000000000 +0100 +++ new/phobos-2.085.1/std/range/package.d 2019-04-01 03:32:18.000000000 +0200 @@ -972,12 +972,20 @@ static if (allSatisfy!(isForwardRange, R)) @property auto save() { - typeof(this) result = this; - foreach (i, Unused; R) + auto saveSource(size_t len)() { - result.source[i] = result.source[i].save; + import std.typecons : tuple; + static if (len == 0) + { + return tuple(); + } + else + { + return saveSource!(len - 1)() ~ + tuple(source[len - 1].save); + } } - return result; + return Result(saveSource!(R.length).expand); } void popFront() @@ -1380,6 +1388,14 @@ assert(chain(a, b).empty); } +pure @safe unittest // issue 18657 +{ + import std.algorithm.comparison : equal; + auto r = refRange(&["foo"][0]).chain("bar"); + assert(equal(r.save, "foobar")); + assert(equal(r, "foobar")); +} + /** Choose one of two ranges at runtime depending on a Boolean condition. @@ -1513,9 +1529,9 @@ static if (isForwardRange!R1 && isForwardRange!R2) @property auto save() { - auto result = this; - actOnChosen!((ref r) { r = r.save; })(result); - return result; + return r1Chosen + ? ChooseResult(r1Chosen, r1.save, r2) + : ChooseResult(r1Chosen, r1, r2.save); } @property void front(T)(T v) @@ -1602,6 +1618,14 @@ } } +pure @safe unittest // issue 18657 +{ + import std.algorithm.comparison : equal; + auto r = choose(true, refRange(&["foo"][0]), "bar"); + assert(equal(r.save, "foo")); + assert(equal(r, "foo")); +} + /** Choose one of multiple ranges at runtime. @@ -1822,12 +1846,20 @@ static if (allSatisfy!(isForwardRange, staticMap!(Unqual, Rs))) @property auto save() { - Result result = this; - foreach (i, Unused; Rs) + auto saveSource(size_t len)() { - result.source[i] = result.source[i].save; + import std.typecons : tuple; + static if (len == 0) + { + return tuple(); + } + else + { + return saveSource!(len - 1)() ~ + tuple(source[len - 1].save); + } } - return result; + return Result(saveSource!(Rs.length).expand, _current); } static if (allSatisfy!(hasLength, Rs)) @@ -1885,6 +1917,14 @@ assert(interleave([1, 2, 3], 0).equal([1, 0, 2, 0, 3])); } +pure @safe unittest +{ + import std.algorithm.comparison : equal; + auto r = roundRobin(refRange(&["foo"][0]), refRange(&["bar"][0])); + assert(equal(r.save, "fboaor")); + assert(equal(r.save, "fboaor")); +} + /** Iterates a random-access range starting from a given point and progressively extending left and right from that point. If no initial @@ -3750,6 +3790,12 @@ _current = input.save; } + private this(R original, R current) + { + _original = original; + _current = current; + } + /// ditto @property auto ref front() { @@ -3789,10 +3835,7 @@ @property Cycle save() { //No need to call _original.save, because Cycle never actually modifies _original - Cycle ret = this; - ret._original = _original; - ret._current = _current.save; - return ret; + return Cycle(_original, _current.save); } } } @@ -4104,6 +4147,14 @@ assertThrown!AssertError(cycle([0, 1, 2][0 .. 0])); } +pure @safe unittest // issue 18657 +{ + import std.algorithm.comparison : equal; + auto r = refRange(&["foo"][0]).cycle.take(4); + assert(equal(r.save, "foof")); + assert(equal(r.save, "foof")); +} + private alias lengthType(R) = typeof(R.init.length.init); /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/phobos-2.085.0/std/variant.d new/phobos-2.085.1/std/variant.d --- old/phobos-2.085.0/std/variant.d 2019-02-15 20:09:48.000000000 +0100 +++ new/phobos-2.085.1/std/variant.d 2019-04-01 03:32:18.000000000 +0200 @@ -726,7 +726,7 @@ } /// - version (unittest) + version (StdDdoc) @system unittest { Variant a; @@ -759,7 +759,7 @@ } /// - version (unittest) + version (StdDdoc) @system unittest { Variant a = 5; @@ -1097,7 +1097,7 @@ } /// - version (unittest) + version (StdDdoc) @system unittest { Variant a = new int[10];
