Bug 14883 – static if does not work although an is expression produces 'true'
Status
RESOLVED
Resolution
WONTFIX
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
All
Creation time
2015-08-07T07:51:00Z
Last change time
2015-08-07T15:55:02Z
Assigned to
code
Creator
pastuhov85
Comments
Comment #0 by pastuhov85 — 2015-08-07T07:51:43Z
D 2.068.0-rc1
static if does not work although an is expression produces 'true'
import std.stdio;
auto foo(T)(T)
{
return 42;
}
struct Vector(T)
{
pragma(msg, is(typeof(foo(Vector.init)))); // prints true
static if(is(typeof(foo(Vector.init)))) {
static assert(false); // is not included
}
}
void main()
{
Vector!float v;
}
Related topic: http://forum.dlang.org/thread/[email protected]
Comment #1 by code — 2015-08-07T10:55:09Z
Digger sez:
commit 84abb30751cbb7b4a0f7aaca706c12807be029bf
Author: Walter Bright <[email protected]>
Date: Wed May 13 14:38:14 2015 -0700
dmd: Merge pull request #4635 from 9rnsr/fix14549
https://github.com/D-Programming-Language/dmd/pull/4635
Issue 14549 - isVirtualMethod does not work well with Github DMD
diff --git a/dmd b/dmd
index acbe13e..5ae249a 160000
--- a/dmd
+++ b/dmd
@@ -1 +1 @@
-Subproject commit acbe13ee54e024c0bba044d1146e244a5ea57502
+Subproject commit 5ae249a6737e2bd048eeef3b4897464b567b3408
Comment #2 by k.hara.pg — 2015-08-07T13:34:36Z
I agree the 2.068.0-rc1 behavior looks inconsistent. But I'm not sure the 2.067 behavior (reaching to the `static assert(false)` then fail to compile) is really intentional/designed behavior.
---
Let's explain what's happened:
When the init property access `Vector.init` happens, it would try to resolve all forward reference of field variable declarations inside the Vector struct.
During that, it would try to evaluate the static-if condition `(is(typeof(foo(Vector.init))))`. Until the condition is actually resolved to true, its then block is not reachable.
In 2.067, while the Vector.init analysis, compiler had gave up searching struct fields before the static-if condition evaluation finished. By that, Vector is fixed to no field struct, and the static-if condition `is(typeof(foo(Vector.init)))` is evaluated to true. Finally, compiler had reached to the static assert, then failed to compile.
In 2.068.0-rc1, the Vector.init analysis continues to evaluate the static-if condition (because there's no special reason to give up the search), and it fails by the "circular typeof definition" error - but the actual error message is hidden by is(...). Then the condition is evaluated to false and compiler won't reach to the static assert.
In both compiler versions, pragma(msg) is evaluated after the determination of Vector struct fields and its instance size. At that time, the expression Vector.init is always valid, then it will print 'true'.
---
To me the 2.068.0-rc1 behavior looks correct. In the test case code, the Vector struct is defined depending on its field definition - it's circular definition. Although it's sad that compiler reports nothing about the circle, the suppression of error message is the intentional design of the `is(...)` expression.
Comment #3 by code — 2015-08-07T15:55:02Z
So this is an circular forward reference issue that cannot be resolved similar to the following contradiction.
struct Foo
{
static if (Foo.init.tupleof.length == 0)
int anotherField;
}
You cannot access .init of a struct until all it's fields are known.
The IsExpression and __traits(compiles, ...) can be dangerous because they hide all compiler errors.
Maybe we should make an exception for forward reference issues and do report them even in speculative context?