Troubles with immutable arrays
kenji hara
k.hara.pg at gmail.com
Mon Jul 23 08:16:57 PDT 2012
Oh, no. I've accidentally done the *fix*, even though that is contrary
to my own claim.
I don't like the cross-talk of compile-time and run-time variables.
An related issue is bug 3449, but it has been opposed by Walter.
http://d.puremagic.com/issues/show_bug.cgi?id=3449
A small example of bug 3449:
----
void main()
{
struct Foo1 { const int bar; }
pragma(msg, Foo1.sizeof); // Prints "4"
Foo1 foo1;
auto p1 = &foo1.bar; // Succeeds to compile, as excepced.
struct Foo2 { const int bar = 123; }
pragma(msg, Foo2.sizeof); // Prints "1", not "4"
Foo2 foo2;
auto p2 = &foo2.bar; // Error: constant 123 is not an lvalue
}
Why cannot get address of foo2.bar?
The answer is: compiler makes Foo2.bar a manifest constant, because
its type is not mutable and has an initializer.
---
With current dmd, *all* of variable declarations, that has non mutable
type and initializer, are _speculatively_ interpreted in compile time
(== CTFE-ed). If it is succeeds, the declaration will be treated as
same as manifest constant. That is the reason of you explained *bug*
and bug 3449.
I think the *implicit interpretation* is inherited from D1, and if go
back further, will reach to C++ constant variable.
BUT, in D2, we have the 'enum' declaration, which express the
declaration is really manifest constant.
So, the muddy interpretation just confuses many D user's, and less benefit.
I think we should separate run-time variable declarations and compile
time ones, to moderate the leaning curve.
Regards.
Kenji Hara
2012/7/23 bearophile <bearophileHUGS at lycos.com>:
> After a discussion in D.learn started by someone else, after a suggestion of
> mine Timon Gehr has added a bug report:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=8400
>
> But the bug was fixed in the opposite way of what I was thinking.
>
> The problem was that the length of global immutable arrays arrays is seen as
> a compile-time constant.
> Instead of fixing that, Issue 8400 has done the opposite, now even the
> lenght of local immutable arrays is seen sometimes as a compile-time
> constant, and example:
>
>
> int[] foo(in int n) pure nothrow {
> int[] a;
> foreach (i; 0 .. n)
> a ~= i * 10;
> return a;
> }
> void main() {
> import core.stdc.stdio: printf;
> immutable int[] A = foo(5);
> int[A.length] B;
> printf("%zd\n", B.length);
> }
>
>
>
> The asm, compiled with -release:
>
> _D4temp3fooFNaNbxiZAi comdat
> L0: enter 018h,0
> push EBX
> push ESI
> mov dword ptr -018h[EBP],0
> mov dword ptr -014h[EBP],0
> mov dword ptr -010h[EBP],0
> mov -0Ch[EBP],EAX
> L1E: mov EAX,-010h[EBP]
> cmp EAX,-0Ch[EBP]
> jge L48
> lea ECX,-010h[EBP]
> mov EDX,[ECX]
> lea EBX,[EDX*4][EDX]
> add EBX,EBX
> push EBX
> lea ESI,-018h[EBP]
> push ESI
> mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
> push EAX
> call near ptr __d_arrayappendcT
> add ESP,0Ch
> inc dword ptr -010h[EBP]
> jmp short L1E
> L48: mov EDX,-014h[EBP]
> mov EAX,-018h[EBP]
> pop ESI
> pop EBX
> leave
> ret
>
> __Dmain comdat
> L0: enter 018h,0
> push EBX
> push ESI
> push 5
> mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
> push EAX
> call near ptr __d_arrayliteralTX
> mov dword ptr [EAX],0
> mov dword ptr 4[EAX],0Ah
> mov dword ptr 8[EAX],014h
> mov dword ptr 0Ch[EAX],01Eh
> mov dword ptr 010h[EAX],028h
> mov ECX,EAX
> mov EBX,5
> lea EDX,-018h[EBP]
> xor EAX,EAX
> mov [EDX],EAX
> mov 4[EDX],EAX
> mov 8[EDX],EAX
> mov 0Ch[EDX],EAX
> mov 010h[EDX],EAX
> push 5
> mov ESI,offset FLAT:_DATA
> push ESI
> call near ptr _printf
> xor EAX,EAX
> add ESP,010h
> pop ESI
> pop EBX
> leave
> ret
>
>
>
> This code too compiles, so A is sometimes computed at run-time and sometimes
> at compile-time:
>
> int[] foo(in int n) pure nothrow {
> int[] a;
> foreach (i; 0 .. n)
> a ~= i * 10;
> return a;
> }
> void main() {
> import core.stdc.stdio: printf;
> int n = 5;
> immutable int[] A = foo(n);
> }
>
>
>
> Now immutable arrays are sometimes seen as enums. I think this is a problem.
> I think in D compile-time is run only if it's evaluated in a context where
> compile-time values are required. But now the situation is more muddy,
> because knowing n at compile-time is not a way to ask A to be computed at
> compile-time.
>
> Another problem is that compile-time arrays in many situations are not
> efficient, they gets copied every time you use them, and I think that
> __d_arrayliteralTX performs a heap allocation. So now both enum and
> immutable arrays perform heap allocations every time you use them, but only
> in some situations.
>
> I think this is a messy situation, I think the fix for bug 8400 should be
> undone, and I think Issue 8400 should be fixed the other way, turning global
> immutable arrays too into run-time entities.
>
> The bug was fixed by Hara and accepted by Walter, both of them are very
> intelligent, so maybe I am just very wrong :-)
>
> Bye,
> bearophile
More information about the Digitalmars-d
mailing list