Solved: Scala 3: Why do match types fail in this inline method?

I am implementing an HList using inline and a type match fails only for the last element of the list. I cannot figure out why. So here are the basic definitions for the HList:

import scala.compiletime.*
import compiletime.ops.int.*

sealed trait Tup
case object EmpT extends Tup
case class TCons[H, T <: Tup](head: H, tail: T) extends Tup

type +:[A,T<:Tup] = TCons[A, T] 

type EmpT = EmpT.type

extension [A, T <: Tup] (a: A) def +: (t: T): TCons[A, T] =
    TCons(a, t)

Now, I want to implement a get method that returns the element at a given index. If the index is invalid, it should fail at compile time. The following inline function works correctly:

transparent inline def getOk[L <: Tup, N <: Int](l: L, n: N): Any =
  inline l match
    case _: EmpT => 
      error("Element index exceeds length of list.")
    case list : TCons[_,_] =>
      inline if n == 0
      then
        list.head
      else
        inline val next = n-1 
        getOk(list.tail,next)


val t1 = getOk(1 +: 2 +: 3 +: EmpT, 0)
assert(t1 == 1)
val t2 = getOk(1 +: 2 +: 3 +: EmpT, 1)
assert(t2 == 2)
val t3 = getOk(1 +: 2 +: 3 +: EmpT, 2)
assert(t3 == 3)

When looking at the Tuple implementation, I see type matching is used. So I “lifted” the type match and adapted and tested it as follows (just changed the concatenation symbol):

type Elem[X <: Tup, N <: Int] = X match
  case x +: xs =>
    N match
      case 0 => x
      case S[n1] => Elem[xs, n1]


summon[Elem[1 +: 2 +: 3 +: EmpT, 0] =:= 1]
summon[Elem[1 +: 2 +: 3 +: EmpT, 1] =:= 2]
summon[Elem[1 +: 2 +: 3 +: EmpT, 2] =:= 3]

So that works correctly. Invalid indexing will also cause a compilation error, as expected. The next step, was to use the same inline function above and adapt that to the use of the return type match. I used this function:

inline def get[L <: Tup, N <: Int](l: L, n: N): Elem[L, n.type] =
  inline if n < 0
  then
    error("Can only select a positively indexed element")
  inline l match
    case _: EmpT => 
      error("Element index exceeds length of list.")
    case list : TCons[_,_] =>
      inline if n < 0
      then
        error("Unexpected value.")
      else inline if n == 0
      then
        list.head.asInstanceOf[Elem[L, n.type]]
      else
        get(list.tail,n-1).asInstanceOf[Elem[L, n.type]]


val t1b = get(1 +: 2 +: 3 +: EmpT, 0)
assert(t1b == 1)
val t2b = get(1 +: 2 +: 3 +: EmpT, 1)
assert(t2b == 2)
val t3b = get(1 +: 2 +: 3 +: EmpT, 2)
assert(t3b == 3)

But the last call to get fails with:

    Match type reduction failed since selector  _
    matches none of the cases

        case Playground.TCons[x, xs] => (-1 : Int) match {
      case (0 : Int) => x
      case compiletime.ops.int.S[n1] => Playground.Elem[xs, n1]
    }

Th error always occurs for the last element of the list. I have tried several variations, but with no success. For example, in the version above I explicitly test for n < 0, but that does not seem to work.

I have been trying to figure out how the type matching ends up with a n.type < 0 but have failed. Can anyone tell me what is the issue here?

Full code can be found here:

TIA

Thanks to @WojciechMazur, issue is solved (see #16493). I quote:

The implementation of match type is not exhaustive, it cannot be matched with empty tuple.
With this modification it would compile

type Elem[X <: Tup, N <: Int] = X match
 case x +: xs =>
   N match
     case 0 => x
     case S[n1] => Elem[xs, n1]
 case EmpT => Nothing

Indeed it does.