Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions std/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,22 @@ if (isIterable!Range && !isNarrowString!Range && !isInfinite!Range)
static if (hasLength!Range)
{
if(r.length == 0) return null;
//@@@BUG@@@ 10928 should be lambda
static @trusted nothrow auto trustedAllocateArray(size_t n)

static auto trustedAllocateArray(size_t n) @trusted nothrow
{
return uninitializedArray!(Unqual!E[])(n);
}
auto result = trustedAllocateArray(r.length);
size_t i = 0;

size_t i;
Copy link
Contributor

Choose a reason for hiding this comment

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

Relying on default initialization like this is really unsightly (and an error according to the spec, while very controversial)...

Copy link
Contributor

Choose a reason for hiding this comment

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

What on earth on mars are you talking about?

Copy link
Contributor

Choose a reason for hiding this comment

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

I know the PR is merged, I'm just pointing out that this PR replaced good practice with bad practice.

Copy link
Contributor

Choose a reason for hiding this comment

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

How is that bad practice?

Copy link

Choose a reason for hiding this comment

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

It's not going to become an error, unless you want everyone to leave D. Relying on .init is perfectly fine, we're not in undefined C++ territory here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh ok, for some reason I thought you were talking about eliminating default init in favor of flow-checking for use-before-init.

Copy link

Choose a reason for hiding this comment

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

Oh that.. well there's a million checks you could do really.. but it's probably easier to do it in D.

Copy link
Contributor

Choose a reason for hiding this comment

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

libdmd, soooooon. Well not that soon, but we're slowly making progress.

Copy link

Choose a reason for hiding this comment

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

C++ or D it still doesn't change the fact that we have a spaghetti monster on our hands! Only Chtulu (Kenji) can handle the beast!

Copy link
Contributor

Choose a reason for hiding this comment

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

Am I missing something?

Code like this is perfectly correct and has no ambiguous intent:

Object o;
if (cond)
    o = a;
else
    o = b;

(simplified)

Adding an = null initializer here that is never used would make it unclear, both to the reader and the compiler. That's what definite-assignment analysis is about - if a local variable doesn't have an initializer (sans struct/union variables), you can rest assured that it's initialized somewhere later in the method before being used. It is exactly the same problem that D's default initializers attempt to solve, but while D's way is only detectable at runtime, flow analysis pushes error messages to compile-time.

static auto trustedGetAddr(T)(ref T t) @trusted nothrow pure
{
return &t;
}
foreach (e; r)
{
// hacky
static if (is(typeof(result[i].opAssign(e))) ||
!is(typeof(result[i] = e)))
{
// this should be in-place construction
emplace(result.ptr + i, e);
}
else
{
result[i] = e;
}
i++;
emplace(trustedGetAddr(result[i]), e);
++i;
}
return cast(E[])result;
}
Expand Down