On 2/5/2015 8:20 PM, Dicebot wrote:
I am not even sure how you can show the example though, to be honest - implied
issues are about maintaining code and not just writing it.
Let's start with std.array.uninitializedArray():
auto uninitializedArray(T, I...)(I sizes) nothrow @trusted
Note how it says it is 'trusted'. Yet it can be used to create an uninitialized
array of pointers! There is no freakin' way this function should pass muster.
Worse, multiple modules use it:
array.d: return uninitializedArray!(Unqual!E[])(n);
array.d:auto uninitializedArray(T, I...)(I sizes) nothrow @trusted
array.d: double[] arr = uninitializedArray!(double[])(100);
array.d: double[][] matrix = uninitializedArray!(double[][])(42, 31);
array.d: auto s1 = uninitializedArray!(int[])();
array.d: return uninitializedArray!(T[])(n);
array.d: auto result = uninitializedArray!(RetTypeElement[])(length);
array.d: auto result = uninitializedArray!(RetTypeElement[])(length);
array.d: auto result = uninitializedArray!(RetTypeElement[])(length);
file.d: import std.array : uninitializedArray;
file.d: auto buf = uninitializedArray!(ubyte[])(size);
file.d: void[] result = uninitializedArray!(ubyte[])(initialAlloc);
numeric.d: import std.array : uninitializedArray;
numeric.d: auto memSpace = uninitializedArray!(lookup_t[])(2 * size);
numeric.d: ret = uninitializedArray!(Complex!F[])(range.length);
numeric.d: ret = uninitializedArray!(Complex!F[])(range.length);
parallelism.d: auto buf = uninitializedArray!(MapType!(Args[0],
functions)[])(len);
parallelism.d: temp = uninitializedArray!Temp(workUnitSize);
parallelism.d: temp = uninitializedArray!Temp(workUnitSize);
stdio.d: import std.array : appender, uninitializedArray;
stdio.d: buf = uninitializedArray!(char[])(i);
stdio.d: buf = uninitializedArray!(char[])(i);
stdio.d: import std.array : appender, uninitializedArray;
utf.d: import std.array : uninitializedArray;
utf.d: auto copy = uninitializedArray!(Unqual!OutChar[])(str.length + 1);
So I already know there are serious problems. Looking closer, I see there's
another function:
auto minimallyInitializedArray(T, I...)(I sizes) nothrow @trusted
which initializes everything to 0, pointers and all. I agree this one can be
trusted. The difference between their implementations is a parameter they pass
to arrayAllocImpl(), which says whether to 0 it or not.
But really, it's only pointer types (and types composed of pointers) that make
it system code. Since uninitializedArray() is a template, we can have two
implementations for it that are statically selected based on the element type.
One is @system, when E is a type that contains a pointer. The other is @trusted,
when E is not a pointer.
That solves that problem without great effort.
Upstream of uninitializedArray(), the only problem then is when it is called to
generate an uninitialized array of pointers. In order to make the call safe, the
caller must then ensure that the array gets initialized with safe values. And
that code should be properly marked as @trusted, and not before.
I.e. start at the bottom, and work up until you find the right place to make it
trusted. Rinse, repeat. I am not seeing where the problem with doing this is.