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.
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()
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)
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
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?
@Jasper-M 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).
With Scala 3.3.0, this breaks. versionNo.type is not compiling at the moment. I am trying to find why, but still not fixed it.
It says the value is not a singleton type.