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.

Reply via email to