Skip to content

Instantly share code, notes, and snippets.

@chris-martin
Created November 16, 2016 21:02
Show Gist options
  • Save chris-martin/35b06c826a874a6a42a418ee2614751a to your computer and use it in GitHub Desktop.
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
@chris-martin
Copy link
Author

Getting closer, although -e doesn't seem to do what I think it does.

scala -cp ~/.ivy2/cache/com.lihaoyi/scalatags_2.11/jars/scalatags_2.11-0.6.0.jar -nocompdaemon -Xprint:typer -e "scalatags.Text.all"
[[syntax trees at end of                     typer]] // scalacmd6163883395223728752.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>();
          ()
        };
        scalatags.Text.all
      };
      {
        new $anon();
        ()
      }
    }
  }
}

@Blaisorblade
Copy link

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.

@Blaisorblade
Copy link

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.

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