Thread overview
Unmatched static array size assignment
Apr 13, 2011
Andrej Mitrovic
Apr 13, 2011
Andrej Mitrovic
Apr 13, 2011
bearophile
Apr 13, 2011
Andrej Mitrovic
Apr 13, 2011
bearophile
Apr 14, 2011
simendsjo
Apr 14, 2011
bearophile
April 13, 2011
Code:

void main()
{
    static string[2] szFormat = ["%s, %s"];
}

This compiles, but this is buggy code. The first declaration should have been: static string[2] szFormat = ["%s", "%s"];

I can't tell whether the first case is legit code. You might *want* to initialize all the elements with the same single initializer. But in that case, you would write:
static string[2] szFormat = "%s, ";

So, without the '[]'.

If you remove static from the declaration (it's still a static array, I know!), you'll get a nice runtime error:
object.Exception@src\rt\arraycat.d(31): lengths don't match for array copy

Actually it's not a nice error message since you can't even tell what causes the error.

So in retrospect:
// no error until a call to writefln,
// which could still potentially not fail => possible bugs
string[2] szFormat = ["%s, %s"];

// error at runtime, the compiler could have caught this though static string[2] szFormat2 = ["%s, %s"];

April 13, 2011
Andrej Mitrovic Wrote:

> So in retrospect:
> // no error until a call to writefln,
> // which could still potentially not fail => possible bugs
> string[2] szFormat = ["%s, %s"];
> 
> // error at runtime, the compiler could have caught this though static string[2] szFormat2 = ["%s, %s"];
> 

Sorry, I've accidentally reversed the two. Fixed:
// no error until a call to writefln,
// which could still potentially not fail => possible bugs
static string[2] szFormat = ["%s, %s"];

// error at runtime, the compiler could have caught this though
string[2] szFormat2 = ["%s, %s"];

April 13, 2011
Andrej Mitrovic:

> void main()
> {
>     static string[2] szFormat = ["%s, %s"];
> }
> 
> This compiles, but this is buggy code.

Please vote this old bug report of mine, about this problem: http://d.puremagic.com/issues/show_bug.cgi?id=3849

See also:
http://d.puremagic.com/issues/show_bug.cgi?id=481

Bye,
bearophile
April 13, 2011
Yeah, I don't have a lot of votes left, in fact I only have one left. :s

I think we're basically on our own when it comes to these kinds of issues. We'll either get a compiler with a better warning system (maybe GDC.. DDMD in the future), or we'll make some kind of Lint tool for D. The latter approach might even be better since you could probably customize such a tool to fit your needs.
April 13, 2011
Andrej Mitrovic:

> We'll either get a compiler with a better warning system

In that bug report I ask for an error, not a warning.


> or we'll make some kind of Lint tool for D.

Eventually some lint tools will surely be written for D, but lot of people don't use lints. What I am looking here is a little change in the language. The full proposal has three parts:

Refuse array lengths that don't match:
int[2] a = [1]; // compile-time error
main() {}

Introduce [$] to infer the array length at the definition point:
int[$] a = [1]; // OK
main() {}

And introduce a syntax like "..." for the uncommon partial specification situations:
int[4] a = [1, 2, ...]; // OK
main() {}

Bye,
bearophile
April 14, 2011
On 13.04.2011 22:56, Andrej Mitrovic wrote:
> Code:
>
> void main()
> {
>      static string[2] szFormat = ["%s, %s"];
> }
>
> This compiles, but this is buggy code. The first declaration should have been:
> static string[2] szFormat = ["%s", "%s"];
>
> I can't tell whether the first case is legit code. You might *want* to initialize all the elements with the same single initializer. But in that case, you would write:
> static string[2] szFormat = "%s, ";
>
> So, without the '[]'.
>
> If you remove static from the declaration (it's still a static array, I know!), you'll get a nice runtime error:
> object.Exception@src\rt\arraycat.d(31): lengths don't match for array copy
>
> Actually it's not a nice error message since you can't even tell what causes the error.
>
> So in retrospect:
> // no error until a call to writefln,
> // which could still potentially not fail =>  possible bugs
> string[2] szFormat = ["%s, %s"];
>
> // error at runtime, the compiler could have caught this though
> static string[2] szFormat2 = ["%s, %s"];
>

Why is this a bug? Static means it's only one instance (per thread), right? The compiler cannot know if you meant to fill the entire array or if you meant something like this

static string[2] szFormat = ["%s, %s"];

void main() {
    szFormat[1] = "%d";
    assert(szFormat == ["%s, %s", "%d"]);
}
April 14, 2011
simendsjo:

> Why is this a bug?

Currently it isn't. But I (and few other people) have asked for it to be a bug, because it sometimes leads to not catching a programmer mistake.


> Static means it's only one instance (per thread), right? The compiler cannot know if you meant to fill the entire array or if you meant something like this
> 
> static string[2] szFormat = ["%s, %s"];
> 
> void main() {
>      szFormat[1] = "%d";
>      assert(szFormat == ["%s, %s", "%d"]);
> }

The idea in the proposal on Bugzilla is that a literal like this is a bug: static string[2] szFormat = ["%s, %s"];

If you want to fill some space later there is this syntax that explicitly tells the compiler some items are left undefined (Python Zen rule: explicit is better than implicit):
static string[2] szFormat = ["%s, %s", ...];

There is also this syntax to auto determination of the fixed length: static string[$] szFormat = ["%s, %s"]; // length == 1

Bye,
bearophile