Scala Programming Language
  1. Scala Programming Language
  2. SI-6259

No TypeTag available for String (in object, derived from parametrized class)

    Details

      Description

      try to compile next text:

      package stringtag
      
      import scala.reflect.runtime.universe._
      
      abstract class PrimitiveTC[X:TypeTag] {
         def is[T:TypeTag]: Boolean = typeOf[X] <:< typeOf[T]
      }
      
      object StringTypeTag extends PrimitiveTC[String]
      

      receive:
      No TypeTag available for String

      materializing requested reflect.runtime.universe.type.TypeTag[String] using `package`.this.materializeTypeTag[String](scala.reflect.runtime.`package`.universe)
      reifying = String
      universe = scala.reflect.runtime.`package`.universe
      mirror = <empty>
      Locatable: type String (type) owned by object Predef (module class) at scala.Predef
      =============================
      // produced from source-C:\Projects\Kepler\sandbox\Test.scala,line-7,offset=160
      object Test extends App {
        val $u: scala.reflect.runtime.`package`.universe.type = scala.reflect.runtime.`package`.universe;
        val $m: $u.Mirror = scala.reflect.runtime.`package`.universe.runtimeMirror(this.getClass.getClassLoader);
        import $u._, $m._
        val tpe = TypeRef(SingleType(ThisType(staticPackage("scala").asModule.moduleClass), staticModule("scala.Predef")), build.selectType(staticModule("scala.Predef").asModule.moduleClass, "String"), List())
        println(tpe)
      }
      =============================
      Test.scala:7: cannot materialize TypeTag[String] as {
        val $u: reflect.runtime.universe.type = scala.reflect.runtime.`package`.universe;
        val $m: $u.Mirror = scala.reflect.runtime.`package`.universe.runtimeMirror(this.getClass.getClassLoader);
        $u.TypeTag.apply[String]($m, {
          final class $typecreator1 extends TypeCreator {
            def <init>(): $typecreator1 = {
              $typecreator1.super.<init>();
              ()
            };
            def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: MirrorOf[U]): U#Type = {
              val $u: U = $m$untyped.universe;
              val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
              $u.TypeRef($u.SingleType($u.ThisType($m.staticPackage("scala").asModule.moduleClass), $m.staticModule("scala.Predef")), $u.build.selectType($m.staticModule("scala.Predef").asModule.moduleClass, "String"), scala.collection.immutab
      le.List.apply())
            }
          };
          new $typecreator1()
        })
      } because:
      scala.reflect.internal.Types$TypeError: this can be used only in a class, object, or template
      object StringTypeTag extends PrimitiveTC[String]
                           ^
      Test.scala:7: `package`.this.materializeTypeTag[String](scala.reflect.runtime.`package`.universe) is not a valid implicit value for reflect.runtime.universe.TypeTag[String] because:
      failed to typecheck the materialized tag:
      No TypeTag available for String
      object StringTypeTag extends PrimitiveTC[String]
                           ^
      Test.scala:7: error: No TypeTag available for String
      object StringTypeTag extends PrimitiveTC[String]
                           ^
      one error found
      
      1. StringTag.scala
        0.2 kB
        ruslan shevchenko

        Issue Links

          Activity

          Hide
          Eugene Burmako added a comment -

          When creating a type tag for universe of type JavaUniverse (usually, a singleton value scala.reflect.runtime.universe), the reifier tries to play smart and automatically instantiate it in a correct mirror (ru.runtimeMirror(this.getClass.getClassLoader) instead of ru.rootMirror) [1].

          To do that, it calls reifyEnclosingRuntimeClass for the current typer [2], which checks whether emitting `this.getClass` in current context makes sense. It seems this logic gets screwed up here as the type error says: "scala.reflect.internal.Types$TypeError: this can be used only in a class, object, or template".

          [1] https://github.com/scalamacros/kepler/blob/5415272018114bb2e15036c5d6f9ae9c5af625d2/src/compiler/scala/reflect/reify/package.scala#L26
          [2] https://github.com/scalamacros/kepler/blob/5415272018114bb2e15036c5d6f9ae9c5af625d2/src/compiler/scala/reflect/reify/package.scala#L64

          Show
          Eugene Burmako added a comment - When creating a type tag for universe of type JavaUniverse (usually, a singleton value scala.reflect.runtime.universe), the reifier tries to play smart and automatically instantiate it in a correct mirror (ru.runtimeMirror(this.getClass.getClassLoader) instead of ru.rootMirror) [1] . To do that, it calls reifyEnclosingRuntimeClass for the current typer [2] , which checks whether emitting `this.getClass` in current context makes sense. It seems this logic gets screwed up here as the type error says: "scala.reflect.internal.Types$TypeError: this can be used only in a class, object, or template". [1] https://github.com/scalamacros/kepler/blob/5415272018114bb2e15036c5d6f9ae9c5af625d2/src/compiler/scala/reflect/reify/package.scala#L26 [2] https://github.com/scalamacros/kepler/blob/5415272018114bb2e15036c5d6f9ae9c5af625d2/src/compiler/scala/reflect/reify/package.scala#L64
          Hide
          Josh Suereth added a comment -
          Show
          Josh Suereth added a comment - https://github.com/scala/scala/pull/1292 A workaround for now.
          Hide
          Jason Zaugg added a comment -

          While the workaround compiles, it triggers a VerifyError

           RUNNER=scala scala-hash v2.10.0 -nc 
          [info] v2.10.0 => /Users/jason/usr/scala-v2.10.0-0-g18481ce
          Welcome to Scala version 2.10.0-20121205-112020-18481cef9b (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_27).
          Type in expressions to have them evaluated.
          Type :help for more information.
          
          scala> import scala.reflect.runtime.universe._
          import scala.reflect.runtime.universe._
          
          scala> 
          
          scala> class A[X](implicit val tt: TypeTag[X]) {println(tt)}
          defined class A
          
          scala> 
          
          scala> object Obj {
               |   val x = {
               |     object InVal extends A[String]
               |     InVal
               |     5
               |   }
               | }
          defined module Obj
          
          scala> Obj
          java.lang.VerifyError: (class: Obj$InVal$2$, method: <init> signature: ()V) Expecting to find object/array on stack
          	at Obj$.InVal$1$lzycompute(<console>:13)
          

          With my in-progress patch for SI-6666:

          ticket/6666 ~/code/./build/quick/bin/scalac test/files/run/t6259b.scala
          test/files/run/t6259b.scala:9: error: Implementation restriction: anonymous class $anon requires premature access to object InVal.
              object InVal extends A[String]
                                   ^
          one error found
          ticket/6666 ~/code/scala2 cat !$
          cat test/files/run/t6259b.scala
          package t6259
          
          import scala.reflect.runtime.universe._
          
          class A[X](implicit val tt: TypeTag[X]) {println(tt)}
          
          object Obj {
            val x = {
              object InVal extends A[String]
              InVal
              5
            }
          }
          
          object Test extends App {
            Obj
          }
          ticket/6666 ~/code/scala2 ./build/quick/bin/scalac test/files/run/t6259b.scala
          test/files/run/t6259b.scala:9: error: Implementation restriction: anonymous class $anon requires premature access to object InVal.
              object InVal extends A[String]
                                   ^
          one error found
          

          We could make this problem go away by allowing moduleClassOf[Companion.type].

          Show
          Jason Zaugg added a comment - While the workaround compiles, it triggers a VerifyError RUNNER=scala scala-hash v2.10.0 -nc [info] v2.10.0 => /Users/jason/usr/scala-v2.10.0-0-g18481ce Welcome to Scala version 2.10.0-20121205-112020-18481cef9b (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_27). Type in expressions to have them evaluated. Type :help for more information. scala> import scala.reflect.runtime.universe._ import scala.reflect.runtime.universe._ scala> scala> class A[X](implicit val tt: TypeTag[X]) {println(tt)} defined class A scala> scala> object Obj { | val x = { | object InVal extends A[String] | InVal | 5 | } | } defined module Obj scala> Obj java.lang.VerifyError: (class: Obj$InVal$2$, method: <init> signature: ()V) Expecting to find object/array on stack at Obj$.InVal$1$lzycompute(<console>:13) With my in-progress patch for SI-6666 : ticket/6666 ~/code/./build/quick/bin/scalac test/files/run/t6259b.scala test/files/run/t6259b.scala:9: error: Implementation restriction: anonymous class $anon requires premature access to object InVal. object InVal extends A[String] ^ one error found ticket/6666 ~/code/scala2 cat !$ cat test/files/run/t6259b.scala package t6259 import scala.reflect.runtime.universe._ class A[X](implicit val tt: TypeTag[X]) {println(tt)} object Obj { val x = { object InVal extends A[String] InVal 5 } } object Test extends App { Obj } ticket/6666 ~/code/scala2 ./build/quick/bin/scalac test/files/run/t6259b.scala test/files/run/t6259b.scala:9: error: Implementation restriction: anonymous class $anon requires premature access to object InVal. object InVal extends A[String] ^ one error found We could make this problem go away by allowing moduleClassOf [Companion.type] .
          Hide
          Jason Zaugg added a comment -

          Relates to SI-6666.

          Show
          Jason Zaugg added a comment - Relates to SI-6666 .
          Hide
          Josh Suereth added a comment -

          Yeah, the workaround is wholly unnecessary if you had control to generate moduleClassOf byte code or had such a method.

          Show
          Josh Suereth added a comment - Yeah, the workaround is wholly unnecessary if you had control to generate moduleClassOf byte code or had such a method.
          Hide
          Adriaan Moors added a comment -

          seems fixed in master

          Show
          Adriaan Moors added a comment - seems fixed in master

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              ruslan shevchenko
            • Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development