Thread overview
NoScopeStatement violates C compatibility principal.
May 28, 2013
monarch_dodra
May 28, 2013
bearophile
May 28, 2013
Kenji Hara
May 28, 2013
monarch_dodra
May 28, 2013
monarch_dodra
May 28, 2013
Ali Çehreli
May 29, 2013
bearophile
May 29, 2013
monarch_dodra
May 28, 2013
I have created before two threads about the weird semantics of labeled block statements. In a word: putting a label before a block means that block does not create a scope, and the variables created inside that scope will "leak" to the outside of said scope. I've found this to be problematic on several points:

1. No use case for this
2. You can accidentally break code by placing a label before a block (but without meaning to label the actual block)
3. Deviates from C.

What kind of bothers me most is the combination 1 & 3: Why??? I've complained about this before, and the answer was: "According to spec", but to the question "why are the specs like this", I have yet to get an answer.

----------------
The reason I'm bringing this up (again), is that it bit me in the ass very recently. According to TDPL:

"If a numeric expression compiles in the C language and also compiles in D, its
type will be the same in both languages (note that not all C expressions must be
accepted by D)."

Followed by

"Rule 1 makes things just a tad more complicated than they would otherwise be, but D overlaps enough with C and C++ to inspire people to simply copy and paste entire functions into D programs. Now it’s all right if D occasionally refuses to compile certain constructs for safety or portability reasons; but if it compiled that 2000-line encryption package and ran it with different results, life would definitely not be good for the hapless victim."

So basically, this is saying "If your C code compiles in D, you'll get the same result. I guarantee it :)"

Here's a (reduced) C program:

----
int i = 3;

void main()
{
  {
    int some_condition = 1;
    if ( some_condition )
      goto block_end;

    /* dummy code */
  } block_end:

  {
    int i = 7;
    printf("%i", i);
  }

  printf("%i", i);
}
----
C prints: "70"
D prints: "77"

Oops!

I realize 99% of people don't use goto or labels too much, but this doesn't mean it shouldn't be addressed. For me, D has been about being a "smooth experience", and this makes so little sense to me it infuriates me.

I don't see how this could help anyone, but I do see how it can create bugs, and these kinds of cases are what D strives to avoid. "Fixing" would probably break nothing.

-------------------
I'd like to make a push to get the specs changed in regards to this. I'd like to get others' opinion on the matter, in particular, if anybody can think of a rationale for the current behavior. And if there is no rationale, how much support there is for changing it. (in which case I'll file the corresponding ER).
May 28, 2013
monarch_dodra:

> So basically, this is saying "If your C code compiles in D, you'll get the same result. I guarantee it :)"

It's a general rule, but it has some exceptions, like C programs that rely on global floating point variables initialized to 0, or when you use a fixed-sized array, that D passes by value and C by pointer.


> Here's a (reduced) C program:
>
> ----
> int i = 3;
>
> void main()
> {
>   {
>     int some_condition = 1;
>     if ( some_condition )
>       goto block_end;
>
>     /* dummy code */
>   } block_end:
>
>   {
>     int i = 7;
>     printf("%i", i);
>   }
>
>   printf("%i", i);
> }
> ----
> C prints: "70"
> D prints: "77"

This should go in some page that lists the differences between C and D.


> if anybody can think of a rationale for the current behavior. And if there is no rationale, how much support there is for changing it.

It's bad to break C backwards compatibility for free, so if it's not useful for D then and it should be fixed.

Bye,
bearophile
May 28, 2013
I think this is a corner case bug of current dmd parser.

Kenji Hara


2013/5/28 monarch_dodra <monarchdodra@gmail.com>

> I have created before two threads about the weird semantics of labeled block statements. In a word: putting a label before a block means that block does not create a scope, and the variables created inside that scope will "leak" to the outside of said scope. I've found this to be problematic on several points:
>
> 1. No use case for this
> 2. You can accidentally break code by placing a label before a block (but
> without meaning to label the actual block)
> 3. Deviates from C.
>
> What kind of bothers me most is the combination 1 & 3: Why??? I've complained about this before, and the answer was: "According to spec", but to the question "why are the specs like this", I have yet to get an answer.
>
> ----------------
> The reason I'm bringing this up (again), is that it bit me in the ass very recently. According to TDPL:
>
> "If a numeric expression compiles in the C language and also compiles in
> D, its
> type will be the same in both languages (note that not all C expressions
> must be
> accepted by D)."
>
> Followed by
>
> "Rule 1 makes things just a tad more complicated than they would otherwise be, but D overlaps enough with C and C++ to inspire people to simply copy and paste entire functions into D programs. Now it’s all right if D occasionally refuses to compile certain constructs for safety or portability reasons; but if it compiled that 2000-line encryption package and ran it with different results, life would definitely not be good for the hapless victim."
>
> So basically, this is saying "If your C code compiles in D, you'll get the same result. I guarantee it :)"
>
> Here's a (reduced) C program:
>
> ----
> int i = 3;
>
> void main()
> {
>   {
>     int some_condition = 1;
>     if ( some_condition )
>       goto block_end;
>
>     /* dummy code */
>   } block_end:
>
>   {
>     int i = 7;
>     printf("%i", i);
>   }
>
>   printf("%i", i);
> }
> ----
> C prints: "70"
> D prints: "77"
>
> Oops!
>
> I realize 99% of people don't use goto or labels too much, but this doesn't mean it shouldn't be addressed. For me, D has been about being a "smooth experience", and this makes so little sense to me it infuriates me.
>
> I don't see how this could help anyone, but I do see how it can create bugs, and these kinds of cases are what D strives to avoid. "Fixing" would probably break nothing.
>
> -------------------
> I'd like to make a push to get the specs changed in regards to this. I'd like to get others' opinion on the matter, in particular, if anybody can think of a rationale for the current behavior. And if there is no rationale, how much support there is for changing it. (in which case I'll file the corresponding ER).
>


May 28, 2013
On Tuesday, 28 May 2013 at 16:38:50 UTC, Kenji Hara wrote:
> I think this is a corner case bug of current dmd parser.
>
> Kenji Hara

It's not a corner case. It's the spec.

It's a "LabeledStatement" : "NoScopeStatement"
http://dlang.org/statement.html#LabeledStatement

I was finally able to track down the original bug report, from really long ago:

"Label causes scope to collapse into parent"
http://d.puremagic.com/issues/show_bug.cgi?id=199

It was closed as "won't fix" by Walter:
http://d.puremagic.com/issues/show_bug.cgi?id=199#c6

> Walter Bright 2008-06-23 17:00:19 PDT
>
> Since the compiler is behaving according to spec, I don't want to change this because it could break existing code, and there doesn't seem to be a compelling reason to do so.

> Walter Bright 2008-06-23 17:29:31 PDT
> 
> The test case behaves as expected, because labels do not introduce a new scope when followed by { }.

I hope I just provided a compelling reason why this is bad
behavior. And I don't think we'd break anything)
May 28, 2013
On Tuesday, 28 May 2013 at 17:54:32 UTC, monarch_dodra wrote:
> On Tuesday, 28 May 2013 at 16:38:50 UTC, Kenji Hara wrote:
>> I think this is a corner case bug of current dmd parser.
>>
>> Kenji Hara
>
> It's not a corner case. It's the spec.

EDIT: Well, that or I could be miss-interpreting the spec, along with walter having come to a wrong conclusion about the bug report.

I can't say without Walter's input.
May 28, 2013
On 05/28/2013 10:54 AM, monarch_dodra wrote:

> It's not a corner case. It's the spec.
>
> It's a "LabeledStatement" : "NoScopeStatement"
> http://dlang.org/statement.html#LabeledStatement

It is still a bug because NoScopeStatement does not mean "expand into current scope." It means "do not introduce a scope" and clearly allows blocked statements:

NoScopeStatement:
    ;
    NonEmptyStatement
    BlockStatement

  http://dlang.org/statement.html#NoScopeStatement

Ali

May 29, 2013
Ali Çehreli:

> It is still a bug because NoScopeStatement does not mean "expand into current scope." It means "do not introduce a scope" and clearly allows blocked statements:
>
> NoScopeStatement:
>     ;
>     NonEmptyStatement
>     BlockStatement

So we reopen issue 199 or we create a new one?

Bye,
bearophile
May 29, 2013
On Wednesday, 29 May 2013 at 09:51:58 UTC, bearophile wrote:
> Ali Çehreli:
>
>> It is still a bug because NoScopeStatement does not mean "expand into current scope." It means "do not introduce a scope" and clearly allows blocked statements:
>>
>> NoScopeStatement:
>>    ;
>>    NonEmptyStatement
>>    BlockStatement
>
> So we reopen issue 199 or we create a new one?
>
> Bye,
> bearophile

I reopened it. Its not a new issue, so I don't think it warrants a new thread.

EDIT: I did file this though, which is kind of related: http://d.puremagic.com/issues/show_bug.cgi?id=10199