A lot of non-IO functions can be computed at compile-time; why aren't they?

The vast majority of non-IO operations could simply be computed at compile-time, but are not; the vast majority of functions in Rust are not const, and so do not get computed at compile time... which is quite confusing to me, since a lot of these functions' outputs could be known at compile-time. This creates a cycle, where things that COULD be computed at compile-time are not because even the most basic functions, functions that SHOULD be const, are not. It makes the const feature essentially impossible to use anywhere unless you are doing something like 2 + 3, something that is done at compile time either way.

(Off the top of my head), there’s at least 2 major blockers for making many more things const

  • allocations are not supported at compiler time
  • calling trait methods doen’t work at compile time

both of these appear/happen very commonly in (non-IO) Rust code, and any allocation or usage of a trait operation immediately prevents the operation from being const. And both of these things are eventually supposed to be addressed in the future, but these kinds of things to require significant implementation- and/or design-work.

4 Likes

Like what?
What I think you have in mind - why is all the "pure" (side-effect-free code) not evaluated at compile time? Well it's really the turtles all the way down problem. Somewhere in the call stack of pure functions, you must have an impure function which gets the input - otherwise everything is constant. This situation is very rare. When it does happen, it isn't worth it to compile time evaluate everything.
That said, LLVM is very good at constant folding which is the formal term for what you're referring to.

I think it's a combination of a few things:

  • There's a lot of stuff that you just can't do in const fn yet - see the tracking issue. The list is getting smaller all the time, but it's still a work in progress.
  • Making a function const is an API commitment that you can't walk back without a breaking change - this means that for something to be made const in the standard library, it needs to be reasonably certain that the function won't be changed to need non-const features in the future.
5 Likes

Well, for one, const wasn't always in the language. It was added at some point, but then it's unreasonable to expect that all the already-existing code (including std) be immediately rewritten to be const. It's a gradual process, and many releases of Rust include changing certain functions to const. It won't happen overnight.

This is normal, const fn sucks at the beginning,
We had the same story in C++

A lot of const code cannot be implemented because language lacks features which on their own cannot be just implemented without tons of bickering about some UB or unsoundness shite

P.s. this is mostly due to fundamentally wrong approach to compile time execution, which is in most cases just repeating C++ history

For public const functions the return value–not only its type—is a type-level-observable part of their contract. Changing the return value can cause compile failures in downstream code. If you want the best compatibility and aren't sure that the computation is perfect you may want to keep your function non-const. This has no bearing on the compiler's ability to inline / compiletime execute it anyways: The analysis pass that decides if a function call should be const-evaluated can run over all functions, no matter their qualifier. The qualifier is a marker in the function contract.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.