Specific compile-time tuples types

I’m trying to write a function that returns tuples of different sizes, e.g.:

transparent inline def tup(inline n: Int): Tuple =
   inline if n == 0 then EmptyTuple else 0 *: tup(n - 1)

I was hoping transparent inline would magically take care of things, but it didn’t. tup(2) has type Int *: Tuple, not (Int, Int).

Is what I want possible? Tuples methods like tail or take do produce specific types, but they have a tuple type to start from and I don’t. I tried to parameterize my function by a tuple type, but I can’t get it to work. I feel that there should be a way to produce the type Tuplen if n is known at compile time.

Seems that transparent does not work recursively:

I can get it to work with a match type, but still requires a cast for some reason.

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

type Result[N <: Int] <: Tuple = N match
  case 0 => EmptyTuple.type
  case _ => Int *: Result[N - 1]

def tup(n: Int): Result[n.type] =
  n match
    case _: 0 => EmptyTuple
    case _ => 0 *: tup(n - 1).asInstanceOf[Result[n.type - 1]]

val result: (Int, Int, Int) = tup(3)

Also doesn’t work with inline.

This seems to work:

inline def tup(inline n: Int): Result[n.type] =
   inline n match
      case _: 0 => EmptyTuple
      case _ => 0 *: tup(n - 1).asInstanceOf[Result[n.type - 1]]

inline val n = 3
val result: (Int, Int, Int) = tup(n)

Hmm I got weird type errors with inline, but I maybe the cast was in a different place when I tried that.