diff --git a/.dscanner.ini b/.dscanner.ini index 5f936444735..03cf7e6ee77 100644 --- a/.dscanner.ini +++ b/.dscanner.ini @@ -404,7 +404,7 @@ redundant_attributes_check="-std.concurrency,-std.digest.md,-std.digest.ripemd,- style_check="+disabled" ;style_check="-etc.c.curl,-etc.c.odbc.sqlext,-etc.c.odbc.sqltypes,-etc.c.odbc.sqlucode,-etc.c.sqlite3,-etc.c.zlib,-std.algorithm.comparison,-std.algorithm.internal,-std.algorithm.iteration,-std.algorithm.mutation,-std.algorithm.sorting,-std.array,-std.base64,-std.bitmanip,-std.c.linux.linux,-std.compiler,-std.container.array,-std.conv,-std.datetime.date,-std.datetime.interval,-std.datetime.systime,-std.digest,-std.digest.murmurhash,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.affix_allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bucketizer,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.null_allocator,-std.experimental.allocator.building_blocks.region,-std.experimental.allocator.building_blocks.segregator,-std.experimental.allocator.common,-std.experimental.allocator.gc_allocator,-std.experimental.allocator.mallocator,-std.experimental.allocator.mmap_allocator,-std.experimental.checkedint,-std.format,-std.functional,-std.getopt,-std.internal.digest.sha_SSSE3,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.test.dummyrange,-std.internal.unicode_tables,-std.json,-std.math,-std.meta,-std.numeric,-std.parallelism,-std.path,-std.process,-std.random,-std.range,-std.range.primitives,-std.regex,-std.regex.internal.ir,-std.regex.internal.kickstart,-std.signals,-std.socket,-std.stdio,-std.string,-std.uni,-std.uri,-std.utf,-std.uuid,-std.variant,-std.zlib" ; Checks for undocumented public declarations -undocumented_declaration_check="-etc.c.curl,-etc.c.odbc.sql,-etc.c.odbc.sqlext,-etc.c.odbc.sqltypes,-etc.c.odbc.sqlucode,-etc.c.sqlite3,-etc.c.zlib,-std.algorithm.sorting,-std.array,-std.ascii,-std.base64,-std.bitmanip,-std.c.linux.linux,-std.c.linux.socket,-std.c.osx.socket,-std.c.process,-std.compiler,-std.complex,-std.concurrency,-std.container,-std.container.array,-std.container.binaryheap,-std.container.dlist,-std.container.rbtree,-std.container.slist,-std.conv,-std.csv,-std.datetime,-std.datetime.date,-std.digest,-std.digest.hmac,-std.digest.md,-std.digest.murmurhash,-std.digest.ripemd,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.affix_allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bitmapped_block,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.kernighan_ritchie,-std.experimental.allocator.building_blocks.quantizer,-std.experimental.allocator.building_blocks.region,-std.experimental.allocator.building_blocks.segregator,-std.experimental.allocator.building_blocks.stats_collector,-std.experimental.allocator.gc_allocator,-std.experimental.allocator.mallocator,-std.experimental.checkedint,-std.logger.core,-std.file,-std.format,-std.functional,-std.internal.digest.sha_SSSE3,-std.internal.math.biguintcore,-std.internal.math.biguintnoasm,-std.internal.math.biguintx86,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.test.dummyrange,-std.internal.test.uda,-std.internal.windows.advapi32,-std.json,-std.math,-std.mmfile,-std.numeric,-std.outbuffer,-std.parallelism,-std.path,-std.process,-std.regex,-std.regex.internal.parser,-std.signals,-std.socket,-std.stdio,-std.string,-std.system,-std.traits,-std.uni,-std.utf,-std.variant,-std.windows.charset,-std.windows.registry,-std.windows.syserror,-std.zip,-std.zlib,-std.int128" +undocumented_declaration_check="-etc.c.curl,-etc.c.odbc.sql,-etc.c.odbc.sqlext,-etc.c.odbc.sqltypes,-etc.c.odbc.sqlucode,-etc.c.sqlite3,-etc.c.zlib,-std.algorithm.sorting,-std.array,-std.ascii,-std.base64,-std.bitmanip,-std.c.linux.linux,-std.c.linux.socket,-std.c.osx.socket,-std.c.process,-std.compiler,-std.complex,-std.concurrency,-std.container,-std.container.array,-std.container.binaryheap,-std.container.dlist,-std.container.rbtree,-std.container.slist,-std.conv,-std.csv,-std.datetime,-std.datetime.date,-std.digest,-std.digest.hmac,-std.digest.md,-std.digest.murmurhash,-std.digest.ripemd,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.affix_allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bitmapped_block,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.kernighan_ritchie,-std.experimental.allocator.building_blocks.quantizer,-std.experimental.allocator.building_blocks.region,-std.experimental.allocator.building_blocks.segregator,-std.experimental.allocator.building_blocks.stats_collector,-std.experimental.allocator.gc_allocator,-std.experimental.allocator.mallocator,-std.experimental.checkedint,-std.logger.core,-std.file,-std.format,-std.functional,-std.internal.digest.sha_SSSE3,-std.internal.math.biguintcore,-std.internal.math.biguintnoasm,-std.internal.math.biguintx86,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.test.dummyrange,-std.internal.test.sumtype_example_overloads,-std.internal.test.uda,-std.internal.windows.advapi32,-std.json,-std.math,-std.mmfile,-std.numeric,-std.outbuffer,-std.parallelism,-std.path,-std.process,-std.regex,-std.regex.internal.parser,-std.signals,-std.socket,-std.stdio,-std.string,-std.system,-std.traits,-std.uni,-std.utf,-std.variant,-std.windows.charset,-std.windows.registry,-std.windows.syserror,-std.zip,-std.zlib,-std.int128" ; Checks for unused labels unused_label_check="-std.conv,-std.internal.math.biguintx86,-std.regex.internal.thompson,-std.signals,-std.uni" ; Checks for unused function parameters diff --git a/Makefile b/Makefile index 89704a431ee..17998f75e31 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,9 @@ # make BUILD=debug => makes debug build of the library # # make unittest => builds all unittests (for debug AND release) and runs them +# make std/somemodule.test => only builds and unittests std.somemodule +# make std/somepackage.test => only builds and unittests modules in std.somepackage +# make unittest/std/somemodule.run => run std.somemodule unittest # # make BUILD=debug unittest => builds all unittests (for debug) and runs them # @@ -25,8 +28,6 @@ # # make install => copies library to /usr/lib # -# make std/somemodule.test => only builds and unittests std.somemodule -# ################################################################################ # Configurable stuff, usually from the command line # @@ -272,6 +273,7 @@ EXTRA_MODULES_INTERNAL := $(addprefix std/, \ $(addprefix math/, biguintcore biguintnoasm biguintx86 \ errorfunction gammafunction ) \ scopebuffer test/dummyrange test/range \ + test/sumtype_example_overloads \ $(addprefix unicode_, comp decomp grapheme norm tables) \ windows/advapi32 \ ) \ diff --git a/std/bitmanip.d b/std/bitmanip.d index de2ff318f4e..639b8214c8c 100644 --- a/std/bitmanip.d +++ b/std/bitmanip.d @@ -805,6 +805,7 @@ private struct FloatingPointRepresentation(T) Allows manipulating the fraction, exponent, and sign parts of a `float` separately. The definition is: +$(RUNNABLE_EXAMPLE ---- struct FloatRep { @@ -819,6 +820,7 @@ struct FloatRep enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1; } ---- +) */ alias FloatRep = FloatingPointRepresentation!float; @@ -874,6 +876,7 @@ alias FloatRep = FloatingPointRepresentation!float; Allows manipulating the fraction, exponent, and sign parts of a `double` separately. The definition is: +$(RUNNABLE_EXAMPLE ---- struct DoubleRep { @@ -888,6 +891,7 @@ struct DoubleRep enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11; } ---- +) */ alias DoubleRep = FloatingPointRepresentation!double; @@ -1050,6 +1054,8 @@ public: of a type different than `size_t`, firstly because its length should be a multiple of `size_t.sizeof`, and secondly because how the bits are mapped: + + $(RUNNABLE_EXAMPLE --- size_t[] source = [1, 2, 3, 3424234, 724398, 230947, 389492]; enum sbits = size_t.sizeof * 8; @@ -1060,6 +1066,7 @@ public: assert(ba[n] == nth_bit); } --- + ) The least significant bit in any `size_t` unit is the starting bit of this unit, and the most significant bit is the last bit of this unit. Therefore, passing e.g. an array of `int`s may result in a different `BitArray` diff --git a/std/experimental/allocator/mallocator.d b/std/experimental/allocator/mallocator.d index 02d5cf8b6d3..3d4dc9a2c52 100644 --- a/std/experimental/allocator/mallocator.d +++ b/std/experimental/allocator/mallocator.d @@ -116,93 +116,11 @@ struct Mallocator test!Mallocator(); } -version (Windows) +version (CRuntime_Microsoft) { - // DMD Win 32 bit, DigitalMars C standard library misses the _aligned_xxx - // functions family (snn.lib) - version (CRuntime_DigitalMars) - { - // Helper to cast the infos written before the aligned pointer - // this header keeps track of the size (required to realloc) and of - // the base ptr (required to free). - private struct AlignInfo - { - void* basePtr; - size_t size; - - @nogc nothrow - static AlignInfo* opCall(void* ptr) - { - return cast(AlignInfo*) (ptr - AlignInfo.sizeof); - } - } - - @nogc nothrow - private void* _aligned_malloc(size_t size, size_t alignment) - { - import core.stdc.stdlib : malloc; - size_t offset = alignment + size_t.sizeof * 2 - 1; - - // unaligned chunk - void* basePtr = malloc(size + offset); - if (!basePtr) return null; - - // get aligned location within the chunk - void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset) - & ~(alignment - 1)); - - // write the header before the aligned pointer - AlignInfo* head = AlignInfo(alignedPtr); - head.basePtr = basePtr; - head.size = size; - - return alignedPtr; - } - - @nogc nothrow - private void* _aligned_realloc(void* ptr, size_t size, size_t alignment) - { - import core.stdc.stdlib : free; - import core.stdc.string : memcpy; - - if (!ptr) return _aligned_malloc(size, alignment); - - // gets the header from the exising pointer - AlignInfo* head = AlignInfo(ptr); - - // gets a new aligned pointer - void* alignedPtr = _aligned_malloc(size, alignment); - if (!alignedPtr) - { - //to https://msdn.microsoft.com/en-us/library/ms235462.aspx - //see Return value: in this case the original block is unchanged - return null; - } - - // copy exising data - memcpy(alignedPtr, ptr, head.size); - free(head.basePtr); - - return alignedPtr; - } - - @nogc nothrow - private void _aligned_free(void *ptr) - { - import core.stdc.stdlib : free; - if (!ptr) return; - AlignInfo* head = AlignInfo(ptr); - free(head.basePtr); - } - - } - // DMD Win 64 bit, uses microsoft standard C library which implements them - else - { - @nogc nothrow private extern(C) void* _aligned_malloc(size_t, size_t); - @nogc nothrow private extern(C) void _aligned_free(void *memblock); - @nogc nothrow private extern(C) void* _aligned_realloc(void *, size_t, size_t); - } + @nogc nothrow private extern(C) void* _aligned_malloc(size_t, size_t); + @nogc nothrow private extern(C) void _aligned_free(void *memblock); + @nogc nothrow private extern(C) void* _aligned_realloc(void *, size_t, size_t); } /** @@ -399,50 +317,3 @@ version (Posix) assert(!AlignedMallocator.instance.alignedReallocate(c, size_t.max, 4096)); AlignedMallocator.instance.deallocate(c); } - -version (CRuntime_DigitalMars) -@nogc @system nothrow unittest -{ - void* m; - - size_t m_addr() { return cast(size_t) m; } - - m = _aligned_malloc(16, 0x10); - if (m) - { - assert((m_addr & 0xF) == 0); - _aligned_free(m); - } - - m = _aligned_malloc(16, 0x100); - if (m) - { - assert((m_addr & 0xFF) == 0); - _aligned_free(m); - } - - m = _aligned_malloc(16, 0x1000); - if (m) - { - assert((m_addr & 0xFFF) == 0); - _aligned_free(m); - } - - m = _aligned_malloc(16, 0x10); - if (m) - { - assert((cast(size_t) m & 0xF) == 0); - m = _aligned_realloc(m, 32, 0x10000); - if (m) assert((m_addr & 0xFFFF) == 0); - _aligned_free(m); - } - - m = _aligned_malloc(8, 0x10); - if (m) - { - *cast(ulong*) m = 0X01234567_89ABCDEF; - m = _aligned_realloc(m, 0x800, 0x1000); - if (m) assert(*cast(ulong*) m == 0X01234567_89ABCDEF); - _aligned_free(m); - } -} diff --git a/std/file.d b/std/file.d index 1db779bdf8e..2a0d1392c08 100644 --- a/std/file.d +++ b/std/file.d @@ -4053,12 +4053,10 @@ else version (Posix) +/ void _ensureStatDone() @trusted scope { - import std.exception : enforce; - if (_didStat) return; - enforce(stat(_name.tempCString(), &_statBuf) == 0, + cenforce(stat(_name.tempCString(), &_statBuf) == 0, "Failed to stat file `" ~ _name ~ "'"); _didStat = true; @@ -4095,13 +4093,11 @@ else version (Posix) +/ void _ensureLStatDone() @trusted scope { - import std.exception : enforce; - if (_didLStat) return; stat_t statbuf = void; - enforce(lstat(_name.tempCString(), &statbuf) == 0, + cenforce(lstat(_name.tempCString(), &statbuf) == 0, "Failed to stat file `" ~ _name ~ "'"); _lstatMode = statbuf.st_mode; @@ -4183,12 +4179,12 @@ else version (Posix) assert(!de.isFile); assert(!de.isDir); assert(de.isSymlink); - assertThrown(de.size); - assertThrown(de.timeStatusChanged); - assertThrown(de.timeLastAccessed); - assertThrown(de.timeLastModified); - assertThrown(de.attributes); - assertThrown(de.statBuf); + assertThrown!FileException(de.size); + assertThrown!FileException(de.timeStatusChanged); + assertThrown!FileException(de.timeLastAccessed); + assertThrown!FileException(de.timeLastModified); + assertThrown!FileException(de.attributes); + assertThrown!FileException(de.statBuf); assert(symfile.exists); symfile.remove(); } diff --git a/std/format/spec.d b/std/format/spec.d index b129686f8a3..e5564c99d8f 100644 --- a/std/format/spec.d +++ b/std/format/spec.d @@ -681,7 +681,7 @@ if (is(Unqual!Char == Char)) auto fmt = "Number: %6.4e\nString: %s"; auto f = FormatSpec!char(fmt); - assert(f.writeUpToNextSpec(a) == true); + assert(f.writeUpToNextSpec(a)); assert(a.data == "Number: "); assert(f.trailing == "\nString: %s"); @@ -689,13 +689,13 @@ if (is(Unqual!Char == Char)) assert(f.width == 6); assert(f.precision == 4); - assert(f.writeUpToNextSpec(a) == true); + assert(f.writeUpToNextSpec(a)); assert(a.data == "Number: \nString: "); assert(f.trailing == ""); assert(f.spec == 's'); - assert(f.writeUpToNextSpec(a) == false); + assert(!f.writeUpToNextSpec(a)); assert(a.data == "Number: \nString: "); } diff --git a/std/internal/test/sumtype_example_overloads.d b/std/internal/test/sumtype_example_overloads.d new file mode 100644 index 00000000000..235659dc8b7 --- /dev/null +++ b/std/internal/test/sumtype_example_overloads.d @@ -0,0 +1,17 @@ +/++ +For testing only. + +Overload set used in std.sumtype example. Needs its own internal module so that +it can be available for `make publictests` without polluting the public API. ++/ +module std.internal.test.sumtype_example_overloads; + +import std.sumtype; + +@safe +{ + string handle(int) { return "got an int"; } + string handle(string) { return "got a string"; } + string handle(double) { return "got a double"; } + alias handle = match!handle; +} diff --git a/std/math/exponential.d b/std/math/exponential.d index 0ca12f8e337..be0fdb0b13c 100644 --- a/std/math/exponential.d +++ b/std/math/exponential.d @@ -256,7 +256,7 @@ if (isFloatingPoint!(F) && isIntegral!(G)) * If x is 0 and n is negative, the result is the same as the result of a * division by zero. */ -typeof(Unqual!(F).init * Unqual!(G).init) pow(F, G)(F x, G n) @nogc @trusted pure nothrow +typeof(Unqual!(F).init * Unqual!(G).init) pow(F, G)(F x, G n) @nogc @safe pure nothrow if (isIntegral!(F) && isIntegral!(G)) { import std.traits : isSigned; diff --git a/std/math/rounding.d b/std/math/rounding.d index 16b02259721..0639078c55f 100644 --- a/std/math/rounding.d +++ b/std/math/rounding.d @@ -772,27 +772,18 @@ version (Posix) * * If the fractional part of x is exactly 0.5, the return value is rounded * away from zero. - * - * $(BLUE This function is not implemented for Digital Mars C runtime.) */ long lround(real x) @trusted nothrow @nogc { - version (CRuntime_DigitalMars) - assert(0, "lround not implemented"); - else - return core.stdc.math.llroundl(x); + return core.stdc.math.llroundl(x); } /// @safe nothrow @nogc unittest { - version (CRuntime_DigitalMars) {} - else - { - assert(lround(0.49) == 0); - assert(lround(0.5) == 1); - assert(lround(1.5) == 2); - } + assert(lround(0.49) == 0); + assert(lround(0.5) == 1); + assert(lround(1.5) == 2); } /** diff --git a/std/net/curl.d b/std/net/curl.d index 3f823013e65..07905fc7003 100644 --- a/std/net/curl.d +++ b/std/net/curl.d @@ -1063,7 +1063,7 @@ private auto _basicHTTP(T)(const(char)[] url, const(void)[] sendData, HTTP clien { size_t minLen = min(buf.length, remainingData.length); if (minLen == 0) return 0; - buf[0 .. minLen] = remainingData[0 .. minLen]; + buf[0 .. minLen] = cast(void[]) remainingData[0 .. minLen]; remainingData = remainingData[minLen..$]; return minLen; }; @@ -1202,7 +1202,7 @@ private auto _basicFTP(T)(const(char)[] url, const(void)[] sendData, FTP client) { size_t minLen = min(buf.length, sendData.length); if (minLen == 0) return 0; - buf[0 .. minLen] = sendData[0 .. minLen]; + buf[0 .. minLen] = cast(void[]) sendData[0 .. minLen]; sendData = sendData[minLen..$]; return minLen; }; diff --git a/std/process.d b/std/process.d index c53a5b11709..d1783742e5e 100644 --- a/std/process.d +++ b/std/process.d @@ -127,26 +127,19 @@ else version (WatchOS) version = iOSDerived; } -// When the DMC runtime is used, we have to use some custom functions -// to convert between Windows file handles and FILE*s. -version (Win32) version (CRuntime_DigitalMars) version = DMC_RUNTIME; - // Some of the following should be moved to druntime. private { // Microsoft Visual C Runtime (MSVCRT) declarations. - version (Windows) + version (CRuntime_Microsoft) { - version (DMC_RUNTIME) { } else + import core.stdc.stdint; + enum { - import core.stdc.stdint; - enum - { - STDIN_FILENO = 0, - STDOUT_FILENO = 1, - STDERR_FILENO = 2, - } + STDIN_FILENO = 0, + STDOUT_FILENO = 1, + STDERR_FILENO = 2, } } diff --git a/std/range/package.d b/std/range/package.d index 995bf1e6c9b..b6fddf76559 100644 --- a/std/range/package.d +++ b/std/range/package.d @@ -13539,10 +13539,10 @@ if (isInputRange!R && isIntegral!(ElementType!R)) { size_t bitsNum = IntegralType.sizeof * 8; - auto first = cast(IntegralType)(1); + auto first = IntegralType(1); // 2 ^ (bitsNum - 1) - auto second = cast(IntegralType)(cast(IntegralType)(1) << (bitsNum - 2)); + auto second = cast(IntegralType)(IntegralType(1) << (bitsNum - 2)); IntegralType[] a = [first, second]; auto bw = Bitwise!(IntegralType[])(a); @@ -13571,7 +13571,7 @@ if (isInputRange!R && isIntegral!(ElementType!R)) auto bw2 = bw[0 .. $ - 5]; auto bw3 = bw2[]; - assert(bw2.length == (bw.length - 5)); + assert(bw2.length == bw.length - 5); assert(bw2.length == bw3.length); bw2.popFront(); assert(bw2.length != bw3.length); diff --git a/std/regex/internal/ir.d b/std/regex/internal/ir.d index 04b902fc39d..25566d6bea6 100644 --- a/std/regex/internal/ir.d +++ b/std/regex/internal/ir.d @@ -318,7 +318,7 @@ struct Bytecode @property bool backreference() const { assert(code == IR.GroupStart || code == IR.GroupEnd); - return cast(bool)(raw & 1 << 23); + return (raw & 1 << 23) != 0; } //mark as local reference (for backrefs in lookarounds) @@ -332,7 +332,7 @@ struct Bytecode @property bool localRef() const { assert(code == IR.Backref); - return cast(bool)(raw & 1 << 23); + return (raw & 1 << 23) != 0; } //human readable name of instruction diff --git a/std/stdio.d b/std/stdio.d index 40dc85420fe..8caa9b36718 100644 --- a/std/stdio.d +++ b/std/stdio.d @@ -123,9 +123,6 @@ alias KeepTerminator = Flag!"keepTerminator"; version (CRuntime_Microsoft) { } -else version (CRuntime_DigitalMars) -{ -} else version (CRuntime_Glibc) { } @@ -215,54 +212,7 @@ version (Posix) static import core.sys.posix.stdio; // getdelim, flockfile } -version (CRuntime_DigitalMars) -{ - private alias _FPUTC = _fputc_nlock; - private alias _FPUTWC = _fputwc_nlock; - private alias _FGETC = _fgetc_nlock; - private alias _FGETWC = _fgetwc_nlock; - private alias _FLOCK = __fp_lock; - private alias _FUNLOCK = __fp_unlock; - - // Alias for CRuntime_Microsoft compatibility. - // @@@DEPRECATED_2.107@@@ - // Rename this back to _setmode once the deprecation phase has ended. - private alias __setmode = setmode; - - // @@@DEPRECATED_2.107@@@ - deprecated("internal alias FPUTC was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - alias FPUTC = _fputc_nlock; - // @@@DEPRECATED_2.107@@@ - deprecated("internal alias FPUTWC was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - alias FPUTWC = _fputwc_nlock; - // @@@DEPRECATED_2.107@@@ - deprecated("internal alias FGETC was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - alias FGETC = _fgetc_nlock; - // @@@DEPRECATED_2.107@@@ - deprecated("internal alias FGETWC was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - alias FGETWC = _fgetwc_nlock; - // @@@DEPRECATED_2.107@@@ - deprecated("internal alias FLOCK was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - alias FLOCK = __fp_lock; - // @@@DEPRECATED_2.107@@@ - deprecated("internal alias FUNLOCK was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - alias FUNLOCK = __fp_unlock; - // @@@DEPRECATED_2.107@@@ - deprecated("internal alias _setmode was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - alias _setmode = setmode; - // @@@DEPRECATED_2.107@@@ - deprecated("internal function _fileno was unintentionally available from " - ~ "std.stdio and will be removed afer 2.107") - fileno_t _fileno(FILE* f) { return f._file; } -} -else version (CRuntime_Microsoft) +version (CRuntime_Microsoft) { private alias _FPUTC = _fputc_nolock; private alias _FPUTWC = _fputwc_nolock; @@ -271,10 +221,6 @@ else version (CRuntime_Microsoft) private alias _FLOCK = _lock_file; private alias _FUNLOCK = _unlock_file; - // @@@DEPRECATED_2.107@@@ - // Remove this once the deprecation phase for CRuntime_DigitalMars has ended. - private alias __setmode = _setmode; - // @@@DEPRECATED_2.107@@@ deprecated("internal alias FPUTC was unintentionally available from " ~ "std.stdio and will be removed afer 2.107") @@ -413,11 +359,7 @@ else private extern (C) @nogc nothrow { pragma(mangle, _FPUTC.mangleof) int trustedFPUTC(int ch, _iobuf* h) @trusted; - - version (CRuntime_DigitalMars) - pragma(mangle, _FPUTWC.mangleof) int trustedFPUTWC(int ch, _iobuf* h) @trusted; - else - pragma(mangle, _FPUTWC.mangleof) int trustedFPUTWC(wchar_t ch, _iobuf* h) @trusted; + pragma(mangle, _FPUTWC.mangleof) int trustedFPUTWC(wchar_t ch, _iobuf* h) @trusted; } //------------------------------------------------------------------------------ @@ -829,7 +771,6 @@ Throws: `ErrnoException` in case of error. f.close(); } - version (CRuntime_DigitalMars) {} else // Not implemented version (CRuntime_Microsoft) {} else // Not implemented @safe unittest // Test changing mode { @@ -889,22 +830,7 @@ Params: auto modez = stdioOpenmode.tempCString(); detach(); - version (CRuntime_DigitalMars) - { - // This is a re-implementation of DMC's fdopen, but without the - // mucking with the file descriptor. POSIX standard requires the - // new fdopen'd file to retain the given file descriptor's - // position. - auto fp = fopen("NUL", modez); - errnoEnforce(fp, "Cannot open placeholder NUL stream"); - _FLOCK(fp); - auto iob = cast(_iobuf*) fp; - .close(iob._file); - iob._file = fd; - iob._flag &= ~_IOTRAN; - _FUNLOCK(fp); - } - else version (CRuntime_Microsoft) + version (CRuntime_Microsoft) { auto fp = _fdopen(fd, modez); errnoEnforce(fp); @@ -943,26 +869,21 @@ Throws: `ErrnoException` in case of error. import std.format : format; // Create file descriptors from the handles - version (CRuntime_DigitalMars) - auto fd = _handleToFD(handle, FHND_DEVICE); - else // MSVCRT - { - int mode; - modeLoop: - foreach (c; stdioOpenmode) - switch (c) - { - case 'r': mode |= _O_RDONLY; break; - case '+': mode &=~_O_RDONLY; break; - case 'a': mode |= _O_APPEND; break; - case 'b': mode |= _O_BINARY; break; - case 't': mode |= _O_TEXT; break; - case ',': break modeLoop; - default: break; - } + int mode; + modeLoop: + foreach (c; stdioOpenmode) + switch (c) + { + case 'r': mode |= _O_RDONLY; break; + case '+': mode &=~_O_RDONLY; break; + case 'a': mode |= _O_APPEND; break; + case 'b': mode |= _O_BINARY; break; + case 't': mode |= _O_TEXT; break; + case ',': break modeLoop; + default: break; + } - auto fd = _open_osfhandle(cast(intptr_t) handle, mode); - } + auto fd = _open_osfhandle(cast(intptr_t) handle, mode); errnoEnforce(fd >= 0, "Cannot open Windows HANDLE"); fdopen(fd, stdioOpenmode, "HANDLE(%s)".format(handle)); @@ -1186,17 +1107,8 @@ Throws: `ErrnoException` if the file is not opened or the call to `fread` fails. version (Windows) { immutable fileno_t fd = .fileno(_p.handle); - immutable mode = .__setmode(fd, _O_BINARY); - scope(exit) .__setmode(fd, mode); - version (CRuntime_DigitalMars) - { - import core.atomic : atomicOp; - - // https://issues.dlang.org/show_bug.cgi?id=4243 - immutable info = __fhnd_info[fd]; - atomicOp!"&="(__fhnd_info[fd], ~FHND_TEXT); - scope(exit) __fhnd_info[fd] = info; - } + immutable mode = ._setmode(fd, _O_BINARY); + scope(exit) ._setmode(fd, mode); } immutable freadResult = trustedFread(_p.handle, buffer); assert(freadResult <= buffer.length); // fread return guarantee @@ -1276,24 +1188,14 @@ Throws: `ErrnoException` if the file is not opened or if the call to `fwrite` fa version (Windows) { immutable fileno_t fd = .fileno(_p.handle); - immutable oldMode = .__setmode(fd, _O_BINARY); + immutable oldMode = ._setmode(fd, _O_BINARY); if (oldMode != _O_BINARY) { // need to flush the data that was written with the original mode - .__setmode(fd, oldMode); - flush(); // before changing translation mode .__setmode(fd, _O_BINARY); - .__setmode(fd, _O_BINARY); - } - - version (CRuntime_DigitalMars) - { - import core.atomic : atomicOp; - - // https://issues.dlang.org/show_bug.cgi?id=4243 - immutable info = __fhnd_info[fd]; - atomicOp!"&="(__fhnd_info[fd], ~FHND_TEXT); - scope (exit) __fhnd_info[fd] = info; + ._setmode(fd, oldMode); + flush(); // before changing translation mode ._setmode(fd, _O_BINARY); + ._setmode(fd, _O_BINARY); } scope (exit) @@ -1301,7 +1203,7 @@ Throws: `ErrnoException` if the file is not opened or if the call to `fwrite` fa if (oldMode != _O_BINARY) { flush(); - .__setmode(fd, oldMode); + ._setmode(fd, oldMode); } } } @@ -1394,9 +1296,6 @@ Throws: `Exception` if the file is not opened. f.seek(7); assert(f.readln() == "hijklmnopqrstuvwxyz"); - version (CRuntime_DigitalMars) - auto bigOffset = int.max - 100; - else version (CRuntime_Bionic) auto bigOffset = int.max - 100; else @@ -2349,10 +2248,7 @@ Returns the underlying operating system `HANDLE` (Windows only). version (Windows) @property HANDLE windowsHandle() { - version (CRuntime_DigitalMars) - return _fdToHandle(fileno); - else - return cast(HANDLE)_get_osfhandle(fileno); + return cast(HANDLE)_get_osfhandle(fileno); } @@ -3151,11 +3047,11 @@ is empty, throws an `Exception`. In case of an I/O error throws // concept of ANSI/UNICODE mode. fputc doesn't work in UNICODE // mode; fputwc has to be used. So that essentially means // "wide-oriented" for us. - immutable int mode = __setmode(f.fileno, _O_TEXT); + immutable int mode = _setmode(f.fileno, _O_TEXT); // Set some arbitrary mode to obtain the previous one. - if (mode != -1) // __setmode() succeeded + if (mode != -1) // _setmode() succeeded { - __setmode(f.fileno, mode); // Restore previous mode. + _setmode(f.fileno, mode); // Restore previous mode. if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT)) { orientation_ = 1; // wide @@ -3386,8 +3282,6 @@ is empty, throws an `Exception`. In case of an I/O error throws { fileno_t fd; int oldMode; - version (CRuntime_DigitalMars) - ubyte oldInfo; } public: @@ -3407,15 +3301,7 @@ is empty, throws an `Exception`. In case of an I/O error throws { .fflush(fps); // before changing translation mode fd = .fileno(fps); - oldMode = .__setmode(fd, _O_BINARY); - version (CRuntime_DigitalMars) - { - import core.atomic : atomicOp; - - // https://issues.dlang.org/show_bug.cgi?id=4243 - oldInfo = __fhnd_info[fd]; - atomicOp!"&="(__fhnd_info[fd], ~FHND_TEXT); - } + oldMode = ._setmode(fd, _O_BINARY); } } @@ -3429,12 +3315,7 @@ is empty, throws an `Exception`. In case of an I/O error throws version (Windows) { .fflush(fps); // before restoring translation mode - version (CRuntime_DigitalMars) - { - // https://issues.dlang.org/show_bug.cgi?id=4243 - __fhnd_info[fd] = oldInfo; - } - .__setmode(fd, oldMode); + ._setmode(fd, oldMode); } _FUNLOCK(fps); @@ -3887,19 +3768,12 @@ void main() return setlocale(LC_CTYPE, loc.ptr).fromStringz.endsWith(loc); }); scope(exit) () @trusted { setlocale(LC_CTYPE, oldCt); } (); - version (CRuntime_DigitalMars) // DM can't handle Unicode above U+07FF. - { - alias strs = AliasSeq!("xä\u07FE", "yö\u07FF"w); - } - else - { - alias strs = AliasSeq!("xä\U0001F607", "yö\U0001F608"w); - } + alias strs = AliasSeq!("xä\U0001F607", "yö\U0001F608"w); { auto f = File(deleteme, "w"); version (CRuntime_Microsoft) { - () @trusted { __setmode(fileno(f.getFP()), _O_U8TEXT); } (); + () @trusted { _setmode(fileno(f.getFP()), _O_U8TEXT); } (); } else { @@ -5537,120 +5411,7 @@ private struct LockedFile // Private implementation of readln private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation) @safe { - version (CRuntime_DigitalMars) - return () @trusted { - auto lf = LockedFile(fps); - ReadlnAppender app; - app.initialize(buf); - - if (__fhnd_info[lf.fp._file] & FHND_WCHAR) - { /* Stream is in wide characters. - * Read them and convert to chars. - */ - static assert(wchar_t.sizeof == 2); - for (int c = void; (c = lf.fgetwc()) != -1; ) - { - if ((c & ~0x7F) == 0) - { - app.putchar(cast(char) c); - if (c == terminator) - break; - } - else - { - if (c >= 0xD800 && c <= 0xDBFF) - { - int c2 = void; - if ((c2 = lf.fgetwc()) != -1 || - c2 < 0xDC00 && c2 > 0xDFFF) - { - StdioException("unpaired UTF-16 surrogate"); - } - c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00); - } - app.putdchar(cast(dchar) c); - } - } - if (ferror(fps)) - StdioException(); - } - else if (lf.fp._flag & _IONBF) - { - /* Use this for unbuffered I/O, when running - * across buffer boundaries, or for any but the common - * cases. - */ - L1: - int c; - while ((c = lf.fgetc()) != -1) - { - app.putchar(cast(char) c); - if (c == terminator) - { - buf = app.data; - return buf.length; - } - - } - - if (ferror(fps)) - StdioException(); - } - else - { - int u = lf.fp._cnt; - char* p = lf.fp._ptr; - int i; - if (lf.fp._flag & _IOTRAN) - { /* Translated mode ignores \r and treats ^Z as end-of-file - */ - char c; - while (1) - { - if (i == u) // if end of buffer - goto L1; // give up - c = p[i]; - i++; - if (c != '\r') - { - if (c == terminator) - break; - if (c != 0x1A) - continue; - goto L1; - } - else - { if (i != u && p[i] == terminator) - break; - goto L1; - } - } - app.putonly(p[0 .. i]); - app.buf[i - 1] = cast(char) terminator; - if (terminator == '\n' && c == '\r') - i++; - } - else - { - while (1) - { - if (i == u) // if end of buffer - goto L1; // give up - auto c = p[i]; - i++; - if (c == terminator) - break; - } - app.putonly(p[0 .. i]); - } - lf.fp._cnt -= i; - lf.fp._ptr += i; - } - - buf = app.data; - return buf.length; - }(); - else version (CRuntime_Microsoft) + version (CRuntime_Microsoft) { auto lf = LockedFile(fps); diff --git a/std/string.d b/std/string.d index ca14c23747e..21e1ca356f8 100644 --- a/std/string.d +++ b/std/string.d @@ -5942,36 +5942,36 @@ C1[] tr(C1, C2, C3, C4 = immutable char) n = 0; // consider it 'found' at position 0 Lfound: - - // Find the nth character in to[] - dchar nextt; - for (size_t i = 0; i < to.length; ) - { - immutable t = decode(to, i); - if (t == '-' && lastt != dchar.init && i < to.length) + { // create a new scope so that gotos don't skip of declaration of nextt + // Find the nth character in to[] + dchar nextt; + for (size_t i = 0; i < to.length; ) { - nextt = decode(to, i); - n -= nextt - lastt; - if (n < 0) + immutable t = decode(to, i); + if (t == '-' && lastt != dchar.init && i < to.length) { - newc = nextt + n + 1; + nextt = decode(to, i); + n -= nextt - lastt; + if (n < 0) + { + newc = nextt + n + 1; + goto Lnewc; + } + lastt = dchar.init; + continue; + } + if (n == 0) + { newc = t; goto Lnewc; } - lastt = dchar.init; - continue; - } - if (n == 0) - { newc = t; - goto Lnewc; + lastt = t; + nextt = t; + n--; } - lastt = t; - nextt = t; - n--; + if (mod_d) + continue; + newc = nextt; } - if (mod_d) - continue; - newc = nextt; - Lnewc: if (mod_s && modified && newc == lastc) continue; @@ -6331,42 +6331,42 @@ if (isSomeString!S || assertCTFEable!( { // Test the isNumeric(in string) function - assert(isNumeric("1") == true ); - assert(isNumeric("1.0") == true ); - assert(isNumeric("1e-1") == true ); - assert(isNumeric("12345xxxx890") == false ); - assert(isNumeric("567L") == true ); - assert(isNumeric("23UL") == true ); - assert(isNumeric("-123..56f") == false ); - assert(isNumeric("12.3.5.6") == false ); - assert(isNumeric(" 12.356") == false ); - assert(isNumeric("123 5.6") == false ); - assert(isNumeric("1233E-1+1.0e-1i") == true ); - - assert(isNumeric("123.00E-5+1234.45E-12Li") == true); - assert(isNumeric("123.00e-5+1234.45E-12iL") == false); - assert(isNumeric("123.00e-5+1234.45e-12uL") == false); - assert(isNumeric("123.00E-5+1234.45e-12lu") == false); - - assert(isNumeric("123fi") == true); - assert(isNumeric("123li") == true); - assert(isNumeric("--123L") == false); - assert(isNumeric("+123.5UL") == false); - assert(isNumeric("123f") == true); - assert(isNumeric("123.u") == false); + assert(isNumeric("1")); + assert(isNumeric("1.0")); + assert(isNumeric("1e-1")); + assert(!isNumeric("12345xxxx890")); + assert(isNumeric("567L")); + assert(isNumeric("23UL")); + assert(!isNumeric("-123..56f")); + assert(!isNumeric("12.3.5.6")); + assert(!isNumeric(" 12.356")); + assert(!isNumeric("123 5.6")); + assert(isNumeric("1233E-1+1.0e-1i")); + + assert(isNumeric("123.00E-5+1234.45E-12Li")); + assert(!isNumeric("123.00e-5+1234.45E-12iL")); + assert(!isNumeric("123.00e-5+1234.45e-12uL")); + assert(!isNumeric("123.00E-5+1234.45e-12lu")); + + assert(isNumeric("123fi")); + assert(isNumeric("123li")); + assert(!isNumeric("--123L")); + assert(!isNumeric("+123.5UL")); + assert(isNumeric("123f")); + assert(!isNumeric("123.u")); // @@@BUG@@ to!string(float) is not CTFEable. // Related: formatValue(T) if (is(FloatingPointTypeOf!T)) if (!__ctfe) { - assert(isNumeric(to!string(real.nan)) == true); - assert(isNumeric(to!string(-real.infinity)) == true); + assert(isNumeric(to!string(real.nan))); + assert(isNumeric(to!string(-real.infinity))); } string s = "$250.99-"; - assert(isNumeric(s[1 .. s.length - 2]) == true); - assert(isNumeric(s) == false); - assert(isNumeric(s[0 .. s.length - 1]) == false); + assert(isNumeric(s[1 .. $ - 2])); + assert(!isNumeric(s)); + assert(!isNumeric(s[0 .. $ - 1])); }); assert(!isNumeric("-")); diff --git a/std/sumtype.d b/std/sumtype.d index 80ce73d6a75..69c2a49dd7f 100644 --- a/std/sumtype.d +++ b/std/sumtype.d @@ -11,6 +11,15 @@ include: * No dependency on runtime type information (`TypeInfo`). * Compatibility with BetterC. +$(H3 List of examples) + +* [Basic usage](#basic-usage) +* [Matching with an overload set](#matching-with-an-overload-set) +* [Recursive SumTypes](#recursive-sumtypes) +* [Memory corruption](#memory-corruption) (why assignment can be `@system`) +* [Avoiding unintentional matches](#avoiding-unintentional-matches) +* [Multiple dispatch](#multiple-dispatch) + License: Boost License 1.0 Authors: Paul Backus Source: $(PHOBOSSRC std/sumtype.d) @@ -77,52 +86,38 @@ version (D_BetterC) {} else assert(!isFahrenheit(t3)); } -/** $(DIVID introspection-based-matching, $(H3 Introspection-based matching)) +/** $(DIVID matching-with-an-overload-set, $(H3 Matching with an overload set)) + * + * Instead of writing `match` handlers inline as lambdas, you can write them as + * overloads of a function. An `alias` can be used to create an additional + * overload for the `SumType` itself. + * + * For example, with this overload set: * - * In the `length` and `horiz` functions below, the handlers for `match` do not - * specify the types of their arguments. Instead, matching is done based on how - * the argument is used in the body of the handler: any type with `x` and `y` - * properties will be matched by the `rect` handlers, and any type with `r` and - * `theta` properties will be matched by the `polar` handlers. + * --- + * string handle(int n) { return "got an int"; } + * string handle(string s) { return "got a string"; } + * string handle(double d) { return "got a double"; } + * alias handle = match!handle; + * --- + * + * Usage would look like this: */ version (D_BetterC) {} else @safe unittest { - import std.math.operations : isClose; - import std.math.trigonometry : cos; - import std.math.constants : PI; - import std.math.algebraic : sqrt; - - struct Rectangular { double x, y; } - struct Polar { double r, theta; } - alias Vector = SumType!(Rectangular, Polar); - - double length(Vector v) - { - return v.match!( - rect => sqrt(rect.x^^2 + rect.y^^2), - polar => polar.r - ); - } - - double horiz(Vector v) - { - return v.match!( - rect => rect.x, - polar => polar.r * cos(polar.theta) - ); - } + alias ExampleSumType = SumType!(int, string, double); - Vector u = Rectangular(1, 1); - Vector v = Polar(1, PI/4); + ExampleSumType a = 123; + ExampleSumType b = "hello"; + ExampleSumType c = 3.14; - assert(length(u).isClose(sqrt(2.0))); - assert(length(v).isClose(1)); - assert(horiz(u).isClose(1)); - assert(horiz(v).isClose(sqrt(0.5))); + assert(a.handle == "got an int"); + assert(b.handle == "got a string"); + assert(c.handle == "got a double"); } -/** $(DIVID arithmetic-expression-evaluator, $(H3 Arithmetic expression evaluator)) +/** $(DIVID recursive-sumtypes, $(H3 Recursive SumTypes)) * * This example makes use of the special placeholder type `This` to define a * [recursive data type](https://en.wikipedia.org/wiki/Recursive_data_type): an @@ -227,6 +222,10 @@ version (D_BetterC) {} else assert(pprint(*myExpr) == "(a + (2 * b))"); } +// For the "Matching with an overload set" example above +// Needs public import to work with `make publictests` +version (unittest) public import std.internal.test.sumtype_example_overloads; + import std.format.spec : FormatSpec, singleSpec; import std.meta : AliasSeq, Filter, IndexOf = staticIndexOf, Map = staticMap; import std.meta : NoDuplicates; @@ -266,8 +265,7 @@ private enum isInout(T) = is(T == inout); * * The special type `This` can be used as a placeholder to create * self-referential types, just like with `Algebraic`. See the - * ["Arithmetic expression evaluator" example](#arithmetic-expression-evaluator) for - * usage. + * ["Recursive SumTypes" example](#recursive-sumtypes) for usage. * * A `SumType` is initialized by default to hold the `.init` value of its * first member type, just like a regular union. The version identifier @@ -1619,9 +1617,9 @@ enum bool isSumType(T) = is(T : SumType!Args, Args...); * overloads are considered as potential matches. * * Templated handlers are also accepted, and will match any type for which they - * can be [implicitly instantiated](https://dlang.org/glossary.html#ifti). See - * ["Introspection-based matching"](#introspection-based-matching) for an - * example of templated handler usage. + * can be [implicitly instantiated](https://dlang.org/glossary.html#ifti). + * (Remember that a $(DDSUBLINK spec/expression,function_literals, function literal) + * without an explicit argument type is considered a template.) * * If multiple [SumType]s are passed to match, their values are passed to the * handlers as separate arguments, and matching is done for each possible diff --git a/std/utf.d b/std/utf.d index c0cd3863b32..f0d5d4d268b 100644 --- a/std/utf.d +++ b/std/utf.d @@ -2528,8 +2528,8 @@ size_t encode(UseReplacementDchar useReplacementDchar = No.useReplacementDchar)( encode(buf, '\u0000'); assert(buf[0] == '\u0000'); encode(buf, '\uD7FF'); assert(buf[0] == '\uD7FF'); encode(buf, '\uE000'); assert(buf[0] == '\uE000'); - encode(buf, 0xFFFE ); assert(buf[0] == 0xFFFE); - encode(buf, 0xFFFF ); assert(buf[0] == 0xFFFF); + encode(buf, 0xFFFE); assert(buf[0] == 0xFFFE); + encode(buf, 0xFFFF); assert(buf[0] == 0xFFFF); encode(buf, '\U0010FFFF'); assert(buf[0] == '\U0010FFFF'); assertThrown!UTFException(encode(buf, cast(dchar) 0xD800)); @@ -2749,8 +2749,8 @@ void encode(UseReplacementDchar useReplacementDchar = No.useReplacementDchar)( encode(buf, '\u0000'); assert(buf[0] == '\u0000'); encode(buf, '\uD7FF'); assert(buf[1] == '\uD7FF'); encode(buf, '\uE000'); assert(buf[2] == '\uE000'); - encode(buf, 0xFFFE ); assert(buf[3] == 0xFFFE); - encode(buf, 0xFFFF ); assert(buf[4] == 0xFFFF); + encode(buf, 0xFFFE); assert(buf[3] == 0xFFFE); + encode(buf, 0xFFFF); assert(buf[4] == 0xFFFF); encode(buf, '\U0010FFFF'); assert(buf[5] == '\U0010FFFF'); assertThrown!UTFException(encode(buf, cast(dchar) 0xD800));