import std.stdio;
uint bar = 0;
void main() {
start:
immutable uint foo = bar;
bar++;
writeln(foo);
goto start;
}
foo changes in this case. Is this a real bug, or is it considered undefined
behavior to use goto in this way?

I disagree: foo doesn't change there :þ.
Declaring a local variable like that actually creates a new scope behind
the scenes, containing everything up to '}' (taking nesting into
account, of course). This means the label is outside the scope of foo,
and foo gets "destroyed" when the goto jumps out of it. A "new" foo is
created (with a different value) when the program enters its scope.
This is basically the same as:
-----
while (true) {
immutable uint foo = bar;
bar++;
writefln(foo);
}
-----
or even:
-----
while (true) {
void nested_fn(uint foo) {
bar++;
writefln(foo);
}
nested_fn(bar);
}
-----
which show the behavior more clearly.

import std.stdio;
uint bar = 0;
void main() {
start:
immutable uint foo = bar;
bar++;
writeln(foo);
goto start;
}
foo changes in this case. Is this a real bug, or is it considered undefined
behavior to use goto in this way?

I disagree: foo doesn't change there :?.
Declaring a local variable like that actually creates a new scope behind
the scenes, containing everything up to '}' (taking nesting into
account, of course). This means the label is outside the scope of foo,
and foo gets "destroyed" when the goto jumps out of it. A "new" foo is
created (with a different value) when the program enters its scope.
This is basically the same as:
-----
while (true) {
immutable uint foo = bar;
bar++;
writefln(foo);
}
-----
or even:
-----
while (true) {
void nested_fn(uint foo) {
bar++;
writefln(foo);
}
nested_fn(bar);
}
-----
which show the behavior more clearly.

Then this is a really weird behavior:
void main()
{
start:
//int j = bar;
scope(exit)
writefln("exit");
writefln(bar);
bar++;
if (bar == 10)
return;
goto start;
}
scope(exit) is not called at all when the local is commented out and
called 10 times, otherwise. This implicit scope looks more like a bug
or misfeature to me. Not calling scope(exit) if there is no variable
declared is definitely a bug.

Then this is a really weird behavior:
void main()
{
start:
//int j = bar;
scope(exit)
writefln("exit");
writefln(bar);
bar++;
if (bar == 10)
return;
goto start;
}
scope(exit) is not called at all when the local is commented out and
called 10 times, otherwise. This implicit scope looks more like a bug
or misfeature to me. Not calling scope(exit) if there is no variable
declared is definitely a bug.

import std.stdio;
uint bar = 0;
void main() {
start:
immutable uint foo = bar;
bar++;
writeln(foo);
goto start;
}
foo changes in this case. Is this a real bug, or is it considered undefined
behavior to use goto in this way?

Hopefully I'm wrong but I believe that this is not a bug. It is incorrect
coding style.
As I've recently worked out from Walter's discussions, the compiler does
NOT enforce immutabilty or CAUSE things to be immutable. You should only
declare immutable those things that you know actually are already immutable
- like literals or stuff which is only ever assigned to once.
On the other hand, I think this should be a bug.
--
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell