static array literal syntax request: auto x=[1,2,3]S;

Artur Skawina art.08.09 at gmail.com
Sun Jun 10 10:00:42 PDT 2012


On 06/10/12 18:02, Timon Gehr wrote:
> On 06/10/2012 04:54 PM, Artur Skawina wrote:
>> On 06/10/12 10:47, mta`chrono wrote:
>>> Am 10.06.2012 01:02, schrieb Timon Gehr:
>>>> On 06/10/2012 12:34 AM, Jonathan M Davis wrote:
>>>>> On Sunday, June 10, 2012 00:15:01 Timon Gehr wrote:
>>>>>> D static array literals don't perform a costly heap allocation. It is
>>>>>> simply a bug in the implementation. This is not a compelling reason to
>>>>>> add new syntax.
>>>>>
>>>>> D
>>>>
>>>> DMD
>>>>
>>>>> doesn't _have_ static array literals. It only has dynamic array literals.
>>>>>
>>>>> int[5] a = [1, 2, 3, 4, 5];
>>>>>
>>>>
>>>> This is a static array literal.
>>>>
>>>>> should definitely be optimized such that it doesn't do any heap
>>>>> allocations,
>>>>> but the array literal itself is dynamic regardless, as typeof indicates.
>>>>
>>>> I don't see a typeof there. The array literal is a static array literal
>>>> if it is assigned/converted to a static array.
>>
>> An array literal is a dynamic array with a known constant length that
>> implicitly converts to a static array of the same size and element type.
>> That's a sane definition,
> 
> It is not. It does not specify if/when allocations take place, for example.

Implementation details. Would you like to forbid "unnecessary" allocations?
Not doing this should be harmless as it only affects performance, but maybe
the hidden heap allocations should indeed be disallowed. Any decent compiler
won't be emitting them anyway. 

>> and AFAICT this is how it's currently handled.
>>
> 
> It is not.
> 
> void main(){
>     int[0] x = [1];
> }

Try running that, in non-release mode. :)

The fact that the compiler accepts it even in the cases where it should
be able to statically figure out that it will fail at runtime isn't ideal,
but this is just a quality of implementation issue.


>>>>> The
>>>>> other place that this causes problems is templated functions. e.g.
>>>>>
>>>>> void func(A)(A array)
>>>>>       if(isStaticArray!A)
>>>>> {}
>>>>>
>>>>> func([1, 2, 3, 4, 5]);
>>>>>
>>>>> will fail to compile. You're forced to create one on the stack first.
>>>>>
>>>>> int[5] array = [1, 2, 3, 4, 5];
>>>>> func(array);
>>>>>
>>>>
>>>> func(cast(int[5])[1,2,3,4,5]);
>>>>
>>>>> That _might_ merit adding a syntax for indicating that an array
>>>>> literal is
>>>>> static.
>>
>> I wasn't kidding about overloading 'static' for this; it would certainly
>> be better that inventing yet another literal syntax.
>>
> 
> Using 'static' is "inventing yet another literal syntax" as well.

In a way - yes. But i think "static[...]" would be much better than "[...]S". 


>>>> Yes, certainly. I was simply pointing out that arguing about performance
>>>> makes a poor case here.
>>>>
>>>>> However, in general, it's definitely true that the additional heap
>>>>> allocations
>>>>> that we currently see should just be optimized out by the compiler,
>>>>> and if
>>>>> that's all that we're trying to solve, then that's a matter of fixing the
>>>>> optimizer, not the language.
>>>>>
>>>>
>>>> This is not about optimization. Allocating is simply incorrect. It is a
>>>> 'wrong code' bug.
>>>
>>> Yes, you're right. And you've also shown that we don't need a new syntax
>>> to accomplish this.
>>
>> When you want to avoid the heap allocation, you can always use hacks such as:
>>
>>     template static_array(alias da) {
>>        typeof(da[0])[da.length] static_array = da;
>>     }
>>     f(...) {
>>        int[3] a = static_array!([1,2,3]);
>>        ...
>>     }
>>
>> But the compiler should do this automatically in these cases,
> 
> The compiler should do the right thing, not automatically apply a hack that only works for CTFEable right hand sides.

Obviously. I'm just showing a workaround that lets you avoid the useless
heap allocation in certain cases, until the compiler learns to do the right
thing.


>> right now it
>> doesn't. This hack won't of course work for the program mentioned in this
>> thread.
>>
>> The isStaticArray!A problem is partially related to how the compiler handles
>> arrays.
>>
>>     auto f(T)(T a) { enum l = a.length; return l; }
>>
>> works with
>>
>>     int[3] a = [1,2,3];
>>     f(a);
>>
>> but fails with
>>
>>     f([1,2,3]);
>>
>> And cases like
>>
>>     auto f(E)(E[] a) { enum l = a.length; return l; }
>>
>> don't work at all.
>>
>> Making these things work, which should be possible,
> 
> f([1,2,3]);               // f!(int[])
> f([1,2,3,4]);             // f!(int[])
> 
> int[3] a = [1,2,3];
> f(a);                     // f!(int[3])
> f(cast(int[3])[1,2,3]);   // f!(int[3])
> f(cast(int[4])[1,2,3,4]); // f!(int[4])

I'm not sure what your point is here. Mine is that 'length' is
known in all these cases at compile time. Yet it's only possible
to retrieve it when the argument is a real static array. It should
also be possible when the function is called with a literal. Yes,
it's just for templates and would need (hidden) specialization/cloning.
Which sounds worse than it is - because it can happen after inlining.


>> would help when dealing
>> with static arrays, and also allow more optimization opportunities.

> I don't see it helping optimization.

See above.

artur


More information about the Digitalmars-d mailing list