Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
scabug opened this issue Aug 19, 2012 · 7 comments
Closed
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Aug 19, 2012

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
@scabug
Copy link
Author

scabug commented Aug 19, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6259?orig=1
Reporter: ruslan shevchenko (rssh)
Affected Versions: 2.10.0-M6
See #6666
Attachments:

@scabug
Copy link
Author

scabug commented Sep 5, 2012

@xeno-by said:
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

@scabug
Copy link
Author

scabug commented Sep 12, 2012

@jsuereth said:
scala/scala#1292

A workaround for now.

@scabug
Copy link
Author

scabug commented Jan 23, 2013

@retronym said:
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 #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].

@scabug
Copy link
Author

scabug commented Jan 23, 2013

@retronym said:
Relates to #6666.

@scabug
Copy link
Author

scabug commented Feb 8, 2013

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

@scabug
Copy link
Author

scabug commented Dec 10, 2013

@adriaanm said:
seems fixed in master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants