Skip to content

Conversation

monarchdodra
Copy link
Collaborator

Third try. I decided to concentrate on fixing/improving the simple things. It's time these get fixed

Solves:

Improvements also include these simple improvements:

  • Explicitly documented as nothrow, and weakly pure.
  • Works with 0 args (returns an empty slice).
  • All args are pre-emptivelly changed to size_t, to avoid template over-instantiation.

Also, arguably, I think the new implementation is easier to handle, since it clearly separates 1 arg and several arg paths.

auto uninitializedArray(T, I...)(I sizes) nothrow pure
if (isArray!T && allSatisfy!(isIntegral, I))
{
    enum isSize_t(E) = is (E : size_t);
    alias toSize_t(E) = size_t;

    static assert(allSatisfy!(isSize_t, I),
        format("Argument types in %s are not all convertible to size_t: %s",
        I.stringof, Filter!(templateNot!(isSize_t), I).stringof));

    //Eagerlly transform non-size_t into size_t to avoid template bloat
    alias ST = staticMap!(toSize_t, I);

    return arrayAllocImpl!(false, T, ST)(sizes);
}

auto minimallyInitializedArray(T, I...)(I sizes) nothrow pure
if (isArray!T && allSatisfy!(isIntegral, I))
{
    enum isSize_t(E) = is (E : size_t);
    alias toSize_t(E) = size_t;

    static assert(allSatisfy!(isSize_t, I),
        format("Argument types in %s are not all convertible to size_t: %s",
        I.stringof, Filter!(templateNot!(isSize_t), I).stringof));

    //Eagerlly transform non-size_t into size_t to avoid template bloat
    alias ST = staticMap!(toSize_t, I);

    return arrayAllocImpl!(true, T, ST)(sizes);
}

private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow pure
{
    static assert(I.length <= nDimensions!T,
        format("%s dimensions specified for a %s dimensional array.", I.length, nDimensions!T));

    alias E = ElementEncodingType!T;

    E[] ret;

    static if (I.length != 0)
    {
        static assert (is(I[0] == size_t));
        alias size = sizes[0];
    }

    static if (I.length == 1)
    {
        if (__ctfe)
        {
            static if (__traits(compiles, new E[](1)))
                ret = new E[](size);
            else
                foreach (i; 0 .. size)
                    ret ~= E.init;
        }
        else
        {
            import core.stdc.string : memset;
            auto ptr = cast(E*) GC.malloc(sizes[0] * E.sizeof, blockAttribute!(E));
            static if (minimallyInitialized && hasIndirections!E)
                memset(ptr, 0, size * E.sizeof);
            ret = ptr[0 .. size];
        }
    }
    else static if (I.length > 1)
    {
        ret = arrayAllocImpl!(false, E[])(size);
        foreach(ref elem; ret)
            elem = arrayAllocImpl!(minimallyInitialized, E)(sizes[1..$]);
    }

    return ret;
}

@ghost
Copy link

ghost commented Oct 24, 2013

This is good to go, except it needs a rebase.

Very nice tricks w.r.t. the size_t static map, may I add!

@monarchdodra
Copy link
Collaborator Author

This is good to go, except it needs a rebase.

Rebased. I actually had to change it a little, I hit some "interesting" bugs.

First: I realized that you can't CTFE if the struct has both disabled init and postblit.
Second: Because of the CTFE branch, the function may not actually be nothrow and pure. I was able to solve this in regards to nothrow, but in regards to pure, structs with impure postblit will not have a pure un-initialized array.

So yeah, ready for review too.

@monarchdodra
Copy link
Collaborator Author

This is good to go, except it needs a rebase.

Ping @AndrejMitrovic .

Initialization is guaranteed only for pointers, references and slices,
for preservation of memory safety.
*/
auto minimallyInitializedArray(T, I...)(I sizes) @trusted
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since @trusted is gone could this break any code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, yes it could. I need to put it back in.

@ghost
Copy link

ghost commented Feb 12, 2014

LGTM other than the @trusted remark.

@ghost
Copy link

ghost commented Feb 13, 2014

Ping me when it's updated and I'll mark it as automerge, thanks.

Solves:
* http://d.puremagic.com/issues/show_bug.cgi?id=9803 : minimallyInitializedArray fails past "1D" depth
* http://d.puremagic.com/issues/show_bug.cgi?id=10637 : minimallyInitializedArray: postblit on non-initialized
* http://d.puremagic.com/issues/show_bug.cgi?id=10847 : uninitializedArray accepts arguments which make it fail internally

Improvements also include:
* Documented as nothrow, and weakly pure.
* Works with 0 args (returns an empty slice).
* All args are pre-emptivelly changed to size_t, to avoid template over-instantiation.
@monarchdodra
Copy link
Collaborator Author

Ping me when it's updated and I'll mark it as automerge, thanks.

I had originally removed it, because I had written a version of arrayAllocImpl which correctly inferred safety (for uninitializedArray). This was a bit complicated, and I reverted, in the hope of getting pulled faster. FYI.

So I put the trusted back in. I may come back and fix the inference in a later pull.

@ghost
Copy link

ghost commented Feb 14, 2014

Auto-merge toggled on

ghost pushed a commit that referenced this pull request Feb 14, 2014
Fixup [un|minimally]InitializedArray
@ghost ghost merged commit 09c5220 into dlang:master Feb 14, 2014
@ghost
Copy link

ghost commented Feb 14, 2014

Thanks for the work @monarchdodra!

@monarchdodra monarchdodra deleted the uniniArray2 branch February 18, 2014 20:58
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant