Bug 17445 – [REG2.073.0] Disagreement between 'static assert' and 'static if'

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-05-27T11:47:56Z
Last change time
2018-11-29T14:46:44Z
Assigned to
No Owner
Creator
Dario Schiavon

Comments

Comment #0 by dario.schiavon — 2017-05-27T11:47:56Z
Using DMD32 v2.074.0. struct MyStruct { static assert(is(typeof(this = this))); // Here it passes. static if (!is(typeof(this = this))) static assert(0); // But here it fails. } If the is-expression was true in the assertion, how can it be false in the static-if condition? Notwithstanding the fact that, AFAIK, 'this' in this context (outside of a member function) shouldn't be defined. It compiles without errors with LDC2 v1.1.1 (which is based on DMD v2.071.2). The reason I wrote this code is I need to check whether the postblit constructor is defined (or alternatively opAssign) before I define a member function that makes use of it.
Comment #1 by dario.schiavon — 2017-05-27T12:05:08Z
See also https://issues.dlang.org/show_bug.cgi?id=17446 for a similar issue, which however is also present on LDC2 (so it can't actually be the same issue).
Comment #2 by stanislav.blinov — 2017-05-27T22:10:42Z
There are isCopyable and isAssignable traits in std.traits. Or you can roll your own: enum bool isCopyable(T) = is(typeof(() { T* a, b; *a = *b; })); using pointers in case e.g. the default ctor is disabled.
Comment #3 by stanislav.blinov — 2017-05-27T22:13:29Z
Sorry, that was isAssignable. isCopyable would be: enum bool isCopyable(T) = is(typeof(() { T* a; T b = *a; }));
Comment #4 by dario.schiavon — 2017-05-28T14:05:21Z
Stanislav, thanks for the tip. I knew about isAssignable but I had somehow missed isCopyable, which is exactly what I needed. However, I still cannot make my code work because of the bug shown here. isAssignable only gives the right answer as long as I don't try to use it as a static-if condition. For example: enum bool isCopyable(T) = is(typeof(() { T* a; T b = *a; })); struct MyStruct { enum result = isCopyable!MyStruct; pragma(msg, result); //static if (result) {} } This code (with the static-if commented out) correctly prints true. But if I leave the static-if in the struct's body, it prints false (DMD 2.074.0). If the static-if is moved outside of the struct's body, or if the condition doesn't involve the struct's name, then everything works as expected - but that's not what I need.
Comment #5 by dario.schiavon — 2017-05-28T14:27:02Z
I guess I can speculate about the reason for this behavior. What I'm doing, is making a copiability test on a type that hasn't been completely defined yet. As long as there's no static-if depending on the answer, the answer can be given. Otherwise, the code inserted by the static-if might cause the answer to change, leading to a paradox. Of course I had something else in mind when I wrote that code. I expected the answer to be based only on the code written so far, and I didn't intend the static-if to produce a paradox. But I guess it would be difficult for the compiler to prove that no paradox happens. If all of this is correct, than it would certainly be better that the compiler emit an error message and stop the compilation, rather than give an answer that is surely 100% wrong.
Comment #6 by dlang-bugzilla — 2017-07-02T01:08:29Z
This appears to be a regression. Introduced in https://github.com/dlang/dmd/pull/6388
Comment #7 by dlang-bugzilla — 2017-07-02T11:16:08Z
(In reply to Vladimir Panteleev from comment #6) > Introduced in https://github.com/dlang/dmd/pull/6388 Specifically: https://github.com/dlang/dmd/pull/5972 (PR to scope branch) Commit 62be2fbda0a09e1a5dd1fa6024f81c165057d386
Comment #8 by razvan.nitu1305 — 2018-11-29T14:46:44Z