dmd
dmd copied to clipboard
fix Issue 14835 - Constant folding should not affect front end flow a…
…nalysis
Users should use static if if they need compile time conditional compilation.
Thanks for your pull request, @WalterBright!
Bugzilla references
| Auto-close | Bugzilla | Severity | Description |
|---|---|---|---|
| ✓ | 14835 | major | Constant folding should not affect front end flow analysis |
Testing this PR locally
If you don't have a local development environment setup, you can use Digger to test this PR:
dub run digger -- build "master + dmd#12311"
Blocked by https://github.com/dlang/druntime/pull/3417
There'll likely be much more of this. Sigh.
This does not fix the issue I reported. The reported issue was explicitly about static if.
I think this is a good fix, but not for issue 14835, rather for issue 13165.
@Geod24 I know, but it may provide the right solution to the static if issue.
Could you add a description about how this fix the reported issue then ?
Use static if if you need compile time flow analysis, use if if you want run time flow analysis. It's not the right words, but the idea is clear.
@WalterBright : If I understand correctly, you intend to solve the issue by recommending people to switch from the following:
bool isEven(int i)()
{
static if (i % 2) // static or not, the warning will get triggered if i is even
return true;
return false;
}
To the following:
bool isEven(int i)()
{
if (i % 2) // static or not, the warning will get triggered if i is even
return true;
return false;
}
I think that makes sense, but it goes against many developer's instinct which is to reach for static if whenever they can.
Hence, it would be really great if such a fix could come with a mention in the website (spec or article) explaining what should be the best practice, otherwise someone else is bound to run in the same issue and report it.
The concept here seems right to me, although I can't comment on the implementation. I bumped the old forum thread for this issue just in case someone else sees a serious problem with this approach that we don't.
you intend to solve the issue by recommending people to switch from the following:
Yes.
I agree that an if is to be preferred to a static if whenever possible. I am not sure however if you want unreachable warnings to be ignore for static branches though. Seems like it could have unintended consequences.
src/object.d(2215): Error: function object.ModuleInfo.namenoreturn exp;orassert(0); at end of function
yep. sure has unintended consequences.
src/object.d(2215): Error: function
There's a PR for that: https://github.com/dlang/druntime/pull/3417
If I understand this reasoning properly (didn't even look at the changes, I don't understand DMD), this doesn't fix the issue.
There are reasons to use static if vs if. For instance, static if forces CTFE for a function call, and also does not introduce a scope.
And in actuality, as I said in the bug report, the "code is unreachable" statement is incorrect. It's reachable, just not in this instantiation.
This is going to result in things like:
static if(doSomethingAtCTFE())
{
if(1) return retval; // trick the compiler
}
Which I don't think is a good look.
What happens when foreach on a CT tuple is used? That's another common source of spurious "unreachable" errors.
My previous comment notwithstanding, as long as the if(1) trick works, this at least gives a path to working around the issue, ugly as it is.
@schveiguy
There are reasons to use
static ifvsif. For instance,static ifforces CTFE for a function call, and also does not introduce a scope.
Although annoying, "not reachable" warnings caused by static if(predicate) statements can generally be worked around by adding else or static if(!predicate) as needed. Also, enum can be used to force CTFE function calls prior to a runtime if.
By contrast, there is no simple workaround for some of the spurious warnings that could theoretically be triggered by runtime control flow: https://github.com/dlang/dmd/pull/5229#issuecomment-198697655
(I'm not sure about static foreach - I don't think it was available yet when I last studied all of this.)
the "code is unreachable" statement is incorrect. It's reachable, just not in this instantiation.
That depends on your perspective. From mine, static if inserts code. If that insert makes other code unreachable, it is unreachable.
This is different from the if version. Whether the condition always evaluates to true or false depends on how far the compiler goes with constant folding, hence it is inherently unreliable. Therefore, it makes sense to not do flow analysis based on the condition.
this also probably needs a force push in order to restart all of the CIs
This is different from the
ifversion. Whether the condition always evaluates to true or false depends on how far the compiler goes with constant folding, hence it is inherently unreliable.
-preview=fieldwise is actually a good example of this problem because it enables dmd to const-fold == for structs without members. This has already caused problems for phobos which should work with and without that switch during the transition period.
Also needs to fix block_statement_only_with_nested_statement in compilable/test18199.d.
Now it's blocked by https://github.com/dlang/phobos/pull/8180
This seems to be green now. Should we merge this?
It's still not clear whether this fix satisfies users (See Steven's comment https://github.com/dlang/dmd/pull/12311#issuecomment-809453058), but if we go with "Constant folding should not affect front end flow analysis", then flow analysis of do {} while () and for () should get the same treatment. They consider constant-folded loop conditions, and this PR doesn't change that currently.
It's still not clear whether this fix satisfies users
I don't love that static if will still complain about unreachable code, but if there is a workaround like I said in https://github.com/dlang/dmd/pull/12311#issuecomment-809456454, then we can consider the issue resolved, and perhaps open another issue on making that workaround obsolete.
Note the original title of the bug was "Statement is not reachable doesn't play along generic code", which describes more accurately the problem I was having, and would not be fixed by this PR.
I'm not sure if the rebase was done correctly. Have to re-evaluate this.