A question about how implicits work

718 views
Skip to first unread message

Eugene Burmako

unread,
Mar 22, 2013, 7:33:28 PM3/22/13
to scala-internals
What does this print and why?

trait Fooable[T]
object Fooable {
implicit def conjure[T]: Fooable[T] = {
println("conjure")
new Fooable[T]{}
}
}

object Main extends App {
implicit def traversable[T, Coll[_] <: Traversable[_]](implicit
elem: Fooable[T]): Fooable[Coll[T]] = {
println("traversable")
new Fooable[Coll[T]]{}
}
implicitly[Fooable[List[Any]]]
}

Paul Phillips

unread,
Mar 22, 2013, 7:39:57 PM3/22/13
to scala-i...@googlegroups.com

On Fri, Mar 22, 2013 at 4:33 PM, Eugene Burmako <eugene....@epfl.ch> wrote:
What does this print and why?

It looks like the usual debacle with Any/Nothing confusing implicit search.

Eugene Burmako

unread,
Mar 22, 2013, 7:46:47 PM3/22/13
to <scala-internals@googlegroups.com>
Yes, it works properly for Fooable[Int]. Thank you for restoring my sanity. Now I only have to understand why this happens...


--
You received this message because you are subscribed to the Google Groups "scala-internals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-interna...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Eugene Burmako

unread,
Mar 22, 2013, 8:48:34 PM3/22/13
to scala-internals, Paul Phillips
This is what I traced this down to:

exprTypeArgs: tparams = List(type T, type Coll), tvars = List(?T, ?
Coll), (implicit elemPickler:
scala.pickling.Pickler[T])scala.pickling.Pickler[Coll[T]] = restpe,
instResTp = (implicit elemPickler: scala.pickling.Pickler[?
T])scala.pickling.Pickler[?Coll], pt = scala.pickling.Pickler[XXX],
useWeaklyCompatible=true
isWeaklyCompatible: tp1 = scala.pickling.Pickler[?Coll], pt =
scala.pickling.Pickler[XXX]

When XXX is Any, isWeaklyCompatible returns true. This triggers a
successful solveTypes, which returns back to typedImplicit1,
triggering a recursive implicit search, which diverges, crashes
bestImplicit with DivergentImplicit, which causes implicit search to
skip searching in the companion.

But if XXX is anything other than Any (I tried Int and AnyRef), the
result of isWeaklyCompatible is false, type inference fails and the
problematic implicit search is never started. bestImplicit doesn't
crash, but rather returns SearchFailure, then control flow reaches
companion implicit searches, which finds conjure.

Two questions:
1) What's the magic role of Any here? Why is it under Any that type
inference succeeds?
2) How come a divergent implicit error can prevent companion implicits
from being looked into?

Sunita Kar

unread,
Jul 29, 2013, 2:18:19 AM7/29/13
to scala-i...@googlegroups.com
I am new to Scala Pickling and facing compile time error while using it. I am trying a basic code which is:

val ff = new Testpickling("Jim", 2005)

val pickl = ff.pickle

The error is :
[error] D:\workspace\scalaapp\test\app\controllers\Application.scala:21: could n
ot find implicit value for parameter e: scala.pickling.FastTypeTag[Null]

[error] val pickl = ff.pickle
[error] (compile:compile) Compilation failed
Any idea/pointers why this is happening?TIA.

Eugene Burmako

unread,
Jul 29, 2013, 2:27:33 AM7/29/13
to <scala-internals@googlegroups.com>
Thanks for the report, I'm looking into it.


--

Eugene Burmako

unread,
Jul 29, 2013, 2:45:55 AM7/29/13
to scala-i...@googlegroups.com
Should now work fine. Could you please do "sbt update" and verify?

Sunita Kar

unread,
Jul 31, 2013, 5:49:30 AM7/31/13
to scala-i...@googlegroups.com
Hi,
I did sbt update but i am still getting the same error which is posted below.

- could not find implicit value for parameter e: scala.pickling.FastTypeTag[test.Testpickling]
- not enough arguments for method implicitly: (implicit e: 
scala.pickling.SPickler[test.Testpickling])scala.pickling.SPickler[test.Testpickling]. Unspecified value parameter e.
- Cannot generate a pickler for test.Testpickling. Recompile with -Xlog-implicits for details
- could not find implicit value for parameter e: scala.pickling.FastTypeTag[Null]

I am using Play Framework 2.1 and Scala 2.10. Is it due to version mismatch?

Philipp Haller

unread,
Aug 1, 2013, 1:26:21 PM8/1/13
to scala-i...@googlegroups.com
Unfortunately, I can't reproduce your error.

I'm using a clean build of the "2.10.x" branch of scala/pickling, using stock Scala 2.10.2:

~/tools/scala-2.10.2/bin/scala -cp core/target/scala-2.10/scala-pickling_2.10-0.8.0-SNAPSHOT.jar 
Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_07).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.pickling._
import scala.pickling._

scala> import json._
import json._

scala> case class Testpickling(s: String, i: Int)
defined class Testpickling

scala> val ff = Testpickling("Jim", 2005)
ff: Testpickling = Testpickling(Jim,2005)

scala> val pickl = ff.pickle
pickl: scala.pickling.json.JSONPickle = 
JSONPickle({
  "tpe": "Testpickling",
  "s": "Jim",
  "i": 2005
})


--

Paul Phillips

unread,
Aug 1, 2013, 3:30:58 PM8/1/13
to scala-i...@googlegroups.com
On Thu, Aug 1, 2013 at 10:26 AM, Philipp Haller <hal...@gmail.com> wrote:
Unfortunately, I can't reproduce your error.
 
I couldn't either, but based on the very, very few clues in his message, I came up with the appended, which could be relevant. The more interesting possibility is initialization order - two eager vals plus an error message involving Null usually means that - but I couldn't reproduce anything that way.

Parenthetically, the easy way to get his exact error message is to just not import anything:

scala> implicitly[scala.pickling.FastTypeTag[Null]]
<console>:8: error: could not find implicit value for parameter e: scala.pickling.FastTypeTag[Null]
              implicitly[scala.pickling.FastTypeTag[Null]]
                        ^

That's not a very likely explanation since the implicit conversion allow for calling "pickle" must be taking place.

But this doesn't compile, which must be a bug:

import scala.pickling._
import json._

case class Jimbo[T](x: T)

object Runner {
  val jim = Jimbo(null)
  def main(args: Array[String]): Unit = jim.pickle
}

Because:

[error] /Users/paulp/scratch/2013-08-01/F3B4B08D/src/main/scala/a.scala:10: Cannot generate a pickler for s.Jimbo[Null]. Recompile with -Xlog-implicits for details
[error]   def main(args: Array[String]): Unit = jim.pickle
[error]                                             ^
[error] one error found

The relevant lines of that overly verbose output are:

[info] /Users/paulp/scratch/2013-08-01/F3B4B08D/src/main/scala/a.scala:10: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[s.Jimbo[Null]] because:
[info] stepping aside: repeating itself
[info]   def main(args: Array[String]): Unit = jim.pickle
[info]                                             ^
[info] /Users/paulp/scratch/2013-08-01/F3B4B08D/src/main/scala/a.scala:10: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[s.Jimbo[Null]] because:
[info] hasMatchingSymbol reported error: value pickleInto is not a member of Null
[info]   def main(args: Array[String]): Unit = jim.pickle
[info]                                             ^


Here's the build.sbt I used.

scalaVersion := "2.10.2"

resolvers += Opts.resolver.sonatypeSnapshots

scalacOptions += "-Xlog-implicits"

libraryDependencies += "org.scala-lang" %% "scala-pickling" % "0.8.0-SNAPSHOT"

Paul Phillips

unread,
Aug 1, 2013, 3:32:53 PM8/1/13
to scala-i...@googlegroups.com
While I'm looking at it, I broke it some other ways too. (Maybe they are expected, I haven't read any docs - but if they're expected this is not the ideal way to fail.) Here's one.

package s

import scala.pickling._
import json._

object Test {
  def main(args: Array[String]): Unit = {
    println("Fine")
    List(1).pickle

    println("Not fine")
    (List(1): Iterable[Int]).pickle
  }
}

[info] Running s.Test 
Fine
Not fine
[error] (run-main) scala.ScalaReflectionException: Scala field hd  isn't represented as a Java field, neither it has a Java accessor method
[error] note that private parameters of class constructors don't get mapped onto fields and/or accessors,
[error] unless they are used outside of their declaring constructors.
scala.ScalaReflectionException: Scala field hd  isn't represented as a Java field, neither it has a Java accessor method
note that private parameters of class constructors don't get mapped onto fields and/or accessors,
unless they are used outside of their declaring constructors.
at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$ErrorNonExistentField(JavaMirrors.scala:132)
at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:256)
at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:243)
at scala.pickling.InterpretedPicklerRuntime$$anon$1.pickle(Runtime.scala:63)
at s.Test$.main(a.scala:15)

Paul Phillips

unread,
Aug 1, 2013, 4:22:09 PM8/1/13
to scala-i...@googlegroups.com
Wow, "List(1).pickle" is 232 lines after typer. Part of it includes the line I said would induce that error, which I see is always in there.

  builder.hintTag(scala.this.Predef.implicitly[scala.pickling.FastTypeTag[Null]]({

Seems like there is an awful lot of work being done on behalf of Null. This program generates ten classfiles instead of the naively expected one:

import scala.pickling._
import json._

class Bippy {
  val x1 = "abc".pickle
  val x2 = "def".pickle
  val x3 = "ghi".pickle
}

Each call to pickle gets one of each of these - its whole own class. I only point this out because I understand efficiency to be a goal of the project, and this isn't. How much call-site-specific behavior is necessary to handle null?

public class Bippy$$anon$1 implements scala.pickling.FastTypeTag<java.lang.String> {
  private scala.reflect.api.Types$TypeApi tpe;
  public final Bippy $outer;
  private volatile boolean bitmap$0;
  private scala.reflect.api.Types$TypeApi tpe$lzycompute();
  public boolean canEqual(java.lang.Object);
  public boolean equals(java.lang.Object);
  public int hashCode();
  public java.lang.String toString();
  public scala.reflect.api.JavaMirrors$JavaMirror mirror();
  public scala.reflect.api.Types$TypeApi tpe();
  public java.lang.String key();
  public Bippy Bippy$$anon$$$outer();
  public Bippy$$anon$1(Bippy);
}

Compiled from "a.scala"
public class Bippy$$anon$2 implements scala.pickling.FastTypeTag<scala.runtime.Null$> {
  private scala.reflect.api.Types$TypeApi tpe;
  public final Bippy $outer;
  private volatile boolean bitmap$0;
  private scala.reflect.api.Types$TypeApi tpe$lzycompute();
  public boolean canEqual(java.lang.Object);
  public boolean equals(java.lang.Object);
  public int hashCode();
  public java.lang.String toString();
  public scala.reflect.api.JavaMirrors$JavaMirror mirror();
  public scala.reflect.api.Types$TypeApi tpe();
  public java.lang.String key();
  public Bippy Bippy$$anon$$$outer();
  public Bippy$$anon$2(Bippy);
}

Philipp Haller

unread,
Aug 1, 2013, 5:45:26 PM8/1/13
to scala-i...@googlegroups.com
Hey Paul, don't underestimate the complexity of `null`. ;-)

I created a ticket:

Sunita Kar

unread,
Aug 2, 2013, 9:01:00 AM8/2/13
to scala-i...@googlegroups.com
Hey Paul and Philipp,
Really appreciate your replies :) But again I am not able to fix the issue. By looking at your replies, it seems I am missing out on a very small thing. Below is the list of what I am using. Please tell me where I am wrong.

1. Play Framework : 2.1.0
2. Scala : 2.10.1
3. Build.scala with configuration: 
val appDependencies = Seq(
    // Add your project dependencies here,
    jdbc,
    anorm,
    "org.scala-lang" %% "scala-pickling" % "0.8.0-SNAPSHOT" )
val main = play.Project(appName, appVersion, appDependencies).settings(
    // Add your own project settings here      
      resolvers+="picklingArtifactory" at "https://oss.sonatype.org/content/repositories/snapshots/)

4. Code in scala class:
import scala.pickling._
import json._
case class Testpickling(str:String, int: Integer)

class testPickling {
  implicit val pickleFormat: JSONPickleFormat = new JSONPickleFormat
 val ff = new Testpickling("Jim", 2005)
val pickl = ff.pickle
}

5. Error in console:
sbt.PlayExceptions$CompilationException: Compilation error[could not find implic
it value for parameter e: scala.pickling.FastTypeTag[Null]]
        at sbt.PlayReloader$$anon$2$$anonfun$reload$2$$anonfun$apply$15$$anonfun
$apply$16.apply(PlayReloader.scala:349) ~[na:na]
   
As I already said I am new to pickling and not that old in Scala/Play. Please Help!

Eugene Burmako

unread,
Aug 2, 2013, 9:02:28 AM8/2/13
to scala-i...@googlegroups.com
It's Scala version. scala/pickling relies on implicit macros, which are only available in 2.10.2.
Reply all
Reply to author
Forward
0 new messages