July 26, 2020
https://issues.dlang.org/show_bug.cgi?id=21078

          Issue ID: 21078
           Summary: static if(is(T IDENT)) introduces IDENT beyond static
                    if's scpe
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: destructionator@gmail.com

The following code is valid D:

---
void main() {
        static if(is(int INT))
                INT a;
        INT b;
}
---


And this is bizarre. If you do

        bool o = is(float FLOAT);

outside the static if btw you get:

Error: can only declare type aliases within static if conditionals or tatic asserts


The spec is not clear on this. It says:

https://dlang.org/spec/expression.html#IsExpression

is ( Type Identifier )
The condition is satisfied if Type is semantically correct. If so, Identifier
is declared to be an alias of Type.



Now, I know the spec says "It does not introduce a new scope even if { } are used for conditionally compiled statements. " and I know why this is useful.

But the `static if(is())` pattern is different. If it evaluates to false, the identifier alias is NOT introduced, so it only really makes sense inside the static if anyway, so the normal justification for static if not making a scope doesn't apply.

And this does have a practical cost: static foreach.

static foreach(overload; __traits(getOverloads, foo, "bar"))
static if(is(typeof(overload) Params == __parameters))


That construct will lead to

forward.d(3): Error: declaration Params is already defined


errors if there's more than one item being iterated. The double {{}} trick doesn't apply btw since that is not valid in a declaration context (and it would be counterproductive if it was, since the whole point of static foreach here is to introduce new declarations to the existing scope!)


Since the spec is unclear on this special case, it serves no practical purpose and does have a real world downside, I wanna file this as a bug. I suspect it is just an oversight rather than a deliberate design.

BTW people I talked to on chat didn't even think this code compiled!

--