Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge stable #9086

Merged
merged 13 commits into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ jobs:
# macOS
- job_name: macOS 13 x64
os: macos-13
- job_name: macOS 12 x64
os: macos-12
# Windows
- job_name: Windows x64
os: windows-2022
Expand Down Expand Up @@ -83,13 +81,6 @@ jobs:
with:
arch: ${{ env.MODEL == '64' && 'x64' || 'x86' }}

# NOTE: Linker ICEs with Xcode 15.0.1 (default version on macos-13)
# * https://issues.dlang.org/show_bug.cgi?id=24407
# Remove this step if the default gets changed to 15.1 in actions/runner-images.
- name: 'macOS 13: Switch to Xcode v15.1'
if: matrix.os == 'macos-13'
run: sudo xcode-select -switch /Applications/Xcode_15.1.app

- name: 'Posix: Install host compiler'
if: runner.os != 'Windows'
run: cd ../dmd && ci/run.sh install_host_compiler
Expand Down
82 changes: 82 additions & 0 deletions std/algorithm/searching.d
Original file line number Diff line number Diff line change
Expand Up @@ -3735,6 +3735,47 @@ if (isInputRange!Range && !isInfinite!Range &&
assert(arr.minElement!"a.val".val == 0);
}

// https://issues.dlang.org/show_bug.cgi?id=24827
@safe unittest
{
static struct S
{
int i;
bool destroyed;

this(int i) @safe
{
this.i = i;
}

~this() @safe
{
destroyed = true;
}

bool opEquals()(auto ref S rhs)
{
return this.i == rhs.i;
}

int opCmp()(auto ref S rhs)
{
if (this.i < rhs.i)
return -1;

return this.i == rhs.i ? 0 : 1;
}

@safe invariant
{
assert(!destroyed);
}
}

auto arr = [S(19), S(2), S(145), S(7)];
assert(minElement(arr) == S(2));
}

/**
Iterates the passed range and returns the maximal element.
A custom mapping function can be passed to `map`.
Expand Down Expand Up @@ -3888,6 +3929,47 @@ if (isInputRange!Range && !isInfinite!Range &&
assert(arr[0].getI == 2);
}

// https://issues.dlang.org/show_bug.cgi?id=24827
@safe unittest
{
static struct S
{
int i;
bool destroyed;

this(int i) @safe
{
this.i = i;
}

~this() @safe
{
destroyed = true;
}

bool opEquals()(auto ref S rhs)
{
return this.i == rhs.i;
}

int opCmp()(auto ref S rhs)
{
if (this.i < rhs.i)
return -1;

return this.i == rhs.i ? 0 : 1;
}

@safe invariant
{
assert(!destroyed);
}
}

auto arr = [S(19), S(2), S(145), S(7)];
assert(maxElement(arr) == S(145));
}

// minPos
/**
Computes a subrange of `range` starting at the first occurrence of `range`'s
Expand Down
59 changes: 58 additions & 1 deletion std/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -3639,6 +3639,7 @@ if (isDynamicArray!A)
}
else
{
import core.stdc.string : memcpy, memset;
// Time to reallocate.
// We need to almost duplicate what's in druntime, except we
// have better access to the capacity field.
Expand All @@ -3650,6 +3651,15 @@ if (isDynamicArray!A)
if (u)
{
// extend worked, update the capacity
// if the type has indirections, we need to zero any new
// data that we requested, as the existing data may point
// at large unused blocks.
static if (hasIndirections!T)
{
immutable addedSize = u - (_data.capacity * T.sizeof);
() @trusted { memset(_data.arr.ptr + _data.capacity, 0, addedSize); }();
}

_data.capacity = u / T.sizeof;
return;
}
Expand All @@ -3665,10 +3675,20 @@ if (isDynamicArray!A)

auto bi = (() @trusted => GC.qalloc(nbytes, blockAttribute!T))();
_data.capacity = bi.size / T.sizeof;
import core.stdc.string : memcpy;
if (len)
() @trusted { memcpy(bi.base, _data.arr.ptr, len * T.sizeof); }();

_data.arr = (() @trusted => (cast(Unqual!T*) bi.base)[0 .. len])();

// we requested new bytes that are not in the existing
// data. If T has pointers, then this new data could point at stale
// objects from the last time this block was allocated. Zero that
// new data out, it may point at large unused blocks!
static if (hasIndirections!T)
() @trusted {
memset(bi.base + (len * T.sizeof), 0, (newlen - len) * T.sizeof);
}();

_data.tryExtendBlock = true;
// leave the old data, for safety reasons
}
Expand Down Expand Up @@ -4047,6 +4067,43 @@ if (isDynamicArray!A)
app2.toString();
}

// https://issues.dlang.org/show_bug.cgi?id=24856
@system unittest
{
import core.memory : GC;
import std.stdio : writeln;
import std.algorithm.searching : canFind;
GC.disable();
scope(exit) GC.enable();
void*[] freeme;
// generate some poison blocks to allocate from.
auto poison = cast(void*) 0xdeadbeef;
foreach (i; 0 .. 10)
{
auto blk = new void*[7];
blk[] = poison;
freeme ~= blk.ptr;
}

foreach (p; freeme)
GC.free(p);

int tests = 0;
foreach (i; 0 .. 10)
{
Appender!(void*[]) app;
app.put(null);
// if not a realloc of one of the deadbeef pointers, continue
if (!freeme.canFind(app.data.ptr))
continue;
++tests;
assert(!app.data.ptr[0 .. app.capacity].canFind(poison), "Appender not zeroing data!");
}
// just notify in the log whether this test actually could be done.
if (tests == 0)
writeln("WARNING: test of Appender zeroing did not occur");
}

//Calculates an efficient growth scheme based on the old capacity
//of data, and the minimum requested capacity.
//arg curLen: The current length
Expand Down
23 changes: 22 additions & 1 deletion std/bitmanip.d
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private template createAccessors(
enum RightShiftOp = ">>>=";
}

static if (is(T == bool))
static if (is(T : bool))
{
enum createAccessors =
// getter
Expand Down Expand Up @@ -4676,3 +4676,24 @@ if (isIntegral!T)
foreach (i; 0 .. 63)
assert(bitsSet(1UL << i).equal([i]));
}

// Fix https://issues.dlang.org/show_bug.cgi?id=24095
@safe @nogc pure unittest
{
enum Bar : bool
{
a,
b,
}

struct Foo
{
mixin(bitfields!(Bar, "bar", 1, ubyte, "", 7,));
}

Foo foo;
foo.bar = Bar.a;
assert(foo.bar == Bar.a);
foo.bar = Bar.b;
assert(foo.bar == Bar.b);
}
25 changes: 24 additions & 1 deletion std/container/dlist.d
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ Implements a doubly-linked list.
struct DList(T)
{
import std.range : Take;
import std.traits : isMutable;

/*
A Node with a Payload. A PayNode.
Expand Down Expand Up @@ -220,7 +221,10 @@ struct DList(T)
{
import std.algorithm.mutation : move;

return (new PayNode(BaseNode(prev, next), move(arg))).asBaseNode();
static if (isMutable!Stuff)
return (new PayNode(BaseNode(prev, next), move(arg))).asBaseNode();
else
return (new PayNode(BaseNode(prev, next), arg)).asBaseNode();
}

void initialize() nothrow @safe pure
Expand Down Expand Up @@ -1149,3 +1153,22 @@ private:
list.removeFront();
assert(list[].walkLength == 0);
}

// https://issues.dlang.org/show_bug.cgi?id=24637
@safe unittest
{
import std.algorithm.comparison : equal;

struct A
{
int c;
}

DList!A B;
B.insert(A(1));
assert(B[].equal([A(1)]));

const a = A(3);
B.insert(a);
assert(B[].equal([A(1), A(3)]));
}
4 changes: 2 additions & 2 deletions std/logger/core.d
Original file line number Diff line number Diff line change
Expand Up @@ -1433,7 +1433,7 @@ logger by the user, the default logger's log level is LogLevel.info.

Example:
-------------
sharedLog = new FileLogger(yourFile);
sharedLog = new shared FileLogger(yourFile);
-------------
The example sets a new `FileLogger` as new `sharedLog`.

Expand All @@ -1450,7 +1450,7 @@ writing `sharedLog`.
The default `Logger` is thread-safe.
-------------
if (sharedLog !is myLogger)
sharedLog = new myLogger;
sharedLog = new shared myLogger;
-------------
*/
@property shared(Logger) sharedLog() @safe
Expand Down
16 changes: 13 additions & 3 deletions std/logger/filelogger.d
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class FileLogger : Logger
auto l3 = new FileLogger("logFile", LogLevel.fatal, CreateFolder.yes);
-------------
*/
this(const string fn, const LogLevel lv = LogLevel.all) @safe
this(this This)(const string fn, const LogLevel lv = LogLevel.all)
{
this(fn, lv, CreateFolder.yes);
}
Expand All @@ -63,7 +63,7 @@ class FileLogger : Logger
auto l2 = new FileLogger(file, LogLevel.fatal);
-------------
*/
this(const string fn, const LogLevel lv, CreateFolder createFileNameFolder) @safe
this(this This)(const string fn, const LogLevel lv, CreateFolder createFileNameFolder)
{
import std.file : exists, mkdirRecurse;
import std.path : dirName;
Expand All @@ -80,7 +80,8 @@ class FileLogger : Logger
" created in '", d,"' could not be created."));
}

this.file_.open(this.filename, "a");
// Cast away `shared` when the constructor is inferred shared.
() @trusted { (cast() this.file_).open(this.filename, "a"); }();
}

/** A constructor for the `FileLogger` Logger that takes a reference to
Expand Down Expand Up @@ -270,3 +271,12 @@ class FileLogger : Logger
assert(tl !is null);
stdThreadLocalLog.logLevel = LogLevel.all;
}

@safe unittest
{
// we don't need to actually run the code, only make sure
// it compiles
static _() {
auto l = new shared FileLogger("");
}
}
2 changes: 1 addition & 1 deletion std/logger/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ using the property called `sharedLog`. This property is a reference to the
current default `Logger`. This reference can be used to assign a new
default `Logger`.
-------------
sharedLog = new FileLogger("New_Default_Log_File.log");
sharedLog = new shared FileLogger("New_Default_Log_File.log");
-------------

Additional `Logger` can be created by creating a new instance of the
Expand Down
11 changes: 6 additions & 5 deletions std/process.d
Original file line number Diff line number Diff line change
Expand Up @@ -4631,11 +4631,12 @@ else version (Posix)
if (childpid == 0)
{
// Trusted because args and all entries are always zero-terminated
(() @trusted =>
core.sys.posix.unistd.execvp(args[0], &args[0]) ||
perror(args[0]) // failed to execute
)();
return;
(() @trusted {
core.sys.posix.unistd.execvp(args[0], &args[0]);
perror(args[0]);
core.sys.posix.unistd._exit(1);
})();
assert(0, "Child failed to exec");
}
if (browser)
// Trusted because it's allocated via strdup above
Expand Down
11 changes: 8 additions & 3 deletions std/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -9238,12 +9238,16 @@ enum isCopyable(S) = __traits(isCopyable, S);
* is the same as `T`. For pointer and slice types, it is `T` with the
* outer-most layer of qualifiers dropped.
*/
package(std) template DeducedParameterType(T)
package(std) alias DeducedParameterType(T) = DeducedParameterTypeImpl!T;
/// ditto
package(std) alias DeducedParameterType(alias T) = DeducedParameterTypeImpl!T;

private template DeducedParameterTypeImpl(T)
{
static if (is(T == U*, U) || is(T == U[], U))
alias DeducedParameterType = Unqual!T;
alias DeducedParameterTypeImpl = Unqual!T;
else
alias DeducedParameterType = T;
alias DeducedParameterTypeImpl = T;
}

@safe unittest
Expand All @@ -9263,6 +9267,7 @@ package(std) template DeducedParameterType(T)
}

static assert(is(DeducedParameterType!NoCopy == NoCopy));
static assert(is(DeducedParameterType!(inout(NoCopy)) == inout(NoCopy)));
}

@safe unittest
Expand Down
Loading
Loading