2

It appears that passing an alias to a wild-carded parameterized type to a function that tries to get an implicit Manifest for the type will crash the Scala 2.11.5 compiler.

The following can be pasted in the 2.11.5 REPL to reproduce the crash:

class C[T]
def f[T](implicit m: Manifest[T]) = 0

type CAlias = C[_]
val x = f[CAlias]

The crash output is very verbose, but contains this info:

scala.reflect.internal.FatalError:
  ?MethodType?
     while compiling: <console>
        during phase: globalPhase=erasure, enteringPhase=posterasure
     library version: version 2.11.5
    compiler version: version 2.11.5
  reconstructed args:

  last tree to typer: type $iw
       tree position: line 9 of <console>
            tree tpe: <notype>
              symbol: object $iw
   symbol definition: class $iw extends Object (a ModuleClassSymbol)
      symbol package: $line10
       symbol owners: object $iw -> object $iw -> object $read
           call site: object $iw in package $line10

There are several conditions for this crash. The type C must be parameterized. The alias must use a wildcard (C[_]). The call must use a type alias, just calling f[C[_]] works fine.

In my program the case is far more complex, and the only solution I've found is to have the method not accept a Manifest, but just take a Class parameter instead, which is ugly.

Am I doing something wrong? Any suggestions for better workaround? I didn't see a bug in the Scala bug tracker, so if this seems legit, I'll go ahead and report it.

Yona Appletree
  • 8,801
  • 6
  • 35
  • 52

1 Answers1

2

Use scala.reflect.runtime.universe.TypeTag (or scala.reflect.ClassTag if it's sufficient; since you mention taking Class as an option, it may be) instead of Manifest. They are inserted as implicit arguments by the compiler in the same way as Manifests are. See http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html for more. In particular, note

In Scala 2.10, scala.reflect.ClassManifests are deprecated, and it is planned to deprecate scala.reflect.Manifest in favor of TypeTags and ClassTags in an upcoming point release.

You probably should still report the bug; even if it's marked as wont-fix, it'll help people who stumble over this in the future.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Awesome, that basically does do what I want. It's interesting that the TypeTag actually gets information about the alias. To get the class, I have to call .erasure on it, but that's fine. Thanks! – Yona Appletree Feb 16 '15 at 21:03
  • Oops... I think I spoke too soon. I need java reflection objects (like java.lang.Class or java.lang.reflect.Type). I'm having trouble figuring out how to get those from the scala Types. – Yona Appletree Feb 17 '15 at 19:06
  • You can use `typeTag.mirror.runtimeClass(typeTag.tpe)` to get a `Class`. I don't know about `java.lang.reflect.Type`; you may want to ask a separate question. – Alexey Romanov Feb 18 '15 at 10:02
  • Thanks, I've reaccepted this and it ended up working. I also asked another question about getting Types, though it seems like not be possible at the moment. – Yona Appletree Feb 18 '15 at 21:12
  • Also, if just getting the `Class` is good enough, you can use `ClassTag` and `classTag.runtimeClass`. – Alexey Romanov Feb 18 '15 at 21:26