www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Missed scope guard statements

reply Steve Jackson <sjackso cs.wisc.edu> writes:
(This is a report of what I believe is a "new" bug in the D compiler.  I'm not
sure whether this newsgroup is the appropriate place to report such things, but
it is the best I have been able to find.)

While experimenting with scope guard statements, I came across some unexpected
behavior.  This snippet:

{
 if( true ){ scope(exit) writef("hello"); }
 writefln(" world" );
}

Produces the output "hello world", as I expected.  However, if I remove the if
statement's braces, like so:

{
 if( true ) scope(exit) writef("hello");
 writefln( " world" );
}

... then the first writef call is skipped entirely, and the output is " world".
 No errors or compiler warnings are generated.

I'm using the dmd compiler v2.010 on Linux.
Mar 05 2008
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Hi Steve,

The place to report issues is here: http://d.puremagic.com/issues/ . You 
need to register a bugzilla account, then click "New" on the bottom bar, 
then "D", and enter a world of happiness and bug reporting.

I would guess that in both cases, that should produce the output:

  world
hello

Since the writefln("hello") is within a scope-exit, so should only fire 
as part of the function exit condition.

Steve Jackson wrote:
 (This is a report of what I believe is a "new" bug in the D compiler.  I'm not
sure whether this newsgroup is the appropriate place to report such things, but
it is the best I have been able to find.)
 
 While experimenting with scope guard statements, I came across some unexpected
behavior.  This snippet:
 
 {
  if( true ){ scope(exit) writef("hello"); }
  writefln(" world" );
 }
 
 Produces the output "hello world", as I expected.  However, if I remove the if
statement's braces, like so:
 
 {
  if( true ) scope(exit) writef("hello");
  writefln( " world" );
 }
 
 ... then the first writef call is skipped entirely, and the output is "
world".  No errors or compiler warnings are generated.
 
 I'm using the dmd compiler v2.010 on Linux.
Mar 05 2008
parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Wed, 05 Mar 2008 23:54:35 +0100, Robert Fraser  
<fraserofthenight gmail.com> wrote:

 Hi Steve,

 The place to report issues is here: http://d.puremagic.com/issues/ . You  
 need to register a bugzilla account, then click "New" on the bottom bar,  
 then "D", and enter a world of happiness and bug reporting.

 I would guess that in both cases, that should produce the output:

   world
 hello

 Since the writefln("hello") is within a scope-exit, so should only fire  
 as part of the function exit condition.
Actually, "hello world" is indeed correct output, as the scope(exit) is executed when it exits the scope of the if{}. The latter does indeed look like a bug, though. -- Simen
Mar 05 2008
prev sibling next sibling parent Gide Nwawudu <gide btinternet.com> writes:
On Wed, 05 Mar 2008 16:26:27 -0500, Steve Jackson
<sjackso cs.wisc.edu> wrote:

(This is a report of what I believe is a "new" bug in the D compiler.  I'm not
sure whether this newsgroup is the appropriate place to report such things, but
it is the best I have been able to find.)

While experimenting with scope guard statements, I came across some unexpected
behavior.  This snippet:

{
 if( true ){ scope(exit) writef("hello"); }
 writefln(" world" );
}

Produces the output "hello world", as I expected.  However, if I remove the if
statement's braces, like so:

{
 if( true ) scope(exit) writef("hello");
 writefln( " world" );
}

... then the first writef call is skipped entirely, and the output is " world".
 No errors or compiler warnings are generated.

I'm using the dmd compiler v2.010 on Linux.
Looks similar to this bug. http://d.puremagic.com/issues/show_bug.cgi?id=1765 Gide
Mar 06 2008
prev sibling parent reply Max Samukha <samukha voliacable.com.removethis> writes:
On Wed, 05 Mar 2008 16:26:27 -0500, Steve Jackson
<sjackso cs.wisc.edu> wrote:

(This is a report of what I believe is a "new" bug in the D compiler.  I'm not
sure whether this newsgroup is the appropriate place to report such things, but
it is the best I have been able to find.)

While experimenting with scope guard statements, I came across some unexpected
behavior.  This snippet:

{
 if( true ){ scope(exit) writef("hello"); }
 writefln(" world" );
}

Produces the output "hello world", as I expected.  However, if I remove the if
statement's braces, like so:

{
 if( true ) scope(exit) writef("hello");
 writefln( " world" );
}

... then the first writef call is skipped entirely, and the output is " world".
 No errors or compiler warnings are generated.

I'm using the dmd compiler v2.010 on Linux.
Looks like a bug but makes no sense in a real application anyway? if( true ) scope(exit) writef("hello"); is semantically the same as simply if( true ) writef("hello"); Do you have any use case for that?
Mar 06 2008
next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 06/03/2008, Max Samukha <samukha voliacable.com.removethis> wrote:
  if( true ) scope(exit) writef("hello");

 is semantically the same as simply
  if( true ) writef("hello");
For that matter, if (true) anything is the same as anything But I assume "if (condition)" what what was really intended. It seems to me that one could instead write: scope(exit) { if (condition) writef("hello") } That is, reverse the order of "scope" and "if".
Mar 06 2008
parent reply Max Samukha <samukha voliacable.com.removethis> writes:
On Thu, 6 Mar 2008 10:47:19 +0000, "Janice Caron"
<caron800 googlemail.com> wrote:

On 06/03/2008, Max Samukha <samukha voliacable.com.removethis> wrote:
  if( true ) scope(exit) writef("hello");

 is semantically the same as simply
  if( true ) writef("hello");
For that matter, if (true) anything is the same as anything
scope is redundant in your example because it is the only statement within if's scope. It executes a block of statements when the thread exits if's scope. you could as well omit it. if (condition) { scope(exit) { ... } } or without braces (according to you, doesn't work as expected) if (condition) scope(exit) { ... } should be equivalent to if (condition) { ... } In case of static if, which doesn't create a new scope: { static if (condition) scope (exit) writef("hello"); } // hello should be printed when control gets here (not tested)
But I assume "if (condition)" what what was really intended. It seems
to me that one could instead write:

    scope(exit) { if (condition) writef("hello") }

That is, reverse the order of "scope" and "if".
{ bool condition = ... ... scope(exit) { if (condition) writef("hello"); } ... } // hello is printed at this point if condition is true // and the function didn't return or throw before // the 'scope'
Mar 06 2008
parent Max Samukha <samukha voliacable.com.removethis> writes:
On Thu, 06 Mar 2008 15:37:07 +0200, Max Samukha
<samukha voliacable.com.removethis> wrote:

On Thu, 6 Mar 2008 10:47:19 +0000, "Janice Caron"
<caron800 googlemail.com> wrote:

On 06/03/2008, Max Samukha <samukha voliacable.com.removethis> wrote:
  if( true ) scope(exit) writef("hello");

 is semantically the same as simply
  if( true ) writef("hello");
For that matter, if (true) anything is the same as anything
scope is redundant in your example because it is the only statement within if's scope. It executes a block of statements when the thread exits if's scope. you could as well omit it. if (condition) { scope(exit) { ... } } or without braces (according to you, doesn't work as expected) if (condition) scope(exit) { ... } should be equivalent to if (condition) { ... } In case of static if, which doesn't create a new scope: { static if (condition) scope (exit) writef("hello"); } // hello should be printed when control gets here (not tested)
But I assume "if (condition)" what what was really intended. It seems
to me that one could instead write:

    scope(exit) { if (condition) writef("hello") }

That is, reverse the order of "scope" and "if".
{ bool condition = ... ... scope(exit) { if (condition) writef("hello"); } ... } // hello is printed at this point if condition is true // and the function didn't return or throw before // the 'scope'
Sorry, Janice, somehow my brain mistook you for Steve. Please ignore
Mar 06 2008
prev sibling next sibling parent Steve Jackson <sjackso cs.wisc.edu> writes:
Max Samukha Wrote:
 Do you have any use case for that?
No. I encountered this while experimenting with the behavior of scope(), not while building any particular application. I agree that my example is a corner case. But I thought it best to raise the issue in case it reflects some more subtle problem in the compiler. I appreciate the prompt responses!
Mar 06 2008
prev sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Max Samukha wrote:
 On Wed, 05 Mar 2008 16:26:27 -0500, Steve Jackson
 <sjackso cs.wisc.edu> wrote:
 
 (This is a report of what I believe is a "new" bug in the D compiler.  I'm not
sure whether this newsgroup is the appropriate place to report such things, but
it is the best I have been able to find.)

 While experimenting with scope guard statements, I came across some unexpected
behavior.  This snippet:

 {
 if( true ){ scope(exit) writef("hello"); }
 writefln(" world" );
 }

 Produces the output "hello world", as I expected.  However, if I remove the if
statement's braces, like so:

 {
 if( true ) scope(exit) writef("hello");
 writefln( " world" );
 }

 ... then the first writef call is skipped entirely, and the output is "
world".  No errors or compiler warnings are generated.

 I'm using the dmd compiler v2.010 on Linux.
Looks like a bug but makes no sense in a real application anyway? if( true ) scope(exit) writef("hello"); is semantically the same as simply if( true ) writef("hello"); Do you have any use case for that?
Compile-time values could evaluate to true, and compile-time code generation could very easily create code that would seem silly to write directly. So it's a valid problem.
Mar 06 2008
parent Max Samukha <maxsamukha gmail.com> writes:
Robert Fraser wrote:

 
 Compile-time values could evaluate to true, and compile-time code
 generation could very easily create code that would seem silly to write
 directly. So it's a valid problem.
You are right, this is a problem. Interestingly, mixing in the ThenStatement works fine: ---- if (true) mixin ("scope(exit) Stdout(\"hello \").newline;"); // prints hello as expected. ---- I guess, this is because a string mixin creates a new scope, which is a bug (or a feature? The specification is not specific on that): ---- mixin ("scope(exit) Stdout(\"Exiting scope.\").newline;"); Stdout("After mixin").newline; ---- outputs: Exiting mixin scope. After mixin while I would expect the reverse.
Mar 07 2008