diff options
Diffstat (limited to 'libphobos/src')
-rw-r--r-- | libphobos/src/MERGE | 2 | ||||
-rw-r--r-- | libphobos/src/std/file.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/getopt.d | 8 | ||||
-rw-r--r-- | libphobos/src/std/range/primitives.d | 11 | ||||
-rw-r--r-- | libphobos/src/std/sumtype.d | 108 |
5 files changed, 110 insertions, 23 deletions
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index b5b939f41b3..e15541e181d 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -1a3e80ec25afab6123cdcfe20186f36f006b68bb +41aaf8c2636df0e2e3ad39933b321d2b4cd231fa The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d index a99c5170afb..b09b82ab85e 100644 --- a/libphobos/src/std/file.d +++ b/libphobos/src/std/file.d @@ -425,10 +425,10 @@ version (Windows) private void[] readImpl(scope const(char)[] name, scope const( fileSize = makeUlong(sizeLow, sizeHigh); return result; } - static trustedReadFile(HANDLE hFile, void *lpBuffer, ulong nNumberOfBytesToRead) + static trustedReadFile(HANDLE hFile, void *lpBuffer, size_t nNumberOfBytesToRead) { // Read by chunks of size < 4GB (Windows API limit) - ulong totalNumRead = 0; + size_t totalNumRead = 0; while (totalNumRead != nNumberOfBytesToRead) { const uint chunkSize = min(nNumberOfBytesToRead - totalNumRead, 0xffff_0000); diff --git a/libphobos/src/std/getopt.d b/libphobos/src/std/getopt.d index 482aae6306a..c1c5cd2b36e 100644 --- a/libphobos/src/std/getopt.d +++ b/libphobos/src/std/getopt.d @@ -438,7 +438,7 @@ GetoptResult getopt(T...)(ref string[] args, T opts) } /// -@system unittest +@safe unittest { auto args = ["prog", "--foo", "-b"]; @@ -1646,11 +1646,13 @@ Params: text = The text to printed at the beginning of the help output. opt = The `Option` extracted from the `getopt` parameter. */ -void defaultGetoptPrinter(string text, Option[] opt) +void defaultGetoptPrinter(string text, Option[] opt) @safe { import std.stdio : stdout; + // stdout global __gshared is trusted with a locked text writer + auto w = (() @trusted => stdout.lockingTextWriter())(); - defaultGetoptFormatter(stdout.lockingTextWriter(), text, opt); + defaultGetoptFormatter(w, text, opt); } /** This function writes the passed text and `Option` into an output range diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d index c092a9d0946..31f58fa5fa9 100644 --- a/libphobos/src/std/range/primitives.d +++ b/libphobos/src/std/range/primitives.d @@ -2055,9 +2055,14 @@ if (isBidirectionalRange!Range) } /** - Moves the front of `r` out and returns it. Leaves `r.front` in a - destroyable state that does not allocate any resources (usually equal - to its `.init` value). + Moves the front of `r` out and returns it. + + If `r.front` is a struct with a destructor or copy constructor defined, it + is reset to its `.init` value after its value is moved. Otherwise, it is + left unchanged. + + In either case, `r.front` is left in a destroyable state that does not + allocate any resources. */ ElementType!R moveFront(R)(R r) { diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d index 5e35a6b9cd5..0dd636ea67b 100644 --- a/libphobos/src/std/sumtype.d +++ b/libphobos/src/std/sumtype.d @@ -533,15 +533,35 @@ public: /** * Assigns a value to a `SumType`. * - * Assigning to a `SumType` is `@system` if any of the - * `SumType`'s members contain pointers or references, since - * those members may be reachable through external references, - * and overwriting them could therefore lead to memory - * corruption. + * If any of the `SumType`'s members other than the one being assigned + * to contain pointers or references, it is possible for the assignment + * to cause memory corruption (see the + * ["Memory corruption" example](#memory-corruption) below for an + * illustration of how). Therefore, such assignments are considered + * `@system`. * * An individual assignment can be `@trusted` if the caller can - * guarantee that there are no outstanding references to $(I any) - * of the `SumType`'s members when the assignment occurs. + * guarantee that there are no outstanding references to any `SumType` + * members that contain pointers or references at the time the + * assignment occurs. + * + * Examples: + * + * $(DIVID memory-corruption, $(H3 Memory corruption)) + * + * This example shows how assignment to a `SumType` can be used to + * cause memory corruption in `@system` code. In `@safe` code, the + * assignment `s = 123` would not be allowed. + * + * --- + * SumType!(int*, int) s = new int; + * s.tryMatch!( + * (ref int* p) { + * s = 123; // overwrites `p` + * return *p; // undefined behavior + * } + * ); + * --- */ ref SumType opAssign(T rhs); } @@ -553,14 +573,35 @@ public: /** * Assigns a value to a `SumType`. * - * Assigning to a `SumType` is `@system` if any of the `SumType`'s - * $(I other) members contain pointers or references, since those - * members may be reachable through external references, and - * overwriting them could therefore lead to memory corruption. + * If any of the `SumType`'s members other than the one being assigned + * to contain pointers or references, it is possible for the assignment + * to cause memory corruption (see the + * ["Memory corruption" example](#memory-corruption) below for an + * illustration of how). Therefore, such assignments are considered + * `@system`. * * An individual assignment can be `@trusted` if the caller can - * guarantee that, when the assignment occurs, there are no - * outstanding references to any such members. + * guarantee that there are no outstanding references to any `SumType` + * members that contain pointers or references at the time the + * assignment occurs. + * + * Examples: + * + * $(DIVID memory-corruption, $(H3 Memory corruption)) + * + * This example shows how assignment to a `SumType` can be used to + * cause memory corruption in `@system` code. In `@safe` code, the + * assignment `s = 123` would not be allowed. + * + * --- + * SumType!(int*, int) s = new int; + * s.tryMatch!( + * (ref int* p) { + * s = 123; // overwrites `p` + * return *p; // undefined behavior + * } + * ); + * --- */ ref SumType opAssign(T rhs) { @@ -1528,7 +1569,27 @@ private enum bool isSumTypeInstance(T) = is(T == SumType!Args, Args...); } /// True if `T` is a [SumType] or implicitly converts to one, otherwise false. -enum bool isSumType(T) = is(T : SumType!Args, Args...); +template isSumType(T) +{ + static if (is(T : SumType!Args, Args...)) + { + enum isSumType = true; + } + else static if (is(T == struct) && __traits(getAliasThis, T).length > 0) + { + // Workaround for https://issues.dlang.org/show_bug.cgi?id=21975 + import std.traits : ReturnType; + + alias AliasThisType = ReturnType!((T t) => + __traits(getMember, t, __traits(getAliasThis, T)[0]) + ); + enum isSumType = .isSumType!AliasThisType; + } + else + { + enum isSumType = false; + } +} /// @safe unittest @@ -1549,6 +1610,25 @@ enum bool isSumType(T) = is(T : SumType!Args, Args...); assert(!isSumType!ContainsSumType); } +@safe unittest +{ + static struct AliasThisVar(T) + { + SumType!T payload; + alias payload this; + } + + static struct AliasThisFunc(T) + { + SumType!T payload; + ref get() { return payload; } + alias get this; + } + + static assert(isSumType!(AliasThisVar!int)); + static assert(isSumType!(AliasThisFunc!int)); +} + /** * Calls a type-appropriate function with the value held in a [SumType]. * |