aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2025-01-05 14:56:59 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-01-10 22:09:00 +0100
commit89629b271827357f81f6f8c7cf28f59919519864 (patch)
treebc6ae2e8d764a128cd9501b30ad96ce7e6360e85 /libphobos/src/std
parentc9353e0fcd0ddc0d48ae8a2b0518f0f82670d708 (diff)
downloadgcc-89629b271827357f81f6f8c7cf28f59919519864.zip
gcc-89629b271827357f81f6f8c7cf28f59919519864.tar.gz
gcc-89629b271827357f81f6f8c7cf28f59919519864.tar.bz2
d: Merge dmd, druntime 34875cd6e1, phobos ebd24da8a
D front-end changes: - Import dmd v2.110.0-beta.1. - `ref' can now be applied to local, static, extern, and global variables. D runtime changes: - Import druntime v2.110.0-beta.1. Phobos changes: - Import phobos v2.110.0-beta.1. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 34875cd6e1. * dmd/VERSION: Bump version to v2.110.0-beta.1. * Make-lang.in (D_FRONTEND_OBJS): Add d/deps.o, d/timetrace.o. * decl.cc (class DeclVisitor): Update for new front-end interface. * expr.cc (class ExprVisitor): Likewise * typeinfo.cc (check_typeinfo_type): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 34875cd6e1. * src/MERGE: Merge upstream phobos ebd24da8a.
Diffstat (limited to 'libphobos/src/std')
-rw-r--r--libphobos/src/std/algorithm/mutation.d23
-rw-r--r--libphobos/src/std/algorithm/sorting.d6
-rw-r--r--libphobos/src/std/array.d29
-rw-r--r--libphobos/src/std/bitmanip.d2
-rw-r--r--libphobos/src/std/datetime/date.d18
-rw-r--r--libphobos/src/std/datetime/timezone.d8
-rw-r--r--libphobos/src/std/exception.d4
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/package.d4
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/region.d4
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d2
-rw-r--r--libphobos/src/std/experimental/allocator/mallocator.d2
-rw-r--r--libphobos/src/std/experimental/allocator/mmap_allocator.d2
-rw-r--r--libphobos/src/std/format/internal/read.d9
-rw-r--r--libphobos/src/std/format/package.d2
-rw-r--r--libphobos/src/std/json.d29
-rw-r--r--libphobos/src/std/math/exponential.d422
-rw-r--r--libphobos/src/std/numeric.d2
-rw-r--r--libphobos/src/std/outbuffer.d9
-rw-r--r--libphobos/src/std/parallelism.d19
-rw-r--r--libphobos/src/std/range/package.d224
-rw-r--r--libphobos/src/std/stdio.d117
-rw-r--r--libphobos/src/std/typecons.d72
-rw-r--r--libphobos/src/std/utf.d2
23 files changed, 560 insertions, 451 deletions
diff --git a/libphobos/src/std/algorithm/mutation.d b/libphobos/src/std/algorithm/mutation.d
index fbef28e..e434d24 100644
--- a/libphobos/src/std/algorithm/mutation.d
+++ b/libphobos/src/std/algorithm/mutation.d
@@ -1071,10 +1071,20 @@ Params:
copy is performed.
*/
void move(T)(ref T source, ref T target)
+if (__traits(compiles, target = T.init))
{
moveImpl(target, source);
}
+/// ditto
+template move(T)
+if (!__traits(compiles, imported!"std.traits".lvalueOf!T = T.init))
+{
+ ///
+ deprecated("Can't move into `target` as `" ~ T.stringof ~ "` can't be assigned")
+ void move(ref T source, ref T target) => moveImpl(target, source);
+}
+
/// For non-struct types, `move` just performs `target = source`:
@safe unittest
{
@@ -1184,6 +1194,19 @@ pure nothrow @safe @nogc unittest
assert(s53 is s51);
}
+@system unittest
+{
+ static struct S
+ {
+ immutable int i;
+ ~this() @safe {}
+ }
+ alias ol = __traits(getOverloads, std.algorithm.mutation, "move", true)[1];
+ static assert(__traits(isDeprecated, ol!S));
+ // uncomment after deprecation
+ //static assert(!__traits(compiles, { S a, b; move(a, b); }));
+}
+
/// Ditto
T move(T)(return scope ref T source)
{
diff --git a/libphobos/src/std/algorithm/sorting.d b/libphobos/src/std/algorithm/sorting.d
index c5b085d..2d16c65 100644
--- a/libphobos/src/std/algorithm/sorting.d
+++ b/libphobos/src/std/algorithm/sorting.d
@@ -2164,12 +2164,12 @@ private void quickSortImpl(alias less, Range)(Range r, size_t depth)
{
import std.algorithm.comparison : min, max;
import std.algorithm.mutation : swap, swapAt;
- import std.conv : to;
alias Elem = ElementType!(Range);
- enum size_t shortSortGetsBetter = max(32, 1024 / Elem.sizeof);
+ enum int size = Elem.sizeof;
+ enum size_t shortSortGetsBetter = max(32, 1024 / size);
static assert(shortSortGetsBetter >= 1, Elem.stringof ~ " "
- ~ to!string(Elem.sizeof));
+ ~ size.stringof);
// partition
while (r.length > shortSortGetsBetter)
diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d
index 494fa29..1ce4a64 100644
--- a/libphobos/src/std/array.d
+++ b/libphobos/src/std/array.d
@@ -295,6 +295,19 @@ if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInf
R().array;
}
+// Test that `array(scope InputRange r)` returns a non-scope array
+// https://issues.dlang.org/show_bug.cgi?id=23300
+@safe pure nothrow unittest
+{
+ @safe int[] fun()
+ {
+ import std.algorithm.iteration : map;
+ int[3] arr = [1, 2, 3];
+ scope r = arr[].map!(x => x + 3);
+ return r.array;
+ }
+}
+
/**
Convert a narrow autodecoding string to an array type that fully supports
random access. This is handled as a special case and always returns an array
@@ -650,6 +663,8 @@ if (isInputRange!Values && isInputRange!Keys)
alias ValueElement = ElementType!Values;
static if (hasElaborateDestructor!ValueElement)
ValueElement.init.__xdtor();
+
+ aa[key] = values.front;
})))
{
() @trusted {
@@ -790,6 +805,20 @@ if (isInputRange!Values && isInputRange!Keys)
assert(assocArray(1.iota, [UnsafeElement()]) == [0: UnsafeElement()]);
}
+@safe unittest
+{
+ struct ValueRange
+ {
+ string front() const @system;
+ @safe:
+ void popFront() {}
+ bool empty() const { return false; }
+ }
+ int[] keys;
+ ValueRange values;
+ static assert(!__traits(compiles, assocArray(keys, values)));
+}
+
/**
Construct a range iterating over an associative array by key/value tuples.
diff --git a/libphobos/src/std/bitmanip.d b/libphobos/src/std/bitmanip.d
index 639b821..0993d34 100644
--- a/libphobos/src/std/bitmanip.d
+++ b/libphobos/src/std/bitmanip.d
@@ -1306,7 +1306,7 @@ public:
/**
Sets the bits of a slice of `BitArray` starting
- at index `start` and ends at index ($D end - 1)
+ at index `start` and ends at index $(D end - 1)
with the values specified by `val`.
*/
void opSliceAssign(bool val, size_t start, size_t end) @nogc pure nothrow
diff --git a/libphobos/src/std/datetime/date.d b/libphobos/src/std/datetime/date.d
index ebdaba4..7526f2d 100644
--- a/libphobos/src/std/datetime/date.d
+++ b/libphobos/src/std/datetime/date.d
@@ -3776,7 +3776,7 @@ public:
enforceValid!"months"(cast(Month) month);
enforceValid!"days"(year, cast(Month) month, day);
- _year = cast(short) year;
+ _year = year.castToYear;
_month = cast(Month) month;
_day = cast(ubyte) day;
}
@@ -3814,6 +3814,7 @@ public:
assertThrown!DateTimeException(Date(1999, 10, 32));
assertThrown!DateTimeException(Date(1999, 11, 31));
assertThrown!DateTimeException(Date(1999, 12, 32));
+ assertThrown!DateTimeException(Date(short.max+1, 1, 1));
assertNotThrown!DateTimeException(Date(1999, 1, 31));
assertNotThrown!DateTimeException(Date(1999, 2, 28));
@@ -3839,6 +3840,7 @@ public:
assertThrown!DateTimeException(Date(-1, 2, 29));
assertThrown!DateTimeException(Date(-2, 2, 29));
assertThrown!DateTimeException(Date(-3, 2, 29));
+ assertThrown!DateTimeException(Date(short.min-1, 1, 1));
}
@@ -4128,7 +4130,7 @@ public:
@property void year(int year) @safe pure
{
enforceValid!"days"(year, _month, _day);
- _year = cast(short) year;
+ _year = year.castToYear;
}
///
@@ -4215,7 +4217,7 @@ public:
{
if (year <= 0)
throw new DateTimeException("The given year is not a year B.C.");
- _year = cast(short)((year - 1) * -1);
+ _year = castToYear((year - 1) * -1);
}
///
@@ -9689,6 +9691,16 @@ if (units == "days")
assert(!valid!"days"(2017, 2, 29));
}
+private short castToYear(int year, string file = __FILE__, size_t line = __LINE__) @safe pure
+{
+ import std.conv : to, ConvOverflowException;
+ import std.format : format;
+
+ try
+ return year.to!short;
+ catch (ConvOverflowException)
+ throw new DateTimeException(format("year %s doesn't fit to Date.", year), file, line);
+}
/++
Params:
diff --git a/libphobos/src/std/datetime/timezone.d b/libphobos/src/std/datetime/timezone.d
index b238918..4b6f27d 100644
--- a/libphobos/src/std/datetime/timezone.d
+++ b/libphobos/src/std/datetime/timezone.d
@@ -3339,7 +3339,7 @@ else version (Posix)
Windows uses a different set of time zone names than the IANA time zone
database does, and how they correspond to one another changes over time
(particularly when Microsoft updates Windows).
- $(HTTP unicode.org/cldr/data/common/supplemental/windowsZones.xml, windowsZones.xml)
+ $(HTTP github.com/unicode-org/cldr/blob/main/common/supplemental/windowsZones.xml, windowsZones.xml)
provides the current conversions (which may or may not match up with what's
on a particular Windows box depending on how up-to-date it is), and
parseTZConversions reads in those conversions from windowsZones.xml so that
@@ -3358,7 +3358,7 @@ else version (Posix)
Params:
windowsZonesXMLText = The text from
- $(HTTP unicode.org/cldr/data/common/supplemental/windowsZones.xml, windowsZones.xml)
+ $(HTTP github.com/unicode-org/cldr/blob/main/common/supplemental/windowsZones.xml, windowsZones.xml)
Throws:
Exception if there is an error while parsing the given XML.
@@ -3372,7 +3372,7 @@ else version (Posix)
// and parse it so that it's guaranteed to be up-to-date, though
// that has the downside that the code needs to worry about the
// site being down or unicode.org changing the URL.
- auto url = "http://unicode.org/cldr/data/common/supplemental/windowsZones.xml";
+ auto url = "https://raw.githubusercontent.com/unicode-org/cldr/main/common/supplemental/windowsZones.xml";
auto conversions2 = parseTZConversions(std.net.curl.get(url));
--------------------
+/
@@ -3458,7 +3458,7 @@ TZConversions parseTZConversions(string windowsZonesXMLText) @safe pure
import std.algorithm.iteration : uniq;
import std.algorithm.sorting : isSorted;
- // Reduced text from http://unicode.org/cldr/data/common/supplemental/windowsZones.xml
+ // Reduced text from https://github.com/unicode-org/cldr/blob/main/common/supplemental/windowsZones.xml
auto sampleFileText =
`<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd">
diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d
index 58a667c..c3024d7 100644
--- a/libphobos/src/std/exception.d
+++ b/libphobos/src/std/exception.d
@@ -1540,9 +1540,9 @@ version (StdUnittest)
}
/+
-Returns true if the field at index `i` in ($D T) shares its address with another field.
+Returns true if the field at index `i` in $(D T) shares its address with another field.
-Note: This does not merelly check if the field is a member of an union, but also that
+Note: This does not merely check if the field is a member of an union, but also that
it is not a single child.
+/
package enum isUnionAliased(T, size_t i) = isUnionAliasedImpl!T(T.tupleof[i].offsetof);
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/package.d b/libphobos/src/std/experimental/allocator/building_blocks/package.d
index 6bc527d..521d7ed 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/package.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/package.d
@@ -43,7 +43,7 @@ alignedReallocate) APIs.))
$(TR $(TDC size_t goodAllocSize(size_t n);, $(POST $(RES) >= n)) $(TD Allocators
customarily allocate memory in discretely-sized chunks. Therefore, a request for
`n` bytes may result in a larger allocation. The extra memory allocated goes
-unused and adds to the so-called $(HTTP goo.gl/YoKffF,internal fragmentation).
+unused and adds to the so-called $(HTTPS en.wikipedia.org/wiki/Fragmentation_(computing)#Internal_fragmentation,internal fragmentation).
The function `goodAllocSize(n)` returns the actual number of bytes that would
be allocated upon a request for `n` bytes. This module defines a default
implementation that returns `n` rounded up to a multiple of the allocator's
@@ -137,7 +137,7 @@ thread-safe or not, this instance may be `shared`.))
$(H2 Sample Assembly)
-The example below features an _allocator modeled after $(HTTP goo.gl/m7329l,
+The example below features an _allocator modeled after $(HTTP jemalloc.net/,
jemalloc), which uses a battery of free-list allocators spaced so as to keep
internal fragmentation to a minimum. The `FList` definitions specify no
bounds for the freelist because the `Segregator` does all size selection in
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/region.d b/libphobos/src/std/experimental/allocator/building_blocks/region.d
index a23746a..736b185 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/region.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/region.d
@@ -904,7 +904,7 @@ version (DragonFlyBSD)
{
// sbrk is deprecated in favor of mmap (we could implement a mmap + MAP_NORESERVE + PROT_NONE version)
// brk has been removed
- // https://www.dragonflydigest.com/2019/02/22/22586.html
+ // https://web.archive.org/web/20221006070113/https://www.dragonflydigest.com/2019/02/22/22586.html
// http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/dc676eaefa61b0f47bbea1c53eab86fd5ccd78c6
// http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/4b5665564ef37dc939a3a9ffbafaab9894c18885
// http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/8618d94a0e2ff8303ad93c123a3fa598c26a116e
@@ -968,7 +968,7 @@ version (Posix) struct SbrkRegion(uint minAlign = platformAlignment)
scope(exit) pthread_mutex_unlock(cast(pthread_mutex_t*) &sbrkMutex) == 0
|| assert(0);
// Assume sbrk returns the old break. Most online documentation confirms
- // that, except for http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf,
+ // that, except for https://web.archive.org/web/20171014020821/http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf,
// which claims the returned value is not portable.
auto p = sbrk(rounded);
if (p == cast(void*) -1)
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d b/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d
index 3770af1..1d1e480 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/stats_collector.d
@@ -134,7 +134,7 @@ enum Options : ulong
bytesNotMoved = 1u << 17,
/**
Measures the sum of extra bytes allocated beyond the bytes requested, i.e.
- the $(HTTP goo.gl/YoKffF, internal fragmentation). This is the current
+ the $(HTTPS en.wikipedia.org/wiki/Fragmentation_(computing)#Internal_fragmentation, internal fragmentation). This is the current
effective number of slack bytes, and it goes up and down with time.
*/
bytesSlack = 1u << 18,
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 3d4dc9a..087dbec 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -52,7 +52,7 @@ struct Mallocator
import core.memory : pureRealloc;
if (!s)
{
- // fuzzy area in the C standard, see http://goo.gl/ZpWeSE
+ // fuzzy area in the C standard, see https://stackoverflow.com/questions/6502077/malloc-and-realloc-functions
// so just deallocate and nullify the pointer
deallocate(b);
b = null;
diff --git a/libphobos/src/std/experimental/allocator/mmap_allocator.d b/libphobos/src/std/experimental/allocator/mmap_allocator.d
index 4151d0e..494d5a3 100644
--- a/libphobos/src/std/experimental/allocator/mmap_allocator.d
+++ b/libphobos/src/std/experimental/allocator/mmap_allocator.d
@@ -60,7 +60,7 @@ struct MmapAllocator
// http://man7.org/linux/man-pages/man2/mmap.2.html
package alias allocateZeroed = allocate;
else version (NetBSD)
- // http://netbsd.gw.com/cgi-bin/man-cgi?mmap+2+NetBSD-current
+ // https://man.netbsd.org/mmap.2
package alias allocateZeroed = allocate;
else version (Solaris)
// https://docs.oracle.com/cd/E88353_01/html/E37841/mmap-2.html
diff --git a/libphobos/src/std/format/internal/read.d b/libphobos/src/std/format/internal/read.d
index 9130499..597898c 100644
--- a/libphobos/src/std/format/internal/read.d
+++ b/libphobos/src/std/format/internal/read.d
@@ -161,15 +161,16 @@ if (isInputRange!Range && isSomeChar!T && !is(T == enum) && isSomeChar!(ElementT
enforceFmt(find(acceptedSpecs!T, spec.spec).length,
text("Wrong unformat specifier '%", spec.spec , "' for ", T.stringof));
- static if (T.sizeof == 1)
+ enum int size = T.sizeof;
+ static if (size == 1)
return unformatValue!ubyte(input, spec);
- else static if (T.sizeof == 2)
+ else static if (size == 2)
return unformatValue!ushort(input, spec);
- else static if (T.sizeof == 4)
+ else static if (size == 4)
return unformatValue!uint(input, spec);
else
static assert(false, T.stringof ~ ".sizeof must be 1, 2, or 4 not " ~
- to!string(T.sizeof));
+ size.stringof);
}
T unformatValueImpl(T, Range, Char)(ref Range input, scope const ref FormatSpec!Char fmt)
diff --git a/libphobos/src/std/format/package.d b/libphobos/src/std/format/package.d
index f1d4705..a78e1b3 100644
--- a/libphobos/src/std/format/package.d
+++ b/libphobos/src/std/format/package.d
@@ -358,7 +358,7 @@ $(BOOKTABLE ,
Default precision is large enough to add all digits
of the integral value.
- In case of ($B 'a') and $(B 'A'), the integral digit can be
+ In case of $(B 'a') and $(B 'A'), the integral digit can be
any hexadecimal digit.
)
)
diff --git a/libphobos/src/std/json.d b/libphobos/src/std/json.d
index 6e94a5d..9dcec89 100644
--- a/libphobos/src/std/json.d
+++ b/libphobos/src/std/json.d
@@ -13,7 +13,7 @@ also $(LINK https://forum.dlang.org/post/dzfyaxypmkdrpakmycjv@forum.dlang.org).)
Copyright: Copyright Jeremie Pelletier 2008 - 2009.
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: Jeremie Pelletier, David Herberth
-References: $(LINK http://json.org/), $(LINK http://seriot.ch/parsing_json.html)
+References: $(LINK http://json.org/), $(LINK https://seriot.ch/projects/parsing_json.html)
Source: $(PHOBOSSRC std/json.d)
*/
/*
@@ -804,7 +804,22 @@ struct JSONValue
assert(j["author"].str == "Walter");
}
- ///
+ /**
+ * Compare two JSONValues for equality
+ *
+ * JSON arrays and objects are compared deeply. The order of object keys does not matter.
+ *
+ * Floating point numbers are compared for exact equality, not approximal equality.
+ *
+ * Different number types (unsigned, signed, and floating) will be compared by converting
+ * them to a common type, in the same way that comparison of built-in D `int`, `uint` and
+ * `float` works.
+ *
+ * Other than that, types must match exactly.
+ * Empty arrays are not equal to empty objects, and booleans are never equal to integers.
+ *
+ * Returns: whether this `JSONValue` is equal to `rhs`
+ */
bool opEquals(const JSONValue rhs) const @nogc nothrow pure @safe
{
return opEquals(rhs);
@@ -871,9 +886,13 @@ struct JSONValue
///
@safe unittest
{
- assert(JSONValue(0u) == JSONValue(0));
- assert(JSONValue(0u) == JSONValue(0.0));
- assert(JSONValue(0) == JSONValue(0.0));
+ assert(JSONValue(10).opEquals(JSONValue(10.0)));
+ assert(JSONValue(10) != (JSONValue(10.5)));
+
+ assert(JSONValue(1) != JSONValue(true));
+ assert(JSONValue.emptyArray != JSONValue.emptyObject);
+
+ assert(parseJSON(`{"a": 1, "b": 2}`).opEquals(parseJSON(`{"b": 2, "a": 1}`)));
}
/// Implements the foreach `opApply` interface for json arrays.
diff --git a/libphobos/src/std/math/exponential.d b/libphobos/src/std/math/exponential.d
index 8fcd88f..7a72f42 100644
--- a/libphobos/src/std/math/exponential.d
+++ b/libphobos/src/std/math/exponential.d
@@ -422,217 +422,7 @@ if (isIntegral!I && isFloatingPoint!F)
Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @nogc @trusted pure nothrow
if (isFloatingPoint!(F) && isFloatingPoint!(G))
{
- import core.math : fabs, sqrt;
- import std.math.traits : isInfinity, isNaN, signbit;
-
- alias Float = typeof(return);
-
- static real impl(real x, real y) @nogc pure nothrow
- {
- // Special cases.
- if (isNaN(y))
- return y;
- if (isNaN(x) && y != 0.0)
- return x;
-
- // Even if x is NaN.
- if (y == 0.0)
- return 1.0;
- if (y == 1.0)
- return x;
-
- if (isInfinity(y))
- {
- if (isInfinity(x))
- {
- if (!signbit(y) && !signbit(x))
- return F.infinity;
- else
- return F.nan;
- }
- else if (fabs(x) > 1)
- {
- if (signbit(y))
- return +0.0;
- else
- return F.infinity;
- }
- else if (fabs(x) == 1)
- {
- return F.nan;
- }
- else // < 1
- {
- if (signbit(y))
- return F.infinity;
- else
- return +0.0;
- }
- }
- if (isInfinity(x))
- {
- if (signbit(x))
- {
- long i = cast(long) y;
- if (y > 0.0)
- {
- if (i == y && i & 1)
- return -F.infinity;
- else if (i == y)
- return F.infinity;
- else
- return -F.nan;
- }
- else if (y < 0.0)
- {
- if (i == y && i & 1)
- return -0.0;
- else if (i == y)
- return +0.0;
- else
- return F.nan;
- }
- }
- else
- {
- if (y > 0.0)
- return F.infinity;
- else if (y < 0.0)
- return +0.0;
- }
- }
-
- if (x == 0.0)
- {
- if (signbit(x))
- {
- long i = cast(long) y;
- if (y > 0.0)
- {
- if (i == y && i & 1)
- return -0.0;
- else
- return +0.0;
- }
- else if (y < 0.0)
- {
- if (i == y && i & 1)
- return -F.infinity;
- else
- return F.infinity;
- }
- }
- else
- {
- if (y > 0.0)
- return +0.0;
- else if (y < 0.0)
- return F.infinity;
- }
- }
- if (x == 1.0)
- return 1.0;
-
- if (y >= F.max)
- {
- if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0))
- return 0.0;
- if (x > 1.0 || x < -1.0)
- return F.infinity;
- }
- if (y <= -F.max)
- {
- if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0))
- return F.infinity;
- if (x > 1.0 || x < -1.0)
- return 0.0;
- }
-
- if (x >= F.max)
- {
- if (y > 0.0)
- return F.infinity;
- else
- return 0.0;
- }
- if (x <= -F.max)
- {
- long i = cast(long) y;
- if (y > 0.0)
- {
- if (i == y && i & 1)
- return -F.infinity;
- else
- return F.infinity;
- }
- else if (y < 0.0)
- {
- if (i == y && i & 1)
- return -0.0;
- else
- return +0.0;
- }
- }
-
- // Integer power of x.
- long iy = cast(long) y;
- if (iy == y && fabs(y) < 32_768.0)
- return pow(x, iy);
-
- real sign = 1.0;
- if (x < 0)
- {
- // Result is real only if y is an integer
- // Check for a non-zero fractional part
- enum maxOdd = pow(2.0L, real.mant_dig) - 1.0L;
- static if (maxOdd > ulong.max)
- {
- // Generic method, for any FP type
- import std.math.rounding : floor;
- if (floor(y) != y)
- return sqrt(x); // Complex result -- create a NaN
-
- const hy = 0.5 * y;
- if (floor(hy) != hy)
- sign = -1.0;
- }
- else
- {
- // Much faster, if ulong has enough precision
- const absY = fabs(y);
- if (absY <= maxOdd)
- {
- const uy = cast(ulong) absY;
- if (uy != absY)
- return sqrt(x); // Complex result -- create a NaN
-
- if (uy & 1)
- sign = -1.0;
- }
- }
- x = -x;
- }
- version (INLINE_YL2X)
- {
- // If x > 0, x ^^ y == 2 ^^ ( y * log2(x) )
- // TODO: This is not accurate in practice. A fast and accurate
- // (though complicated) method is described in:
- // "An efficient rounding boundary test for pow(x, y)
- // in double precision", C.Q. Lauter and V. Lefèvre, INRIA (2007).
- return sign * exp2( core.math.yl2x(x, y) );
- }
- else
- {
- // If x > 0, x ^^ y == 2 ^^ ( y * log2(x) )
- // TODO: This is not accurate in practice. A fast and accurate
- // (though complicated) method is described in:
- // "An efficient rounding boundary test for pow(x, y)
- // in double precision", C.Q. Lauter and V. Lefèvre, INRIA (2007).
- Float w = exp2(y * log2(x));
- return sign * w;
- }
- }
- return impl(x, y);
+ return _powImpl(x, y);
}
///
@@ -802,6 +592,216 @@ if (isFloatingPoint!(F) && isFloatingPoint!(G))
assert(pow(-real.infinity, 0.0) == 1.0);
}
+private real _powImpl(real x, real y) @safe @nogc pure nothrow
+{
+ alias F = real;
+ import core.math : fabs, sqrt;
+ import std.math.traits : isInfinity, isNaN, signbit;
+
+ // Special cases.
+ if (isNaN(y))
+ return y;
+ if (isNaN(x) && y != 0.0)
+ return x;
+
+ // Even if x is NaN.
+ if (y == 0.0)
+ return 1.0;
+ if (y == 1.0)
+ return x;
+
+ if (isInfinity(y))
+ {
+ if (isInfinity(x))
+ {
+ if (!signbit(y) && !signbit(x))
+ return F.infinity;
+ else
+ return F.nan;
+ }
+ else if (fabs(x) > 1)
+ {
+ if (signbit(y))
+ return +0.0;
+ else
+ return F.infinity;
+ }
+ else if (fabs(x) == 1)
+ {
+ return F.nan;
+ }
+ else // < 1
+ {
+ if (signbit(y))
+ return F.infinity;
+ else
+ return +0.0;
+ }
+ }
+ if (isInfinity(x))
+ {
+ if (signbit(x))
+ {
+ long i = cast(long) y;
+ if (y > 0.0)
+ {
+ if (i == y && i & 1)
+ return -F.infinity;
+ else if (i == y)
+ return F.infinity;
+ else
+ return -F.nan;
+ }
+ else if (y < 0.0)
+ {
+ if (i == y && i & 1)
+ return -0.0;
+ else if (i == y)
+ return +0.0;
+ else
+ return F.nan;
+ }
+ }
+ else
+ {
+ if (y > 0.0)
+ return F.infinity;
+ else if (y < 0.0)
+ return +0.0;
+ }
+ }
+
+ if (x == 0.0)
+ {
+ if (signbit(x))
+ {
+ long i = cast(long) y;
+ if (y > 0.0)
+ {
+ if (i == y && i & 1)
+ return -0.0;
+ else
+ return +0.0;
+ }
+ else if (y < 0.0)
+ {
+ if (i == y && i & 1)
+ return -F.infinity;
+ else
+ return F.infinity;
+ }
+ }
+ else
+ {
+ if (y > 0.0)
+ return +0.0;
+ else if (y < 0.0)
+ return F.infinity;
+ }
+ }
+ if (x == 1.0)
+ return 1.0;
+
+ if (y >= F.max)
+ {
+ if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0))
+ return 0.0;
+ if (x > 1.0 || x < -1.0)
+ return F.infinity;
+ }
+ if (y <= -F.max)
+ {
+ if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0))
+ return F.infinity;
+ if (x > 1.0 || x < -1.0)
+ return 0.0;
+ }
+
+ if (x >= F.max)
+ {
+ if (y > 0.0)
+ return F.infinity;
+ else
+ return 0.0;
+ }
+ if (x <= -F.max)
+ {
+ long i = cast(long) y;
+ if (y > 0.0)
+ {
+ if (i == y && i & 1)
+ return -F.infinity;
+ else
+ return F.infinity;
+ }
+ else if (y < 0.0)
+ {
+ if (i == y && i & 1)
+ return -0.0;
+ else
+ return +0.0;
+ }
+ }
+
+ // Integer power of x.
+ long iy = cast(long) y;
+ if (iy == y && fabs(y) < 32_768.0)
+ return pow(x, iy);
+
+ real sign = 1.0;
+ if (x < 0)
+ {
+ // Result is real only if y is an integer
+ // Check for a non-zero fractional part
+ enum maxOdd = pow(2.0L, real.mant_dig) - 1.0L;
+ static if (maxOdd > ulong.max)
+ {
+ // Generic method, for any FP type
+ import std.math.rounding : floor;
+ if (floor(y) != y)
+ return sqrt(x); // Complex result -- create a NaN
+
+ const hy = 0.5 * y;
+ if (floor(hy) != hy)
+ sign = -1.0;
+ }
+ else
+ {
+ // Much faster, if ulong has enough precision
+ const absY = fabs(y);
+ if (absY <= maxOdd)
+ {
+ const uy = cast(ulong) absY;
+ if (uy != absY)
+ return sqrt(x); // Complex result -- create a NaN
+
+ if (uy & 1)
+ sign = -1.0;
+ }
+ }
+ x = -x;
+ }
+ version (INLINE_YL2X)
+ {
+ // If x > 0, x ^^ y == 2 ^^ ( y * log2(x) )
+ // TODO: This is not accurate in practice. A fast and accurate
+ // (though complicated) method is described in:
+ // "An efficient rounding boundary test for pow(x, y)
+ // in double precision", C.Q. Lauter and V. Lefèvre, INRIA (2007).
+ return sign * exp2( core.math.yl2x(x, y) );
+ }
+ else
+ {
+ // If x > 0, x ^^ y == 2 ^^ ( y * log2(x) )
+ // TODO: This is not accurate in practice. A fast and accurate
+ // (though complicated) method is described in:
+ // "An efficient rounding boundary test for pow(x, y)
+ // in double precision", C.Q. Lauter and V. Lefèvre, INRIA (2007).
+ auto w = exp2(y * log2(x));
+ return sign * w;
+ }
+}
+
/** Computes the value of a positive integer `x`, raised to the power `n`, modulo `m`.
*
* Params:
diff --git a/libphobos/src/std/numeric.d b/libphobos/src/std/numeric.d
index 648b70e..9f0fb56 100644
--- a/libphobos/src/std/numeric.d
+++ b/libphobos/src/std/numeric.d
@@ -3405,7 +3405,7 @@ private:
// This algorithm works by performing the even and odd parts of our FFT
// using the "two for the price of one" method mentioned at
- // http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM#Head521
+ // https://web.archive.org/web/20180312110051/http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM#Head521
// by making the odd terms into the imaginary components of our new FFT,
// and then using symmetry to recombine them.
void fftImplPureReal(Ret, R)(R range, Ret buf) const
diff --git a/libphobos/src/std/outbuffer.d b/libphobos/src/std/outbuffer.d
index 92af9a9..f6d4ba8 100644
--- a/libphobos/src/std/outbuffer.d
+++ b/libphobos/src/std/outbuffer.d
@@ -22,9 +22,10 @@ import std.traits : isSomeString;
* OutBuffer's byte order is the format native to the computer.
* To control the byte order (endianness), use a class derived
* from OutBuffer.
+ *
* OutBuffer's internal buffer is allocated with the GC. Pointers
* stored into the buffer are scanned by the GC, but you have to
- * ensure proper alignment, e.g. by using alignSize((void*).sizeof).
+ * ensure proper alignment, e.g. by using `alignSize((void*).sizeof)`.
*/
class OutBuffer
@@ -297,7 +298,7 @@ class OutBuffer
* Append output of C's vprintf() to internal buffer.
*/
- void vprintf(scope string format, va_list args) @trusted nothrow
+ void vprintf(scope string format, va_list args) @system nothrow
{
import core.stdc.stdio : vsnprintf;
import core.stdc.stdlib : alloca;
@@ -342,7 +343,7 @@ class OutBuffer
* Append output of C's printf() to internal buffer.
*/
- void printf(scope string format, ...) @trusted
+ void printf(scope string format, ...) @system
{
va_list ap;
va_start(ap, format);
@@ -475,7 +476,7 @@ class OutBuffer
buf.write("hello");
buf.write(cast(byte) 0x20);
buf.write("world");
- buf.printf(" %d", 62665);
+ buf.writef(" %d", 62665);
assert(cmp(buf.toString(), "hello world 62665") == 0);
buf.clear();
diff --git a/libphobos/src/std/parallelism.d b/libphobos/src/std/parallelism.d
index fadb4c1..7525d9b 100644
--- a/libphobos/src/std/parallelism.d
+++ b/libphobos/src/std/parallelism.d
@@ -884,11 +884,26 @@ identical to the non-@safe case, but safety introduces some restrictions:
*/
@trusted auto task(F, Args...)(F fun, Args args)
-if (is(typeof(fun(args))) && isSafeTask!F)
+if (__traits(compiles, () @safe => fun(args)) && isSafeTask!F)
{
return new Task!(run, F, Args)(fun, args);
}
+@safe unittest
+{
+ static struct Oops {
+ int convert() {
+ *cast(int*) 0xcafebabe = 0xdeadbeef;
+ return 0;
+ }
+ alias convert this;
+ }
+ static void foo(int) @safe {}
+
+ static assert(!__traits(compiles, task(&foo, Oops.init)));
+ static assert(!__traits(compiles, scopedTask(&foo, Oops.init)));
+}
+
/**
These functions allow the creation of `Task` objects on the stack rather
than the GC heap. The lifetime of a `Task` created by `scopedTask`
@@ -928,7 +943,7 @@ if (is(typeof(delegateOrFp(args))) && !isSafeTask!F)
/// Ditto
@trusted auto scopedTask(F, Args...)(F fun, Args args)
-if (is(typeof(fun(args))) && isSafeTask!F)
+if (__traits(compiles, () @safe => fun(args)) && isSafeTask!F)
{
auto ret = Task!(run, F, Args)(fun, args);
ret.isScoped = true;
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index b6fddf7..e2a2d7d 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -6070,10 +6070,13 @@ nothrow pure @system unittest
Generate lockstep's opApply function as a mixin string.
If withIndex is true prepend a size_t index to the delegate.
*/
-private string lockstepMixin(Ranges...)(bool withIndex, bool reverse)
+private struct LockstepMixin(Ranges...)
{
+ import std.conv : text;
import std.format : format;
+ string name;
+ string implName;
string[] params;
string[] emptyChecks;
string[] dgArgs;
@@ -6081,76 +6084,101 @@ private string lockstepMixin(Ranges...)(bool withIndex, bool reverse)
string indexDef;
string indexInc;
- if (withIndex)
+@safe pure:
+ this(bool withIndex, bool reverse)
{
- params ~= "size_t";
- dgArgs ~= "index";
- if (reverse)
+ if (withIndex)
{
- indexDef = q{
- size_t index = ranges[0].length-1;
- enforce(_stoppingPolicy == StoppingPolicy.requireSameLength,
- "lockstep can only be used with foreach_reverse when stoppingPolicy == requireSameLength");
+ params ~= "size_t";
+ dgArgs ~= "index";
+ if (reverse)
+ {
+ indexDef = q{
+ size_t index = ranges[0].length - 1;
+ enforce(this.stoppingPolicy == StoppingPolicy.requireSameLength,
+ "lockstep can only be used with foreach_reverse when stoppingPolicy == requireSameLength");
- foreach (range; ranges[1..$])
- enforce(range.length == ranges[0].length);
- };
- indexInc = "--index;";
+ foreach (range; ranges[1 .. $])
+ enforce(range.length == ranges[0].length);
+ };
+ indexInc = "--index;";
+ }
+ else
+ {
+ indexDef = "size_t index = 0;";
+ indexInc = "++index;";
+ }
}
- else
+
+ foreach (idx, Range; Ranges)
{
- indexDef = "size_t index = 0;";
- indexInc = "++index;";
+ params ~= format("%sElementType!(Ranges[%s])", hasLvalueElements!Range ? "ref " : "", idx);
+ emptyChecks ~= format("!ranges[%s].empty", idx);
+ if (reverse)
+ {
+ dgArgs ~= format("ranges[%s].back", idx);
+ popFronts ~= format("ranges[%s].popBack();", idx);
+ }
+ else
+ {
+ dgArgs ~= format("ranges[%s].front", idx);
+ popFronts ~= format("ranges[%s].popFront();", idx);
+ }
}
- }
- foreach (idx, Range; Ranges)
- {
- params ~= format("%sElementType!(Ranges[%s])", hasLvalueElements!Range ? "ref " : "", idx);
- emptyChecks ~= format("!ranges[%s].empty", idx);
if (reverse)
{
- dgArgs ~= format("ranges[%s].back", idx);
- popFronts ~= format("ranges[%s].popBack();", idx);
+ name = "opApplyReverse";
+ if (withIndex) implName = "opApplyReverseIdxImpl";
+ else implName = "opApplyReverseImpl";
}
else
{
- dgArgs ~= format("ranges[%s].front", idx);
- popFronts ~= format("ranges[%s].popFront();", idx);
+ name = "opApply";
+ if (withIndex) implName = "opApplyIdxImpl";
+ else implName = "opApplyImpl";
}
}
- string name = reverse ? "opApplyReverse" : "opApply";
-
- return format(
- q{
- int %s(scope int delegate(%s) dg)
- {
- import std.exception : enforce;
-
- auto ranges = _ranges;
- int res;
- %s
+const:
+ string getAlias()
+ {
+ return format(q{
+ alias %s = %s!(int delegate(%-(%s%|, %)));
+ },
+ name, implName, params
+ );
+ }
- while (%s)
+ string getImpl()
+ {
+ return format(q{
+ int %s(DG)(scope DG dg) scope
{
- res = dg(%s);
- if (res) break;
- %s
+ import std.exception : enforce;
+
+ auto ranges = this.ranges;
%s
- }
- if (_stoppingPolicy == StoppingPolicy.requireSameLength)
- {
- foreach (range; ranges)
- enforce(range.empty);
+ while (%-(%s%| && %))
+ {
+ if (int result = dg(%-(%s%|, %))) return result;
+ %-(%s%|
+ %)
+ %s
+ }
+
+ if (this.stoppingPolicy == StoppingPolicy.requireSameLength)
+ {
+ foreach (range; ranges)
+ enforce(range.empty);
+ }
+ return 0;
}
- return res;
- }
- }, name, params.join(", "), indexDef,
- emptyChecks.join(" && "), dgArgs.join(", "),
- popFronts.join("\n "),
- indexInc);
+ },
+ implName, indexDef, emptyChecks, dgArgs, popFronts, indexInc
+ );
+ }
}
/**
@@ -6170,10 +6198,6 @@ private string lockstepMixin(Ranges...)(bool withIndex, bool reverse)
By default `StoppingPolicy` is set to `StoppingPolicy.shortest`.
- Limitations: The `pure`, `@safe`, `@nogc`, or `nothrow` attributes cannot be
- inferred for `lockstep` iteration. $(LREF zip) can infer the first two due to
- a different implementation.
-
See_Also: $(LREF zip)
`lockstep` is similar to $(LREF zip), but `zip` bundles its
@@ -6184,41 +6208,53 @@ private string lockstepMixin(Ranges...)(bool withIndex, bool reverse)
struct Lockstep(Ranges...)
if (Ranges.length > 1 && allSatisfy!(isInputRange, Ranges))
{
+ private Ranges ranges;
+ private StoppingPolicy stoppingPolicy;
+
///
- this(R ranges, StoppingPolicy sp = StoppingPolicy.shortest)
+ this(Ranges ranges, StoppingPolicy sp = StoppingPolicy.shortest)
{
import std.exception : enforce;
- _ranges = ranges;
+ this.ranges = ranges;
enforce(sp != StoppingPolicy.longest,
- "Can't use StoppingPolicy.Longest on Lockstep.");
- _stoppingPolicy = sp;
+ "Can't use StoppingPolicy.Longest on Lockstep.");
+ this.stoppingPolicy = sp;
}
- mixin(lockstepMixin!Ranges(false, false));
- mixin(lockstepMixin!Ranges(true, false));
+ private enum lockstepMixinFF = LockstepMixin!Ranges(withIndex: false, reverse: false);
+ mixin(lockstepMixinFF.getImpl);
+
+ private enum lockstepMixinTF = LockstepMixin!Ranges(withIndex: true, reverse: false);
+ mixin(lockstepMixinTF.getImpl);
+
+ mixin(lockstepMixinFF.getAlias);
+ mixin(lockstepMixinTF.getAlias);
+
static if (allSatisfy!(isBidirectionalRange, Ranges))
{
- mixin(lockstepMixin!Ranges(false, true));
+ private enum lockstepMixinFT = LockstepMixin!Ranges(withIndex: false, reverse: true);
+ mixin(lockstepMixinFT.getImpl);
static if (allSatisfy!(hasLength, Ranges))
{
- mixin(lockstepMixin!Ranges(true, true));
+ private enum lockstepMixinTT = LockstepMixin!Ranges(withIndex: true, reverse: true);
+ mixin(lockstepMixinTT.getImpl);
+ mixin(lockstepMixinTT.getAlias);
}
else
{
- mixin(lockstepReverseFailMixin!Ranges(true));
+ mixin(lockstepReverseFailMixin!Ranges(withIndex: true));
+ alias opApplyReverse = opApplyReverseIdxFail;
}
+ mixin(lockstepMixinFT.getAlias);
}
else
{
- mixin(lockstepReverseFailMixin!Ranges(false));
- mixin(lockstepReverseFailMixin!Ranges(true));
+ mixin(lockstepReverseFailMixin!Ranges(withIndex: false));
+ mixin(lockstepReverseFailMixin!Ranges(withIndex: true));
+ alias opApplyReverse = opApplyReverseFail;
+ alias opApplyReverse = opApplyReverseIdxFail;
}
-
-private:
- alias R = Ranges;
- R _ranges;
- StoppingPolicy _stoppingPolicy;
}
/// Ditto
@@ -6238,33 +6274,39 @@ if (allSatisfy!(isInputRange, Ranges))
}
///
-@system unittest
+pure @safe unittest
{
- auto arr1 = [1,2,3,4,5,100];
- auto arr2 = [6,7,8,9,10];
+ int[6] arr1 = [1,2,3,4,5,100];
+ int[5] arr2 = [6,7,8,9,10];
- foreach (ref a, b; lockstep(arr1, arr2))
- {
- a += b;
- }
+ foreach (ref a, b; lockstep(arr1[], arr2[]))
+ {
+ a += b;
+ }
- assert(arr1 == [7,9,11,13,15,100]);
+ assert(arr1 == [7,9,11,13,15,100]);
+}
- /// Lockstep also supports iterating with an index variable:
- foreach (index, a, b; lockstep(arr1, arr2))
- {
- assert(arr1[index] == a);
- assert(arr2[index] == b);
- }
+/// Lockstep also supports iterating with an index variable:
+pure @safe unittest
+{
+ int[3] arr1 = [1,2,3];
+ int[3] arr2 = [4,5,6];
+
+ foreach (index, a, b; lockstep(arr1[], arr2[]))
+ {
+ assert(arr1[index] == a);
+ assert(arr2[index] == b);
+ }
}
// https://issues.dlang.org/show_bug.cgi?id=15860: foreach_reverse on lockstep
-@system unittest
+pure @safe unittest
{
auto arr1 = [0, 1, 2, 3];
auto arr2 = [4, 5, 6, 7];
- size_t n = arr1.length -1;
+ size_t n = arr1.length - 1;
foreach_reverse (index, a, b; lockstep(arr1, arr2, StoppingPolicy.requireSameLength))
{
assert(n == index);
@@ -6283,7 +6325,7 @@ if (allSatisfy!(isInputRange, Ranges))
}
}
-@system unittest
+pure @safe unittest
{
import std.algorithm.iteration : filter;
import std.conv : to;
@@ -6380,7 +6422,7 @@ if (allSatisfy!(isInputRange, Ranges))
foreach (x, y; lockstep(iota(0, 10), iota(0, 10))) { }
}
-@system unittest
+pure @safe unittest
{
struct RvalueRange
{
@@ -6436,11 +6478,11 @@ private string lockstepReverseFailMixin(Ranges...)(bool withIndex)
return format(
q{
- int opApplyReverse()(scope int delegate(%s) dg)
+ int opApplyReverse%sFail()(scope int delegate(%s) dg)
{
static assert(false, "%s");
}
- }, params.join(", "), message);
+ }, withIndex ? "Idx" : "" , params.join(", "), message);
}
// For generic programming, make sure Lockstep!(Range) is well defined for a
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index 8caa9b3..b474460 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -220,31 +220,6 @@ version (CRuntime_Microsoft)
private alias _FGETWC = _fgetwc_nolock;
private alias _FLOCK = _lock_file;
private alias _FUNLOCK = _unlock_file;
-
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FPUTC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FPUTC = _fputc_nolock;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FPUTWC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FPUTWC = _fputwc_nolock;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FGETC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FGETC = _fgetc_nolock;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FGETWC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FGETWC = _fgetwc_nolock;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FLOCK was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FLOCK = _lock_file;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FUNLOCK was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FUNLOCK = _unlock_file;
}
else version (CRuntime_Glibc)
{
@@ -254,31 +229,6 @@ else version (CRuntime_Glibc)
private alias _FGETWC = fgetwc_unlocked;
private alias _FLOCK = core.sys.posix.stdio.flockfile;
private alias _FUNLOCK = core.sys.posix.stdio.funlockfile;
-
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FPUTC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FPUTC = fputc_unlocked;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FPUTWC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FPUTWC = fputwc_unlocked;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FGETC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FGETC = fgetc_unlocked;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FGETWC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FGETWC = fgetwc_unlocked;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FLOCK was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FLOCK = core.sys.posix.stdio.flockfile;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FUNLOCK was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FUNLOCK = core.sys.posix.stdio.funlockfile;
}
else version (GENERIC_IO)
{
@@ -304,52 +254,6 @@ else version (GENERIC_IO)
{
static assert(0, "don't know how to lock files on GENERIC_IO");
}
-
- // @@@DEPRECATED_2.107@@@
- deprecated("internal function fputc_unlocked was unintentionally available "
- ~ "from std.stdio and will be removed afer 2.107")
- extern (C) pragma(mangle, fputc.mangleof) int fputc_unlocked(int c, _iobuf* fp);
- // @@@DEPRECATED_2.107@@@
- deprecated("internal function fputwc_unlocked was unintentionally available "
- ~ "from std.stdio and will be removed afer 2.107")
- extern (C) pragma(mangle, core.stdc.wchar_.fputwc.mangleof) int fputwc_unlocked(wchar_t c, _iobuf* fp);
- // @@@DEPRECATED_2.107@@@
- deprecated("internal function fgetc_unlocked was unintentionally available "
- ~ "from std.stdio and will be removed afer 2.107")
- extern (C) pragma(mangle, fgetc.mangleof) int fgetc_unlocked(_iobuf* fp);
- // @@@DEPRECATED_2.107@@@
- deprecated("internal function fgetwc_unlocked was unintentionally available "
- ~ "from std.stdio and will be removed afer 2.107")
- extern (C) pragma(mangle, core.stdc.wchar_.fgetwc.mangleof) int fgetwc_unlocked(_iobuf* fp);
-
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FPUTC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FPUTC = fputc_unlocked;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FPUTWC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FPUTWC = fputwc_unlocked;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FGETC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FGETC = fgetc_unlocked;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FGETWC was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FGETWC = fgetwc_unlocked;
-
- version (Posix)
- {
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FLOCK was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FLOCK = core.sys.posix.stdio.flockfile;
- // @@@DEPRECATED_2.107@@@
- deprecated("internal alias FUNLOCK was unintentionally available from "
- ~ "std.stdio and will be removed afer 2.107")
- alias FUNLOCK = core.sys.posix.stdio.funlockfile;
- }
}
else
{
@@ -795,7 +699,7 @@ Throws: `ErrnoException` in case of error.
/**
Detaches from the current file (throwing on failure), and then runs a command
by calling the C standard library function $(HTTP
-opengroup.org/onlinepubs/007908799/xsh/_popen.html, _popen).
+pubs.opengroup.org/onlinepubs/7908799/xsh/popen.html, popen).
Throws: `ErrnoException` in case of error.
*/
@@ -813,8 +717,9 @@ The mode must be compatible with the mode of the file descriptor.
Throws: `ErrnoException` in case of error.
Params:
fd = File descriptor to associate with this `File`.
- stdioOpenmode = Mode to associate with this File. The mode has the same semantics
- semantics as in the C standard library $(CSTDIO fdopen) function,
+ stdioOpenmode = Mode to associate with this File. The mode has the same
+ semantics as in the POSIX library function $(HTTP
+ pubs.opengroup.org/onlinepubs/7908799/xsh/fdopen.html, fdopen)
and must be compatible with `fd`.
*/
void fdopen(int fd, scope const(char)[] stdioOpenmode = "rb") @safe
@@ -1135,6 +1040,9 @@ Throws: `ErrnoException` if the file is not opened or the call to `fread` fails.
assert(buf == "\r\n\n\r\n");
}
+ // https://issues.dlang.org/show_bug.cgi?id=24685
+ static assert(!__traits(compiles, (File f) @safe { int*[1] bar; f.rawRead(bar[]); }));
+
// https://issues.dlang.org/show_bug.cgi?id=21729
@system unittest
{
@@ -4576,11 +4484,11 @@ if ((isSomeFiniteCharInputRange!R1 || isSomeString!R1) &&
{
/*
* The new opengroup large file support API is transparently
- * included in the normal C bindings. http://opengroup.org/platform/lfs.html#1.0
+ * included in the normal C bindings. https://www.opengroup.org/platform/lfs.html#1.0
* if _FILE_OFFSET_BITS in druntime is 64, off_t is 64 bit and
* the normal functions work fine. If not, then large file support
* probably isn't available. Do not use the old transitional API
- * (the native extern(C) fopen64, http://www.unix.org/version2/whatsnew/lfs20mar.html#3.0)
+ * (the native extern(C) fopen64, https://unix.org/version2/whatsnew/lfs20mar.html#3.0)
*/
import core.sys.posix.stdio : fopen;
return fopen(namez, modez);
@@ -4629,6 +4537,13 @@ private auto trustedFwrite(T)(FILE* f, const T[] obj) @trusted
* Convenience function that forwards to `core.stdc.stdio.fread`
*/
private auto trustedFread(T)(FILE* f, T[] obj) @trusted
+if (!imported!"std.traits".hasIndirections!T)
+{
+ return fread(obj.ptr, T.sizeof, obj.length, f);
+}
+
+private auto trustedFread(T)(FILE* f, T[] obj) @system
+if (imported!"std.traits".hasIndirections!T)
{
return fread(obj.ptr, T.sizeof, obj.length, f);
}
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 3c425c7..aceb287 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -3544,6 +3544,35 @@ struct Nullable(T)
}
/**
+ * Returns true if `this` has a value, otherwise false.
+ *
+ * Allows a `Nullable` to be used as the condition in an `if` statement:
+ *
+ * ---
+ * if (auto result = functionReturningNullable())
+ * {
+ * doSomethingWith(result.get);
+ * }
+ * ---
+ */
+ bool opCast(T : bool)() const
+ {
+ return !isNull;
+ }
+
+ /// Prevents `opCast` from disabling built-in conversions.
+ auto ref T opCast(T, this This)()
+ if (is(This : T) || This.sizeof == T.sizeof)
+ {
+ static if (is(This : T))
+ // Convert implicitly
+ return this;
+ else
+ // Reinterpret
+ return *cast(T*) &this;
+ }
+
+ /**
* Forces `this` to the null state.
*/
void nullify()()
@@ -4400,6 +4429,26 @@ auto nullable(T)(T t)
assert(destroyed);
}
+// https://issues.dlang.org/show_bug.cgi?id=22293
+@safe unittest
+{
+ Nullable!int empty;
+ Nullable!int full = 123;
+
+ assert(cast(bool) empty == false);
+ assert(cast(bool) full == true);
+
+ if (empty) assert(0);
+ if (!full) assert(0);
+}
+
+// check that opCast doesn't break unsafe casts
+@system unittest
+{
+ Nullable!(const(int*)) a;
+ auto result = cast(immutable(Nullable!(int*))) a;
+}
+
/**
Just like `Nullable!T`, except that the null state is defined as a
particular value. For example, $(D Nullable!(uint, uint.max)) is an
@@ -10928,19 +10977,22 @@ struct RefCounted(T, RefCountedAutoInitialize autoInit =
swap(_refCounted._store, rhs._refCounted._store);
}
- void opAssign(T rhs)
+ static if (__traits(compiles, lvalueOf!T = T.init))
{
- import std.algorithm.mutation : move;
-
- static if (autoInit == RefCountedAutoInitialize.yes)
+ void opAssign(T rhs)
{
- _refCounted.ensureInitialized();
- }
- else
- {
- assert(_refCounted.isInitialized);
+ import std.algorithm.mutation : move;
+
+ static if (autoInit == RefCountedAutoInitialize.yes)
+ {
+ _refCounted.ensureInitialized();
+ }
+ else
+ {
+ assert(_refCounted.isInitialized);
+ }
+ move(rhs, _refCounted._store._payload);
}
- move(rhs, _refCounted._store._payload);
}
static if (autoInit == RefCountedAutoInitialize.yes)
diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d
index f0d5d4d..9a326a5 100644
--- a/libphobos/src/std/utf.d
+++ b/libphobos/src/std/utf.d
@@ -53,7 +53,7 @@ $(TR $(TD Miscellaneous) $(TD
See_Also:
$(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)<br>
$(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)<br>
- $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
+ $(LINK https://web.archive.org/web/20100113043530/https://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
Copyright: Copyright The D Language Foundation 2000 - 2012.
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: $(HTTP digitalmars.com, Walter Bright) and