Bug 21078 – static if(is(T IDENT)) introduces IDENT beyond static if's scpe

Status
RESOLVED
Resolution
DUPLICATE
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2020-07-26T02:09:50Z
Last change time
2023-07-13T15:39:31Z
Assigned to
No Owner
Creator
Adam D. Ruppe

Comments

Comment #0 by destructionator — 2020-07-26T02:09:50Z
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!
Comment #1 by ag0aep6g — 2020-07-26T10:56:46Z
(In reply to Adam D. Ruppe from comment #0) > 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. The spec is quite clear on this (third paragraph): "The Identifier forms can only be used if the IsExpression appears in a StaticIfCondition." Not saying that that rule makes any sense, but it's there.
Comment #2 by destructionator — 2020-07-26T12:51:22Z
> The spec is quite clear on this (third paragraph): My English is sloppy, by "this" I mean the extent of the scope, that it would survive INT outside the static if (I edited in the other thing later and forgot to clarify). The FLOAT one is defined, but the INT one is the one I care about anyway.
Comment #3 by b2.temp — 2020-07-28T02:31:59Z
One thing is that it is specified `static if` doesn't introduce a "logical" scope also there's one in the syntax, so "lexicographically" (let's call this like that) void main() { static if(is(int INT)) { // <-- lexical scope but not "logical" INT a; } INT b; }
Comment #4 by nick — 2023-02-21T18:23:42Z
This was stated as intended behaviour but I can't find the invalid bug now. The reason is that an identifier can't be added to an existing scope only for part of the remaining scope. If there are no braces for the static if, and if the identifier is valid inside the static if, then it must be valid after it too, as they share a single scope.
Comment #5 by nick — 2023-07-13T15:39:31Z
*** This issue has been marked as a duplicate of issue 18609 ***