Scala TypeTag Behavior with Nested Types

I have the following code snippet:

import scala.reflect.runtime.universe._

def paramInfo[N: TypeTag](x: N): Unit = {
  val targs = typeOf[N] match { case TypeRef(_, _, args) => args }
  println(s"type of $x has type arguments $targs")
}

case class Dummy(l: List[Int])

import scala.reflect.runtime.universe._
paramInfo: [N](x: N)(implicit evidence$1: reflect.runtime.universe.TypeTag[N])Unit
defined class Dummy

// Exiting paste mode, now interpreting.

scala> paramInfo(List(1,2))
type of List(1, 2) has type arguments List(Int)

scala> paramInfo(Dummy(List(1,2)))
type of Dummy(List(1, 2)) has type arguments List()

What I do not understand is that I was expecting the call paramInfo(Dummy(List(1,2))) to actually print:

type of Dummy(List(1, 2)) has type arguments List(Dummy(List(Int)))

Did I get it wrong? Any reason?

Type arguments are what you pass to a type constructor. So in List[Int] the type argument is Int. In Set[String] the type argument is String. In Map[Long, Double] the type arguments are Long and Double. Dummy is not a type constructor like List, Set or Map but a fully constructed type, so there are no type arguments.

It’s analogous to value constructors, or in normal words: functions. In foo(42, "bar") the value arguments are 42 and "bar".

1 Like