www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Is this a bug?

reply Robert Clipsham <robert octarineparrot.com> writes:
I've been staring blankly at this for a while now and want some input 
from others:

----
void foo(T, U...)(bool arg)
{
     if (arg)
     {
         assert(T.tupleof.length == U.length);
         assert(arg); /* Line 6 */
         // Or some other code here
     }
}
struct A {}
void main()
{
     foo!(A, int)(false);
}
----

When compiled with warnings:

$ dmd -w test.d
test.d(6): Warning: statement is not reachable

So what appears to be happening here is that dmd is constant folding 
T.tupleof.length == U.length to false, then assert(arg) can never 
happen, so the warning is given.

It is obvious, however, that the assertion will never be executed 
anyway. Has anyone else run into this situation? The compile time 
parameters only need to match based on the runtime value provided (other 
branches in the code don't have such strict requirements for the compile 
time parameters).

Is there some way around this? (other than compiling without -w)
I can't help but feel what I'm doing isn't right some how.

Apologies if this makes no sense, I'm rather tired.

-- 
Robert
http://octarineparrot.com/
Apr 20 2012
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 20 Apr 2012 15:21:12 -0400, Robert Clipsham  
<robert octarineparrot.com> wrote:

 I've been staring blankly at this for a while now and want some input  
 from others:

 ----
 void foo(T, U...)(bool arg)
 {
      if (arg)
      {
          assert(T.tupleof.length == U.length);
          assert(arg); /* Line 6 */
          // Or some other code here
      }
 }
 struct A {}
 void main()
 {
      foo!(A, int)(false);
 }
 ----

 When compiled with warnings:

 $ dmd -w test.d
 test.d(6): Warning: statement is not reachable

 So what appears to be happening here is that dmd is constant folding  
 T.tupleof.length == U.length to false, then assert(arg) can never  
 happen, so the warning is given.

Also note that assert(0), which is what that line reduces to, is *not* removed for release builds.
 It is obvious, however, that the assertion will never be executed anyway.

No it isn't. this: foo!(A, int)(true); compiles to the same exact template function instantiation. arg is a runtime parameter, not determinable at compile-time, and therefore the compiler must include the branch.
 Is there some way around this? (other than compiling without -w)
 I can't help but feel what I'm doing isn't right some how.

Use static assert/static if when you expect something that is determined at compile time to be a certain way. Not only will it be more efficient code, but if it's *not* compile-time determined, you will get an error from the compiler. -Steve
Apr 20 2012