Scala 3 inline compilation error

Hi everyone,
I am trying to do a simple inline logic which should generate compilation time error if invalid. Here is the code. I don’t understand why this shows error. Isn’t the value a constant at the compilation time ?
If I change the versionNo to Int and use < 0 as the check, then it works fine.

Could someone tell me why this is not possible

import scala.compiletime.*

object InlineCompilerError {
  inline def checkVersion(inline versionNo: String) = {
    if (versionNo.isEmpty()) {
      error("Wrong version numbering! ")
    } else {
      println(s"Correct version information")

  def compilerErrorMain =

The error is coming at the main method even with a valid string.

I believe you also need an inline if

Thanks for you reply.
With inline if, it gives error that the if statement can’t be inlined.
* Cannot reduce inline if because its condition is not a constant value: "1.2".isEmpty()

Here is the scastie link for reference:

There you have the answer, str.isEmpty couldn’t be evaluated at compile time. No idea why.

Yeah, but isn’t the value a compile time constant? I am confused because of that.

The value is indeed a constant, the problem is the isEmpty
But, I don’t understand why the compiler can’t evaluate that.

My idea was to use a regex to validate this version number. Since that didn’t work, I shortened code to check if a simple isEmpty could work.
I get the same error even if I use the condition as “1.2”.isEmpty() in if condition. I was not sure what is going on there,
If i change the condition to

inline if (versionNo != "1.2")

then it works, strange that the isEmpty and any other string operations doesnt work

Hmm. String.isEmpty() is a JVM function, right? So it’s definitely not marked inline itself, and it wouldn’t astonish me if between those two facts, it becomes ineligible for inline use.

(Just guessing, mind – I haven’t even begun to play with modern inline – but it wouldn’t surprise me.)

I mean, that was my rationale as well; also from someone who hasn’t played a lot with inline
However, I was under the impression that the compiler could simply evaluate that logic.

I am lost at this moment. Is it only possible to use numbers?
Any other ideas to try to work around this? I mean, I want to validate a version string at compile time and fail compilation if wrong format is used.

You can match an exact string literal at compile-time. Here’s a little REPL session illustrating this:

scala> transparent inline def check(s: String) = inline s match
     |   case "1.0" => ()
     |   case _ => compiletime.error("Only version 1.0 is allowwed")
def check(s: String): Unit
scala> check("")
-- Error: ----------------------------------------------------------------------
1 |check("")
  |Only version 1.0 is allowwed
1 error found
scala> check("1.0")
scala> val version = "1.0"
val version: String = 1.0
scala> check(version)
-- Error: ----------------------------------------------------------------------
1 |check(version)
  |Only version 1.0 is allowwed
1 error found
scala> inline val version = "1.0"
scala> check(version)

Yes, that is possible. But that would not help me.
I wanted to have a particular format for the version numbers (e.g.: “v0.2”, “v1.2” etc).

No in-depth experience with inline defs here, either, but according to the docs, the condition of an inline if expression must be a constant expression - i.e. a constant expression according to the lang spec (basically just literals) or some platform specific extension “such as constant folding of pure numeric computations”, making for a pretty limited and fuzzy space of supported expressions (for now?).

Thanks for the reply.
So, I guess that I can’t use this in my scenario then. Sad!
I thought that it was a nice usecase for applying this compiletime.error logic :frowning:

They have a compiletime op for that.

import scala.compiletime.*, ops.string.*
import InlineCompilerError.*

object InlineCompilerError {
  inline def checkVersion(inline versionNo: String) =
    if constValue[Matches[versionNo.type, "\\d\\.\\d"]] then
      println(s"Correct version information")
      error("Wrong version numbering! ")
//@main def compilerErrorMain = checkVersion("1.2")
@main def compilerErrorMain = checkVersion("1.x")

@som-snytt This is amazing! Thank you very much for sharing this, this helps me a lot :smile:

I don’t understand. This is still not an inline if, yet the error is no longer emitted. Is this if else automatically constant folded or something? Which begs the question: what then is the point of inline if?

inline if just guarantees that the expression is constant at compile time. If not it throws an appropriate error message. You can think in the lines of @tailrec annotation.
The above code compile because we are using the Matches from scala.compiletime.ops package. The operators in that package will be compile-time constants (and if you look at that package, you can notice that there are not many operations available yet).

I don’t think I knew it would expand the link inline (to pun on inlining):

-Vprint:typer,inlining,inlineVals shows that an ordinary if/else with a final val condition is pruned at inlineVals.

In Scala 2, that is in refchecks (!):

For line 37, see the magic number.

the error is no longer emitted

It wasn’t clear to me which error was meant, but I hope the previous answer was clarifying.