July 18, 2022

On Monday, 18 July 2022 at 16:19:20 UTC, Nick Treleaven wrote:

>

On Monday, 18 July 2022 at 12:13:47 UTC, FeepingCreature wrote:

>

And D does not have extremely reliable escape analysis.

Can you please post an example of @safe -dip1000 code that allows memory corruption? (There is a known problem with constructors with a PR to fix).

Also I presume the bugs you're talking about aren't just due to the in preview switch?

Why would I post an example of dip1000? dip1000 is not the default. If the compiler needs dip1000 to work correctly, that means the compiler is not working correctly.

The bug that triggered this is https://issues.dlang.org/show_bug.cgi?id=23170 , thankfully already fixed. I'm not optimistic it's the last one though.

DIP1000 is good, but if memory corruption in non-DIP1000 compiles is the cost of the transition, then the transition is being mishandled. Spurious compiler errors, fine, but a compiler update should not cause a very basic construct like [] to start corrupting values.

July 18, 2022

On Monday, 18 July 2022 at 17:45:08 UTC, FeepingCreature wrote:

>

Spurious compiler errors, fine, but a compiler update should not cause a very basic construct like [] to start corrupting values.

But this is more of a development process and quality assurance issue than a language design issue.

The former should adapt to the latter, not the other way around…

July 19, 2022

On Monday, 18 July 2022 at 18:01:45 UTC, Ola Fosheim Grøstad wrote:

>

On Monday, 18 July 2022 at 17:45:08 UTC, FeepingCreature wrote:

>

Spurious compiler errors, fine, but a compiler update should not cause a very basic construct like [] to start corrupting values.

But this is more of a development process and quality assurance issue than a language design issue.

The former should adapt to the latter, not the other way around…

I have made a Renderer abstraction, so, in OpenGL terms I have been setting my Uniform variables such as Vector2, Vector3, Vector4. But importing math.vector for just setting those variables creates unnecessary dependency, what have I done to solve this problem?

void setUniform(string uniformName, float[2] vec);
void setUniform(string uniformName, float[3] vec);
void setUniform(string uniformName, float[4] vec);

What happens if I do:

void setupRenderer() @nogc
{
    setUniform("Test", [1, 2]);
    setUniform("Test", [1, 2, 3]);
    setUniform("Test", [1, 2, 3, 4]);
}

Then what it happens?
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform

You guys solution:

import std.array;
void setupRenderer() @nogc
{
    setUniform("Test", [1, 2].staticArray);
    setUniform("Test", [1, 2, 3].staticArray);
    setUniform("Test", [1, 2, 3, 4].staticArray);
}

Unnecessary verbosity. That's all I could say. Then, what happens?

onlineapp.d(29): Error: none of the overloads of `setUniform` are callable using argument types `(string, int[2])`
onlineapp.d(13):        Candidates are: `onlineapp.setUniform(string uniformName, float[2] vec)`
onlineapp.d(17):                        `onlineapp.setUniform(string uniformName, float[3] vec)`
onlineapp.d(21):                        `onlineapp.setUniform(string uniformName, float[4] vec)`
onlineapp.d(30): Error: none of the overloads of `setUniform` are callable using argument types `(string, int[3])`
onlineapp.d(13):        Candidates are: `onlineapp.setUniform(string uniformName, float[2] vec)`
onlineapp.d(17):                        `onlineapp.setUniform(string uniformName, float[3] vec)`
onlineapp.d(21):                        `onlineapp.setUniform(string uniformName, float[4] vec)`
onlineapp.d(31): Error: none of the overloads of `setUniform` are callable using argument types `(string, int[4])`
onlineapp.d(13):        Candidates are: `onlineapp.setUniform(string uniformName, float[2] vec)`
onlineapp.d(17):                        `onlineapp.setUniform(string uniformName, float[3] vec)`
onlineapp.d(21):

So, for solving that, one must either:

setUniform("Test", [cast(float)1, 2].staticArray);
Or they need to actually have a float literal in the array.

Actually, I think that could be one of the the worse usecases for that

July 19, 2022

On Tuesday, 19 July 2022 at 11:00:58 UTC, Hipreme wrote:

>

What happens if I do:

void setupRenderer() @nogc
{
    setUniform("Test", [1, 2]);
    setUniform("Test", [1, 2, 3]);
    setUniform("Test", [1, 2, 3, 4]);
}

Then what it happens?
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform

>

...

>

So, for solving that, one must either:

setUniform("Test", [cast(float)1, 2].staticArray);
Or they need to actually have a float literal in the array.

Actually, I think that could be one of the the worse usecases for that

Just to note, even without DIP1000 you can just

void setUniform(string name, float[] vec...) { }

setUniform("Test", 1, 2);

and get a stack allocation for vec.

But what I'd do if I wanted to make fully sure is just void setUniform(T...)(string name, T args) and then build a static buffer manually inside setUniform.

July 19, 2022

On Tuesday, 19 July 2022 at 11:19:10 UTC, FeepingCreature wrote:

>

On Tuesday, 19 July 2022 at 11:00:58 UTC, Hipreme wrote:

>

What happens if I do:

void setupRenderer() @nogc
{
    setUniform("Test", [1, 2]);
    setUniform("Test", [1, 2, 3]);
    setUniform("Test", [1, 2, 3, 4]);
}

Then what it happens?
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform

>

...

>

So, for solving that, one must either:

setUniform("Test", [cast(float)1, 2].staticArray);
Or they need to actually have a float literal in the array.

Actually, I think that could be one of the the worse usecases for that

Just to note, even without DIP1000 you can just

void setUniform(string name, float[] vec...) { }

setUniform("Test", 1, 2);

and get a stack allocation for vec.

But what I'd do if I wanted to make fully sure is just void setUniform(T...)(string name, T args) and then build a static buffer manually inside setUniform.

I don't think that approach is good

I personally use:

void setUniform(string name, scope float[] data);

Clearer about what the data is, will always stack alloc and will be able to take what ever slice you throw at it

No need vararg or tempaltes that'll end up slowing down your compile speed

July 19, 2022

On Monday, 18 July 2022 at 12:13:47 UTC, FeepingCreature wrote:

>

On Thursday, 14 July 2022 at 13:14:59 UTC, ryuukk_ wrote:

>

It is misleading, nobody expect this to be GC allocated

It should be equal to:

int[3] arr = [1, 2, 3]

Also why it is GC allocated without requiring new?

DMD 2.099 has introduced crippling bugs that arise from overzealous stack allocation. If I could have a command line switch that would always heap allocate everything not completely obviously a stack allocation, ie. always heap allocate closures, always heap allocate arrays, I would put it in our build scripts and never touch it again.

Stack allocation without extremely reliable escape analysis is an express ride to corruptiontown. And D does not have extremely reliable escape analysis.

If stack allocation is removed and everything will be heap allocated, then it will be the day i get rid of D

If compilers bugs there are, they should be fixed

I don't understand why you even make that suggestion, a language without stack allocation can't be taken seriously

July 19, 2022

On Tuesday, 19 July 2022 at 11:54:17 UTC, ryuukk_ wrote:

>

If stack allocation is removed and everything will be heap allocated, then it will be the day i get rid of D

If compilers bugs there are, they should be fixed

I don't understand why you even make that suggestion, a language without stack allocation can't be taken seriously

Different usecases. To be clear, my take is that things should be stack allocated exactly iff they are value types. (By preference, immutable value types.) And heap allocated iff they're reference types. Arrays are reference types, so they should be heap allocated. Objects ditto. Simple and predictable. I just don't see the advantage in cleverly stack allocating arrays; it seems like an invitation to danger that's not worth the benefit. If you want a stack allocated fixed-size list, you should use an idiom that always stack allocates it, but also reliably copies it to callers and protects it from unintentional mutation. Stack allocating T[] overloads the abstraction, IMO.

July 19, 2022

On Tuesday, 19 July 2022 at 11:00:58 UTC, Hipreme wrote:

>
void setUniform(string uniformName, float[2] vec);
void setUniform(string uniformName, float[3] vec);
void setUniform(string uniformName, float[4] vec);

What happens if I do:

void setupRenderer() @nogc
{
    setUniform("Test", [1, 2]);
    setUniform("Test", [1, 2, 3]);
    setUniform("Test", [1, 2, 3, 4]);
}

Then what it happens?
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform
Error: @nogc function setupRenderer cannot call non-@nogc function renderer.setUniform

I don't understand the issue, this works?

import std;
float[2] a;
void setUniform(string uniformName, float[2] vec)@nogc { a = vec;}

void setupRenderer() @nogc
{
    setUniform("Test", [1, 2]);
}
void main()
{
   setupRenderer();
   writeln(a);
}
July 19, 2022

On Thursday, 14 July 2022 at 13:14:59 UTC, ryuukk_ wrote:

>

It is misleading, nobody expect this to be GC allocated

It should be equal to:

int[3] arr = [1, 2, 3]

Also why it is GC allocated without requiring new?

Because it’s useful to more people than if it were the opposite. If you find that staticArray too verbose, there’s a single-keystroke way to get pseudo-literals for static arrays:

struct s
{
    static typeof([ Ts.init ][0])[Ts.length] opIndex(Ts...)(auto ref Ts args)
    {
        import std.functional : forward;
        return [ forward!args ];
    }
}

Usage:

void main()
{
    auto empty = s[];
    static assert(is(typeof(empty) == void[0]));

    auto xs = s[1,cast(byte)2,3];
    static assert(is(typeof(xs) == int[3]));

    static struct NoCopy { @disable this(this); }
    auto noCopies = s[NoCopy(), NoCopy()];
}

You’re free to choose any name (except keywords). If you name it stackalloc, it almost looks like taken from C#.

July 19, 2022

On Tuesday, 19 July 2022 at 14:04:09 UTC, Quirin Schroll wrote:

>
void main()
{
    auto empty = s[];
    static assert(is(typeof(empty) == void[0]));

    auto xs = s[1,cast(byte)2,3];
    static assert(is(typeof(xs) == int[3]));

    static struct NoCopy { @disable this(this); }
    auto noCopies = s[NoCopy(), NoCopy()];
}

You’re free to choose any name (except keywords). If you name it stackalloc, it almost looks like taken from C#.

I love this! Great use of multidimensional indexes. I guess you can think of it as s being an n-dimensional table of all static arrays.