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
+
+- 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];