Skip to content

Commit ed55a66

Browse files
committed
Alexandrescus last review - deleted template attributes and added a test
that would not have passed with them.
1 parent cf67d36 commit ed55a66

File tree

1 file changed

+63
-25
lines changed

1 file changed

+63
-25
lines changed

std/array.d

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4002,7 +4002,7 @@ Params:
40024002
40034003
Returns: A static array constructed from `a`.
40044004
+/
4005-
pragma(inline, true) T[n] staticArray(T, size_t n)(auto ref T[n] a) nothrow @safe pure @nogc
4005+
pragma(inline, true) T[n] staticArray(T, size_t n)(auto ref T[n] a)
40064006
{
40074007
return a;
40084008
}
@@ -4015,7 +4015,7 @@ nothrow pure @safe unittest
40154015
assert(a == [0, 1]);
40164016
}
40174017

4018-
pragma(inline, true) U[n] staticArray(U, T, size_t n)(auto ref T[n] a) nothrow @safe pure @nogc
4018+
pragma(inline, true) U[n] staticArray(U, T, size_t n)(auto ref T[n] a)
40194019
if (!is(T == U) && is(T : U))
40204020
{
40214021
return a[].staticArray!(U[n]);
@@ -4056,41 +4056,40 @@ nothrow pure @safe unittest
40564056
}
40574057

40584058
/// ditto
4059-
auto staticArray(size_t n, T)(T a)
4059+
auto staticArray(size_t n, T)(scope T a)
40604060
if (isInputRange!T)
40614061
{
40624062
alias U = ElementType!T;
40634063
return staticArray!(U[n], U, n)(a);
40644064
}
40654065

40664066
/// ditto
4067-
auto staticArray(size_t n, T)(T a, out size_t rangeLength)
4067+
auto staticArray(size_t n, T)(scope T a, out size_t rangeLength)
40684068
if (isInputRange!T)
40694069
{
40704070
alias U = ElementType!T;
40714071
return staticArray!(U[n], U, n)(a, rangeLength);
40724072
}
40734073

40744074
/// ditto
4075-
auto staticArray(Un : U[n], U, size_t n, T)(T a) nothrow
4076-
if ((isInputRange!T) && is(ElementType!T : U))
4075+
auto staticArray(Un : U[n], U, size_t n, T)(scope T a)
4076+
if (isInputRange!T && is(ElementType!T : U))
40774077
{
40784078
size_t extraStackSpace;
40794079
return staticArray!(Un, U, n)(a, extraStackSpace);
40804080
}
40814081

40824082
/// ditto
4083-
auto staticArray(Un : U[n], U, size_t n, T)(T a, out size_t rangeLength)
4084-
if ((isInputRange!T) && is(ElementType!T : U))
4083+
auto staticArray(Un : U[n], U, size_t n, T)(scope T a, out size_t rangeLength)
4084+
if (isInputRange!T && is(ElementType!T : U))
40854085
{
40864086
import std.algorithm.mutation : uninitializedFill;
40874087
import std.range : take;
40884088
import std.conv : emplaceRef;
40894089

4090-
size_t i;
4091-
40924090
if (__ctfe)
40934091
{
4092+
size_t i;
40944093
// Compile-time version to avoid unchecked memory access.
40954094
Unqual!U[n] ret;
40964095
for (auto iter = a.take(n); !iter.empty; iter.popFront())
@@ -4109,20 +4108,20 @@ if ((isInputRange!T) && is(ElementType!T : U))
41094108
return theArray;
41104109
}());
41114110

4112-
static if (hasElaborateDestructor!U) scope (failure)
4111+
size_t i;
4112+
if (true)
41134113
{
4114-
//without this, a destructor would be called on uninitialized memory
4115-
foreach (j; i .. n) emplace(result[j]);
4116-
}
4114+
// ret was void-initialized so let's initialize the unfilled part manually.
4115+
// also prevents destructors to be called on uninitialized memory if
4116+
// an exception is thrown
4117+
scope (exit) ret[i .. $].uninitializedFill(U.init);
41174118

4118-
for (auto iter = a.take(n); !iter.empty; iter.popFront())
4119-
{
4120-
emplaceRef!U(ret[i++], iter.front);
4119+
for (auto iter = a.take(n); !iter.empty; iter.popFront())
4120+
{
4121+
emplaceRef!U(ret[i++], iter.front);
4122+
}
41214123
}
41224124

4123-
// ret was void-initialized so let's initialize the unfilled part manually.
4124-
ret[i .. $].uninitializedFill(U.init);
4125-
41264125
rangeLength = i;
41274126
return (() @trusted => cast(U[n]) ret)();
41284127
}
@@ -4141,9 +4140,50 @@ nothrow pure @safe unittest
41414140
assert(b == [0, 1, 2, 0]);
41424141
}
41434142

4144-
nothrow pure @safe unittest
4143+
// Tests that code compiles when there is an elaborate destructor and exceptions
4144+
// are thrown. Unfortunately can't test that memory is initialized
4145+
// before having a destructor called on it.
4146+
// @system required because of issue 18872.
4147+
@system nothrow unittest
41454148
{
4149+
// exists only to allow doing something in the destructor. Not tested
4150+
// at the end because value appears to depend on implementation of the.
4151+
// function.
4152+
static int preventersDestroyed = 0;
41464153

4154+
static struct CopyPreventer
4155+
{
4156+
bool on = false;
4157+
this(this)
4158+
{
4159+
if (on) throw new Exception("Thou shalt not copy past me!");
4160+
}
4161+
4162+
~this()
4163+
{
4164+
preventersDestroyed++;
4165+
}
4166+
}
4167+
auto normalArray =
4168+
[
4169+
CopyPreventer(false),
4170+
CopyPreventer(false),
4171+
CopyPreventer(true),
4172+
CopyPreventer(false),
4173+
CopyPreventer(true),
4174+
];
4175+
4176+
try
4177+
{
4178+
auto staticArray = normalArray.staticArray!5;
4179+
assert(false);
4180+
}
4181+
catch (Exception e){}
4182+
}
4183+
4184+
4185+
nothrow pure @safe unittest
4186+
{
41474187
auto a = [1, 2].staticArray;
41484188
assert(is(typeof(a) == int[2]) && a == [1, 2]);
41494189

@@ -4168,16 +4208,14 @@ nothrow pure @system unittest
41684208
auto staticArray(alias a)()
41694209
if (isInputRange!(typeof(a)))
41704210
{
4171-
// NOTE: without `cast`, getting error:
4172-
// cannot deduce function from argument types !(length)(Result)
4173-
return .staticArray!(cast(size_t) a.length)(a);
4211+
return .staticArray!(size_t(a.length))(a);
41744212
}
41754213

41764214
/// ditto
41774215
auto staticArray(U, alias a)()
41784216
if (isInputRange!(typeof(a)))
41794217
{
4180-
return .staticArray!(U[cast(size_t) a.length])(a);
4218+
return .staticArray!(U[size_t(a.length)])(a);
41814219
}
41824220

41834221
/// static array from CT range

0 commit comments

Comments
 (0)