@@ -4002,7 +4002,7 @@ Params:
4002
4002
4003
4003
Returns: A static array constructed from `a`.
4004
4004
+/
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)
4006
4006
{
4007
4007
return a;
4008
4008
}
@@ -4015,7 +4015,7 @@ nothrow pure @safe unittest
4015
4015
assert (a == [0 , 1 ]);
4016
4016
}
4017
4017
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)
4019
4019
if (! is (T == U) && is (T : U))
4020
4020
{
4021
4021
return a[].staticArray! (U[n]);
@@ -4056,41 +4056,40 @@ nothrow pure @safe unittest
4056
4056
}
4057
4057
4058
4058
// / ditto
4059
- auto staticArray (size_t n, T)(T a)
4059
+ auto staticArray (size_t n, T)(scope T a)
4060
4060
if (isInputRange! T)
4061
4061
{
4062
4062
alias U = ElementType! T;
4063
4063
return staticArray! (U[n], U, n)(a);
4064
4064
}
4065
4065
4066
4066
// / 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)
4068
4068
if (isInputRange! T)
4069
4069
{
4070
4070
alias U = ElementType! T;
4071
4071
return staticArray! (U[n], U, n)(a, rangeLength);
4072
4072
}
4073
4073
4074
4074
// / 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))
4077
4077
{
4078
4078
size_t extraStackSpace;
4079
4079
return staticArray! (Un, U, n)(a, extraStackSpace);
4080
4080
}
4081
4081
4082
4082
// / 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))
4085
4085
{
4086
4086
import std.algorithm.mutation : uninitializedFill;
4087
4087
import std.range : take;
4088
4088
import std.conv : emplaceRef;
4089
4089
4090
- size_t i;
4091
-
4092
4090
if (__ctfe)
4093
4091
{
4092
+ size_t i;
4094
4093
// Compile-time version to avoid unchecked memory access.
4095
4094
Unqual! U[n] ret;
4096
4095
for (auto iter = a.take(n); ! iter.empty; iter.popFront())
@@ -4109,20 +4108,20 @@ if ((isInputRange!T) && is(ElementType!T : U))
4109
4108
return theArray;
4110
4109
}());
4111
4110
4112
- static if (hasElaborateDestructor! U) scope (failure)
4111
+ size_t i;
4112
+ if (true )
4113
4113
{
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);
4117
4118
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
+ }
4121
4123
}
4122
4124
4123
- // ret was void-initialized so let's initialize the unfilled part manually.
4124
- ret[i .. $].uninitializedFill(U.init);
4125
-
4126
4125
rangeLength = i;
4127
4126
return (() @trusted => cast (U[n]) ret)();
4128
4127
}
@@ -4141,9 +4140,50 @@ nothrow pure @safe unittest
4141
4140
assert (b == [0 , 1 , 2 , 0 ]);
4142
4141
}
4143
4142
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
4145
4148
{
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 ;
4146
4153
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
+ {
4147
4187
auto a = [1 , 2 ].staticArray;
4148
4188
assert (is (typeof (a) == int [2 ]) && a == [1 , 2 ]);
4149
4189
@@ -4168,16 +4208,14 @@ nothrow pure @system unittest
4168
4208
auto staticArray (alias a)()
4169
4209
if (isInputRange! (typeof (a)))
4170
4210
{
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);
4174
4212
}
4175
4213
4176
4214
// / ditto
4177
4215
auto staticArray (U, alias a)()
4178
4216
if (isInputRange! (typeof (a)))
4179
4217
{
4180
- return .staticArray! (U[cast ( size_t ) a.length])(a);
4218
+ return .staticArray! (U[size_t ( a.length) ])(a);
4181
4219
}
4182
4220
4183
4221
// / static array from CT range
0 commit comments