Solidity Needs Consistent Semantics

For a language that is mission critical and is relied upon to secure billions of $ in assets it seems self evident to me that there should not be subtle semantic changes caused by a simple compiler optimization flag being turned on: Solidity IR-based Codegen Changes — Solidity 0.8.31 documentation

While I understand that under the hood much more is going on than simply “optimizing the code” when you turn on --via-ir it seems that it’s crucial to not introduce more footguns than necessary into the language.

If the language feature is niche / hard to recreate the behavior of shouldn’t it just be deprecated and removed instead? Isn’t a seemingly backwards compatible but actually not implementation the worst of both worlds?

As a smart contract developer & auditor I judge it to be easier to update code that relies on removed features rather than have to think about & engineer around the possible behaviors of the language under the two modes.

What can be done to avoid this kind of thing in the future?

1 Like

--via-ir is not an optimization flag. It switches the whole code generation backend. It’s orthogonal to whether the code is being optimized or not. It may be better to think about it as a whole new compiler than just a parameter change in the old one.

The plan is exactly to deprecate and remove the old backend. If everything went as planned the switch would have been quick and the semantic changes a non-issue. We routinely ship semantic changes in breaking versions and the switch between backends is such a change as well. Switch to --via-ir is not something that can ship quietly in 0.8.x either.

Unfortunately the work on the new backend took longer than expected and we ended up in a situation where both exist side by side for a significant period of time. Still, the expectation is for projects to migrate to IR once they feel it’s good enough for them, not stay compatible with both indefinitely.

As for what can be done, we could theoretically backport some of the changes to the legacy backend in 0.9.0 to make the backends closer in behavior and ease the transition. Perhaps for some changes this should have been done already in the past instead of putting them only in the new backend. For example, I suspect that doing this with the initialization order would be feasible. The problem is that not all changes are of this kind. Especially the new parameter evaluation order is intimately tied to the implementation and backporting it would be a lot of effort for little gain and a lot of risk or introducing subtle bugs. There’s a reason why writing code that depends on evaluation order is generally considered a bad practice. Such backporting would also have an impact on the general timeline and work on the IR backend.

Overall, I feel there’s not that much we can do right now other than just power through it. Our current work on the SSA CFG is pretty advanced by now and IR by default is not far off. We know it’s frustating to users and auditors and we feel that frustration as well, but the problem will ultimately be solved with time.