I have been experimenting again with tuples and tried to select an item from a tuple indexed by a string. If the index does not exist, this should fail at compile time. I am assuming tuples of arbitrary length (possibly > 22). Here is an example of such a tuple:
(("a",1), ("b",2))
So if I select by “a”, I should get a 1. I have come up with the function bellow that seems to compile, however its application fails irrespective of whether or not the key exists. The error is:
Cannot reduce `inline if` because its condition is not a constant value:
Here is the code:
import scala.compiletime.*
inline def find5[ID <: String, Labels <: Tuple](id: ID, labels: Labels)(using Tuple.Union[Labels] <:< Tuple2[String,Int]): Int =
inline erasedValue[Labels] match {
case _: EmptyTuple =>
error("No ID found 5")
case _: ((head,idx) *: tail) =>
val v = erasedValue[head]
inline if v == erasedValue[ID]
then
constValue[idx].asInstanceOf[Int]
else
val vtail = labels.drop(1).asInstanceOf[tail]
find5[ID, tail](id, vtail)(using summonInline[Tuple.Union[tail] <:< Tuple2[String,Int]])
}
// error: Cannot reduce `inline if` because its condition is not a constant value: v.==(scala.compiletime.erasedValue[String])
val rf9 = find5("a", (("a",1), ("b",2)))
println(rf9)
Here is the working code:
Is what I am attempting impossible? Will I have to resort to recursive type matching via implicits as discussed here?
scala> inline def test[A] = { val a = erasedValue[A] }
def test[A]: Unit
scala> test[Int]
-- Error: ----------------------------------------------------------------------
1 |test[Int]
|^^^^^^^^^
|method erasedValue is declared as `erased`, but is in fact used
I believe this has something to do with type inference.
Assume I have a class A and B extends A. If I have a method func[T<: A](a:<T) and I call func(b:B), I expect the type T to be bound to the most specific type B. In other words:
func(b:B) =:= func[B](b:B)
This does not seem to happen. In the link below, I show how if I add all value types, the code works.
EDIT:
I think this typing issue is somehow connected to the Tuple class. In the link below I have added a simple check on the func(b:B) =:= func[B](b:B), which seems to work: