Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into dirEntries-pred
Browse files Browse the repository at this point in the history
  • Loading branch information
nordlow committed Oct 5, 2022
2 parents ca3caf4 + 29a71ef commit 902a4c5
Show file tree
Hide file tree
Showing 56 changed files with 1,872 additions and 4,941 deletions.
27 changes: 9 additions & 18 deletions .dscanner.ini

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ std/digest/* @jpf91
std/experimental/allocator/* @andralex @wilzbach @PetarKirov
std/experimental/checkedint/* @andralex
std/experimental/logger/* @burner
# std/experimental/typecons.d
std/file.d @CyberShadow
# std/format.d
# std/functional.d
Expand Down Expand Up @@ -72,6 +71,5 @@ std/utf.d @jmdavis
std/uuid.d @jpf91
# std/variant.d
std/windows/* @CyberShadow
# std/xml.d
std/zip.d @CyberShadow
std/zlib.d @CyberShadow
52 changes: 52 additions & 0 deletions changelog/borrow_for_refcounted.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Added `SafeRefCounted`, that can be used in `@safe` with `-preview=dip1000`.

`RefCounted` is only available for `@system` code, because of the possibility of
escaping a reference to its payload past the end of its lifetime. a modified
copy of it, `std.typecons.SafeRefCounted` has been added. Also added is a
`borrow` function, that lets one safely access and modify the payload.
`-preview=dip1000` prevents escaping a reference to it in `@safe` code.

-------
@safe pure nothrow void fun()
{
import std.typecons;

auto rcInt = safeRefCounted(5);
assert(rcInt.borrow!(theInt => theInt) == 5);
auto sameInt = rcInt;
assert(sameInt.borrow!"a" == 5);

// using `ref` in the function
auto arr = [0, 1, 2, 3, 4, 5, 6];
sameInt.borrow!(ref (x) => arr[x]) = 10;
assert(arr == [0, 1, 2, 3, 4, 10, 6]);

// modifying the payload via an alias
sameInt.borrow!"a*=2";
assert(rcInt.borrow!"a" == 10);
}
-------

Direct access to the payload unfortunately has to be `@system`, though. While
`-dip1000` could prevent escaping the reference, it is possible to destroy the
last reference before the end of it's scope:

-------
int destroyFirstAndUseLater()
{
import std.typecons;

auto rc = SafeRefCounted!int(123);
int* ptr = &rc.refCountedPayload();
destroy(rc);
return *ptr; // Reads from freed memory. Don't do this.
}
-------

As a side effect, this enabled us to make $(REF dirEntries, std, file) `@safe`
with `-preview=dip1000`.

Some member functions of `RefCounted` that are `@safe` are not so in
`SafeRefCounted`. The `RefCounted` type and `refCounted` function are still
available for the old behaviour. However, their main purpose is backwards
compatibility. They are not recommended for new code.
4 changes: 4 additions & 0 deletions changelog/remove-experimental-typecons.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
std.experimental.typecons has been removed

This was an attempt to update `std.typecons.wrap` with an implementation that could work with struct, but it did not go anywhere.
See [this post on the forum](https://forum.dlang.org/post/[email protected]).
5 changes: 5 additions & 0 deletions changelog/remove-std-digest-digest.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
std.digest.digest has been removed

This module was initially deprecated in 2.076.1, and has been empty since
2.092.0 when all deprecated symbols were removed in favour of importing
`std.digest` or its submodules instead.
4 changes: 4 additions & 0 deletions changelog/remove-std-xml.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
std.xml has been removed

This module is considered out-dated and not up to Phobos' current standards.
If you still need it, go to $(LINK https://github.com/DigitalMars/undeaD)
4 changes: 0 additions & 4 deletions index.dd
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ $(BOOKTABLE ,
$(TDNW $(MREF std,json))
$(TD Read/write data in JSON format.)
)
$(TR
$(TDNW $(MREF std,xml))
$(TD Read/write data in XML format.)
)
$(TR
$(TDNW $(MREF std,zip))
$(TD Read/write data in the ZIP archive format.)
Expand Down
5 changes: 2 additions & 3 deletions posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ PACKAGE_std = array ascii base64 bigint bitmanip checkedint compiler complex con
functional getopt int128 json mathspecial meta mmfile numeric \
outbuffer package parallelism path process random signals socket stdint \
stdio string sumtype system traits typecons \
uri utf uuid variant xml zip zlib
PACKAGE_std_experimental = checkedint typecons
uri utf uuid variant zip zlib
PACKAGE_std_experimental = checkedint
PACKAGE_std_algorithm = comparison iteration mutation package searching setops \
sorting
PACKAGE_std_container = array binaryheap dlist package rbtree slist util
Expand Down Expand Up @@ -259,7 +259,6 @@ EXTRA_DOCUMENTABLES := $(EXTRA_MODULES_COMMON)

EXTRA_MODULES_INTERNAL := $(addprefix std/, \
algorithm/internal \
digest/digest \
$(addprefix internal/, \
cstring memory digest/sha_SSSE3 \
$(addprefix math/, biguintcore biguintnoasm biguintx86 \
Expand Down
20 changes: 18 additions & 2 deletions std/algorithm/comparison.d
Original file line number Diff line number Diff line change
Expand Up @@ -577,14 +577,24 @@ Returns:
and `T3` are different.
*/
T1 clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val) : T1))
if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val))
&& (is(T2 : T1) && is(T3 : T1)))
// cannot use :
// `if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val) : T1))
// because of https://issues.dlang.org/show_bug.cgi?id=16235.
// Once that is fixed, we can simply use the ternary in both the template constraint
// and the template body
in
{
assert(!lower.greaterThan(upper), "Lower can't be greater than upper.");
}
do
{
return val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val;
if (val.lessThan(lower))
return lower;
else if (val.greaterThan(upper))
return upper;
return val;
}

///
Expand Down Expand Up @@ -637,6 +647,12 @@ do
assert(x.clamp(lo, hi).y == 42);
}

// https://issues.dlang.org/show_bug.cgi?id=23268
@safe pure nothrow @nogc unittest
{
static assert(__traits(compiles, clamp(short.init, short.init, cast(const) short.init)));
}

// cmp
/**********************************
Performs a lexicographical comparison on two
Expand Down
57 changes: 49 additions & 8 deletions std/algorithm/iteration.d
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,23 @@ private struct MapResult(alias fun, Range)
assert(dd.length == 4);
}

// Verify fix for: https://issues.dlang.org/show_bug.cgi?id=16034
@safe unittest
{
struct One
{
int entry = 1;
@disable this(this);
}

One[] ones = [One(), One()];

import std.algorithm.comparison : equal;

assert(ones.map!`a.entry + 1`.equal([2, 2]));
}


@safe unittest
{
import std.algorithm.comparison : equal;
Expand Down Expand Up @@ -1798,7 +1815,7 @@ if (isInputRange!R)
assert(equal(g3, [ tuple(1, 2u), tuple(2, 2u) ]));

interface I {}
class C : I { override size_t toHash() const nothrow @safe { return 0; } }
static class C : I { override size_t toHash() const nothrow @safe { return 0; } }
const C[] a4 = [new const C()];
auto g4 = a4.group!"a is b";
assert(g4.front[1] == 1);
Expand Down Expand Up @@ -2255,25 +2272,26 @@ if (isForwardRange!Range)
import std.algorithm.comparison : equal;

size_t popCount = 0;
class RefFwdRange
static class RefFwdRange
{
int[] impl;
size_t* pcount;

@safe nothrow:

this(int[] data) { impl = data; }
this(int[] data, size_t* pcount) { impl = data; this.pcount = pcount; }
@property bool empty() { return impl.empty; }
@property auto ref front() { return impl.front; }
void popFront()
{
impl.popFront();
popCount++;
(*pcount)++;
}
@property auto save() { return new RefFwdRange(impl); }
@property auto save() { return new RefFwdRange(impl, pcount); }
}
static assert(isForwardRange!RefFwdRange);

auto testdata = new RefFwdRange([1, 3, 5, 2, 4, 7, 6, 8, 9]);
auto testdata = new RefFwdRange([1, 3, 5, 2, 4, 7, 6, 8, 9], &popCount);
auto groups = testdata.chunkBy!((a,b) => (a % 2) == (b % 2));
auto outerSave1 = groups.save;

Expand Down Expand Up @@ -6058,7 +6076,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
import std.algorithm.comparison : equal;

// Test by-reference separator
class RefSep {
static class RefSep {
@safe:
string _impl;
this(string s) { _impl = s; }
Expand Down Expand Up @@ -7908,7 +7926,13 @@ if (isRandomAccessRange!Range && hasLength!Range)
_indices = iota(size_t(r.length)).array;
_empty = r.length == 0;
}

private this(size_t[] indices, size_t[] state, Range r, bool empty_)
{
_indices = indices;
_state = state;
_r = r;
_empty = empty_;
}
/// Returns: `true` if the range is empty, `false` otherwise.
@property bool empty() const pure nothrow @safe @nogc
{
Expand Down Expand Up @@ -7949,6 +7973,11 @@ if (isRandomAccessRange!Range && hasLength!Range)

next(2);
}
/// Returns: an independent copy of the permutations range.
auto save()
{
return typeof(this)(_indices.dup, _state.dup, _r.save, _empty);
}
}

///
Expand All @@ -7964,3 +7993,15 @@ if (isRandomAccessRange!Range && hasLength!Range)
[1, 2, 0],
[2, 1, 0]]));
}

@safe unittest
{
import std.algorithm.comparison : equal;
import std.range : ElementType;
import std.array : array;
auto p = [1, 2, 3].permutations;
auto x = p.save.front;
p.popFront;
auto y = p.front;
assert(x != y);
}
76 changes: 71 additions & 5 deletions std/algorithm/searching.d
Original file line number Diff line number Diff line change
Expand Up @@ -5002,7 +5002,7 @@ If set to `OpenRight.yes`, then the interval is open to the right
(last element is not included).
Otherwise if set to `OpenRight.no`, then the interval is closed to the right
(last element included).
including the entire sentinel.
*/
alias OpenRight = Flag!"openRight";

Expand Down Expand Up @@ -5052,6 +5052,7 @@ if (isInputRange!Range)
static if (!is(Sentinel == void))
private Sentinel _sentinel;
private OpenRight _openRight;
private bool _matchStarted;
private bool _done;

static if (!is(Sentinel == void))
Expand All @@ -5063,7 +5064,19 @@ if (isInputRange!Range)
_input = input;
_sentinel = sentinel;
_openRight = openRight;
_done = _input.empty || openRight && predSatisfied();
static if (isInputRange!Sentinel)
{
_matchStarted = predSatisfied();
_done = _input.empty || _sentinel.empty || openRight && _matchStarted;
if (_matchStarted && !_done && !openRight)
{
_sentinel.popFront;
}
}
else
{
_done = _input.empty || openRight && predSatisfied();
}
}
private this(Range input, Sentinel sentinel, OpenRight openRight,
bool done)
Expand Down Expand Up @@ -5118,9 +5131,32 @@ if (isInputRange!Range)
assert(!empty, "Can not popFront of an empty Until");
if (!_openRight)
{
_done = predSatisfied();
_input.popFront();
_done = _done || _input.empty;
static if (isInputRange!Sentinel)
{
_input.popFront();
_done = _input.empty || _sentinel.empty;
if (!_done)
{
if (_matchStarted)
{
_sentinel.popFront;
}
else
{
_matchStarted = predSatisfied();
if (_matchStarted)
{
_sentinel.popFront;
}
}
}
}
else
{
_done = predSatisfied();
_input.popFront();
_done = _done || _input.empty;
}
}
else
{
Expand Down Expand Up @@ -5212,3 +5248,33 @@ pure @safe unittest
assert(equal(r.save, "foo"));
}
}
// https://issues.dlang.org/show_bug.cgi?id=14543
pure @safe unittest
{
import std.algorithm.comparison : equal;
import std.uni : toUpper;
assert("one two three".until("two").equal("one "));
assert("one two three".until("two", OpenRight.no).equal("one two"));

assert("one two three".until("two", No.openRight).equal("one two"));
assert("one two three".until("two", Yes.openRight).equal("one "));

assert("one two three".until('t', Yes.openRight).equal("one "));
assert("one two three".until("", Yes.openRight).equal(""));
assert("one two three".until("", No.openRight).equal(""));

assert("one two three".until("three", No.openRight).equal("one two three"));
assert("one two three".until("three", Yes.openRight).equal("one two "));

assert("one two three".until("one", No.openRight).equal("one"));
assert("one two three".until("one", Yes.openRight).equal(""));

assert("one two three".until("o", No.openRight).equal("o"));
assert("one two three".until("o", Yes.openRight).equal(""));

assert("one two three".until("", No.openRight).equal(""));
assert("one two three".until("", Yes.openRight).equal(""));

assert("one two three".until!((a,b)=>a.toUpper == b)("TWO", No.openRight).equal("one two"));
}

4 changes: 2 additions & 2 deletions std/algorithm/sorting.d
Original file line number Diff line number Diff line change
Expand Up @@ -1642,9 +1642,9 @@ private void multiSortImpl(Range, SwapStrategy ss, funs...)(Range r)
}

// https://issues.dlang.org/show_bug.cgi?id=16413 - @system comparison function
@safe unittest
@system unittest
{
bool lt(int a, int b) { return a < b; } static @system
static @system bool lt(int a, int b) { return a < b; }
auto a = [2, 1];
a.multiSort!(lt, lt);
assert(a == [1, 2]);
Expand Down
Loading

0 comments on commit 902a4c5

Please sign in to comment.