Scala Macros: “cannot create TypeTag from a type T having unresolved type parameters”

前端 未结 1 1494
悲&欢浪女
悲&欢浪女 2021-02-15 04:59

I\'m playing around with Scalas new macros and found this gist from akshaal. As it seams I did not quite get it. Given the following trait (the fieldsMacro is more or less the

1条回答
  •  暗喜
    暗喜 (楼主)
    2021-02-15 05:28

    T: TypeTag context bound for a type parameter T means that you require type arguments provided in place of this parameter to be concrete (i.e. not contain references to untagged type parameters or abstract type members). Otherwise an error occurs.

    Examples:

    scala> val ru = scala.reflect.runtime.universe
    ru @ 6d657803: scala.reflect.api.JavaUniverse = scala.reflect.runtime.JavaUniverse@6d657803
    
    scala> def foo[T: ru.TypeTag] = implicitly[ru.TypeTag[T]]
    foo: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]
    
    scala> foo[Int]
    res0 @ 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int]
    
    scala> foo[List[Int]]
    res1 @ 7d53ccbe: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]]
    
    scala> def bar[T] = foo[T] // T is not a concrete type here, hence the error
    :26: error: No TypeTag available for T
           def bar[T] = foo[T]
                           ^
    
    scala> def bar[T] = foo[List[T]] // T being not concrete renders 
                                     // the entire compound type not concrete
    :26: error: No TypeTag available for List[T]
           def bar[T] = foo[List[T]]
                           ^
    
    scala> def bar[T: TypeTag] = foo[T] // to the contrast T is concrete here
                                        // because it's bound by a concrete tag bound
    bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]
    
    scala> bar[Int]
    res2 @ 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int]
    
    scala> def bar[T: TypeTag] = foo[List[T]]
    bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[List[T]]
    
    scala> bar[Int]
    res3 @ 1a108c98: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]]
    
    scala> bar[List[Int]]
    res4 @ 76d5989c: reflect.runtime.universe.TypeTag[List[List[Int]]] = TypeTag[scala.List[scala.List[Int]]]
    

    Having a notion of concrete types to be enforcible at compile-time is useful. Having concrete type tags on by default is useful as well as described in https://issues.scala-lang.org/browse/SI-5884.

    However as you've seen yourself, concrete type tags in macros can be a source of confusion, because typically macros should work both for concrete and non-concrete types. Therefore one should always use c.AbsTypeTag instead. Due to this reason we no longer allow c.TypeTag context bounds in 2.10.0-M7: https://github.com/scala/scala/commit/788478d3ab.

    Edit. In 2.10.0-RC1 some AbsTypeTag has been renamed to WeakTypeTag. Everything else about type tags remains the same.

    0 讨论(0)
提交回复
热议问题