Thread overview
Re: Is enum static?
Aug 20, 2013
Jonathan M Davis
Aug 20, 2013
Dicebot
Aug 20, 2013
H. S. Teoh
August 20, 2013
On Tuesday, August 20, 2013 13:35:43 H. S. Teoh wrote:
> On Tue, Aug 20, 2013 at 03:38:18PM -0400, Jonathan M Davis wrote:
> > On Tuesday, August 20, 2013 21:33:23 John Colvin wrote:
> > > I presume there's a good reason why we don't have:
> > > enum a = [1,2,3,4];
> > > assert assert(is(typeof(a) == int[4]));
> > > 
> > > this works after all:
> > > enum int[4] a = [1,2,3,4];
> > > assert assert(is(typeof(a) == int[4]));
> > 
> > Array literals are always dynamic arrays, so [1, 2, 3, 4] is int[] by definition.
> 
> Wait, is that dynamic *by default*, or is it *always* dynamic? If the latter, I think we should fix the language.

It is _always_ dynamic.

> It should be possible to write
> things like:
> 
> byte[] a = [1,2,3,4];
> 
> and *not* incur the overhead of allocating an int[] and then copying it over (with implicit casting) to the byte[].

That doesn't allocate anymore, and there are plenty of cases like that (several of which I'm sure still allocate), but it's essentially an optimization any time that an array literal doesn't end up allocating.

> On that note, I find it Very Evil that this doesn't work properly:
> 
> char[] a = "abc";
> const(char)[] b = "abc";
> 
> Instead, you have to do:
> 
> char[] a = "abc".dup;
> const(char)[] b = "abc".dup;
>
> I can accept that having an explicit .dup or .idup is a good thing when the source string is a variable, but in this case, the compiler *should* be smart enough to know, hey, "abc" is a literal and is being immediately assigned to a char[], so the user must intend that it's used only to initialize the char[], so I don't need to actually allocate a *string* (as in, immutable(char)[]) for the literal and copy it, but instead, I should generate code to initialize each array element.
> 
> tl;dr, I think D literals are assigned a type far too early in the compilation process. The intended meaning of a literal shouldn't be bound until the compiler is able to infer from context what type is actually required.

Honestly, I have no problem with this. The type of string literal is immutable(char)[], so having to dup it makes sense. And you don't incur any extra allocations, because string literals are part of the generated binary rather than being allocated at runtime (and on Linux, they end up in the read- only portion). So, you're only allocating once (when you dup), which is what what happen if the compiler allowed the code that you're looking for.

- Jonathan M Davis
August 20, 2013
On Tue, Aug 20, 2013 at 05:01:36PM -0400, Jonathan M Davis wrote:
> On Tuesday, August 20, 2013 13:35:43 H. S. Teoh wrote:
[...]
> > It should be possible to write things like:
> > 
> > byte[] a = [1,2,3,4];
> > 
> > and *not* incur the overhead of allocating an int[] and then copying it over (with implicit casting) to the byte[].
> 
> That doesn't allocate anymore, and there are plenty of cases like that (several of which I'm sure still allocate), but it's essentially an optimization any time that an array literal doesn't end up allocating.

That's what troubles me. Allocations shouldn't be the default; they should be fallback when they can't be avoided.


> > On that note, I find it Very Evil that this doesn't work properly:
> > 
> > char[] a = "abc";
> > const(char)[] b = "abc";
> > 
> > Instead, you have to do:
> > 
> > char[] a = "abc".dup;
> > const(char)[] b = "abc".dup;
> >
> > I can accept that having an explicit .dup or .idup is a good thing when the source string is a variable, but in this case, the compiler *should* be smart enough to know, hey, "abc" is a literal and is being immediately assigned to a char[], so the user must intend that it's used only to initialize the char[], so I don't need to actually allocate a *string* (as in, immutable(char)[]) for the literal and copy it, but instead, I should generate code to initialize each array element.
> > 
> > tl;dr, I think D literals are assigned a type far too early in the compilation process. The intended meaning of a literal shouldn't be bound until the compiler is able to infer from context what type is actually required.
> 
> Honestly, I have no problem with this. The type of string literal is immutable(char)[], so having to dup it makes sense. And you don't incur any extra allocations, because string literals are part of the generated binary rather than being allocated at runtime (and on Linux, they end up in the read- only portion). So, you're only allocating once (when you dup), which is what what happen if the compiler allowed the code that you're looking for.
[...]

It's not just with strings. What about this:

	byte[] a = [1,2,3];
	uint[] b = [1,2,3];
	long[] c = [1,2,3];

?  Will the compiler emit an int[] (or immutable(int)[]?) to hold each
literal, and then copy the contents (with casting) to the target arrays
at runtime?

I argue that [1,2,3] has a different meaning in each of these lines. On
the first line, it should mean [byte(1), byte(2), byte(3)], on the
second line it should mean [1u, 2u, 3u], and on the third line it should
mean [1L, 2L, 3L]. The compiler should not assign it to int[] except as
a fallback (e.g., if you wrote auto d = [1,2,3];, then it would default
to int[]).

This issues shows up in places like IFTI, where [1,2,3] is assigned too early to be int[], so it fails to match a template function that expects byte[]. IFTI can of course be hacked to work around this (and maybe already has), but the fundamental problem is that literals are assumed to be of a particular type far too early on. They really should have flexible type, adaptable to the context they appear in. A literal like [1,2,3] should not be be assumed to be int[] until the compiler determines that the context does not provide sufficient information to deduce the intended type. IOW, int[] should be a *fallback* type for [1,2,3], not something presumed up-front.


T

-- 
Which is worse: ignorance or apathy? Who knows? Who cares? -- Erich Schubert
August 20, 2013
On Tuesday, 20 August 2013 at 21:01:48 UTC, Jonathan M Davis wrote:
> Honestly, I have no problem with this. The type of string literal is
> immutable(char)[], so having to dup it makes sense.

Problem is that literal with has a known fixed size results in dynamic array instead of a static stack-allocated one.