-
-
Save chris-martin/35b06c826a874a6a42a418ee2614751a to your computer and use it in GitHub Desktop.
> scala ~/.ivy2/cache/com.lihaoyi/scalatags_2.11/jars/scalatags_2.11-0.6.0.jar -Xprint:typer -e "scalatags.Text.all" | |
java.lang.NullPointerException | |
at java.lang.Class.forName0(Native Method) | |
at java.lang.Class.forName(Class.java:348) | |
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$tryClass$1.apply(ScalaClassLoader.scala:43) | |
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$tryClass$1.apply(ScalaClassLoader.scala:43) | |
at scala.util.control.Exception$Catch$$anonfun$opt$1.apply(Exception.scala:119) | |
at scala.util.control.Exception$Catch$$anonfun$opt$1.apply(Exception.scala:119) | |
at scala.util.control.Exception$Catch.apply(Exception.scala:103) | |
at scala.util.control.Exception$Catch.opt(Exception.scala:119) | |
at scala.reflect.internal.util.ScalaClassLoader$class.tryClass(ScalaClassLoader.scala:42) | |
at scala.reflect.internal.util.ScalaClassLoader$class.tryToInitializeClass(ScalaClassLoader.scala:39) | |
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.tryToInitializeClass(ScalaClassLoader.scala:101) | |
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:63) | |
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101) | |
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22) | |
at scala.tools.nsc.JarRunner$.run(MainGenericRunner.scala:13) | |
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29) | |
at scala.tools.nsc.JarRunner$.runJar(MainGenericRunner.scala:25) | |
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:69) | |
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87) | |
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98) | |
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103) | |
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) | |
> scala -Xprint:typer -e "()" | |
Exception in thread "main" java.net.UnknownHostException: renzo: renzo: Name or service not known | |
at java.net.InetAddress.getLocalHost(InetAddress.java:1505) | |
at scala.tools.nsc.io.Socket$.localhost(Socket.scala:28) | |
at scala.tools.nsc.CompileSocket.getsock$1(CompileSocket.scala:175) | |
at scala.tools.nsc.CompileSocket.getOrCreateSocket(CompileSocket.scala:190) | |
at scala.tools.nsc.ScriptRunner.compileWithDaemon(ScriptRunner.scala:70) | |
at scala.tools.nsc.ScriptRunner.scala$tools$nsc$ScriptRunner$$compile$1(ScriptRunner.scala:113) | |
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply$mcZ$sp(ScriptRunner.scala:161) | |
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:129) | |
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:129) | |
at scala.tools.nsc.util.package$.trackingThreads(package.scala:43) | |
at scala.tools.nsc.util.package$.waitingForThreads(package.scala:27) | |
at scala.tools.nsc.ScriptRunner.withCompiledScript(ScriptRunner.scala:128) | |
at scala.tools.nsc.ScriptRunner.runCommand(ScriptRunner.scala:222) | |
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:85) | |
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98) | |
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103) | |
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) | |
Caused by: java.net.UnknownHostException: renzo: Name or service not known | |
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method) | |
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928) | |
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323) | |
at java.net.InetAddress.getLocalHost(InetAddress.java:1500) | |
... 16 more |
Most of the junk you see is what the Scala REPL adds to convert expressions to Scala compilation units. You're implicitly pointing out no other REPL does that, but that's Scala for you. You can run scala -Xprint:typer
without -e
to see it happen in real time.
But to be sure, there are docs on -Xprint
:
$ scala -X
[...]
-Xprint:<phases> Print out program after <phases>
[...]
And for completeness: typer
is the phase doing typechecking and implicit resolution (they're intertwined), so it also shows the inserted implicits and it's invaluable constantly when figuring out how Scala is mangling your program.
To have a slightly more interesting example:
$ scala -Xprint:typer -e 'implicitly[Int <:< Any]'
[[syntax trees at end of typer]] // scalacmd7742517026832451635.scala
package <empty> {
object Main extends scala.AnyRef {
def <init>(): Main.type = {
Main.super.<init>();
()
};
def main(args: Array[String]): Unit = {
final class $anon extends scala.AnyRef {
def <init>(): <$anon: AnyRef> = {
$anon.super.<init>();
()
};
scala.this.Predef.implicitly[<:<[Int,Any]](scala.this.Predef.$conforms[Int])
};
{
new $anon();
()
}
}
}
}
The only interesting part of that is scala.this.Predef.implicitly[<:<[Int,Any]](scala.this.Predef.$conforms[Int])
, which shows the implicit argument $conforms[Int]
passed to implicitly
.
So what I'd recommend: take your example code using mistery implicits, pass it to -e
or put it in a file or paste it at the REPL, and use -Xprint:typer
to see the inserted implicits. Actually, scalac ... -Xprint:typer Foo.scala
would avoid inserting the REPL junk, so you'd only have the other junk from the typechecker. But I still think that can be rather useful.
The other approach, when it works, it to use an IDE highlighting implicits and use "open implicit", but those are annoying in different ways and you have to use Eclipse/ScalaIDE over IntelliJ for reliable results.
Getting closer, although
-e
doesn't seem to do what I think it does.