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

Diverging implicit with 1-class-recursive-discriminated-union #30

Closed
lihaoyi opened this issue Sep 28, 2014 · 9 comments
Closed

Diverging implicit with 1-class-recursive-discriminated-union #30

lihaoyi opened this issue Sep 28, 2014 · 9 comments

Comments

@lihaoyi
Copy link
Member

lihaoyi commented Sep 28, 2014

This causes uPickle to fail with a diverging implicit expansion error:

sealed trait SingleTree
case class SingleNode(value: Int, children: List[SingleTree]) extends SingleTree

write(
  SingleNode(123, List(SingleNode(456, Nil), SingleNode(789, Nil)))
)(Writer.macroW)

It really shouldn't, but I haven't managed to figure out why. Oddly enough, adding a : SingleTree type annotation or removing the children: List[SingleTree] from SingleNode is sufficient to make the problem go away.

@lihaoyi
Copy link
Member Author

lihaoyi commented Sep 28, 2014

This happens in both 2.10.4 and 2.11.2

@tindzk
Copy link
Contributor

tindzk commented Jan 15, 2015

scalac also fails to evaluate the SeqishR implicit for the following code:

sealed trait Inline
case class Emph(content: Seq[Inline]) extends Inline

sealed trait Block
case class Plain(content: Seq[Inline]) extends Block

upickle.read[Block]("")

I used -Xlog-implicits and received:

SeqishR is not a valid implicit value for upickle.Reader[Block] because:
hasMatchingSymbol reported error: polymorphic expression cannot be instantiated to expected type;
 found   : [T, V[_]]upickle.Aliases.R[V[T]]
    (which expands to)  [T, V[_]]upickle.Reader[V[T]]
 required: upickle.Reader[Block]
    println(read[Block](""))
                       ^

diverging implicit expansion for type upickle.Reader[Seq[Inline]]
starting with method SeqishR in trait Implicits
    println(read[Block](""))
                       ^

It is probably related to this bug. Note that replacing Seq[Inline] with Seq[String] in Plain makes the error vanish.

I am confused by the type the expression requires. Shouldn't it be upickle.Reader[Seq[Inline]] instead of upickle.Reader[Block]?

@lihaoyi
Copy link
Member Author

lihaoyi commented Mar 9, 2015

Reported by @MasseGuillaume

case class Bucket(name: String, objects: Seq[S3Node])
sealed trait S3Node
case class S3Folder(path: String, nodes: Seq[S3Node]) extends S3Node
case class S3File(path: String) extends S3Node
import upickle._
write(Bucket("a", Seq(S3Folder("b", Seq(S3File("c"))))))
java.lang.AssertionError: assertion failed
        at scala.Predef$.assert(Predef.scala:151)
        at upickle.Macros$.macroWImpl(Macros.scala:49)
              write(Bucket("a", Seq(S3Folder("b", Seq(S3File("c"))))))

@MasseGuillaume
Copy link
Contributor

default parameters are also not working

sealed trait Node
case class Branch(value: String, nodes: Seq[Node] = Seq()) extends Node
case class Leaf(value: String) extends Node

@lihaoyi
Copy link
Member Author

lihaoyi commented Jul 4, 2015

The original case is fixed in cached-macros, @tindzk's case is still borked. Trying to figure out why

@lihaoyi
Copy link
Member Author

lihaoyi commented Jul 5, 2015

Here's a minimal repro of AFAIK what everyone is facing. These fails:

// Doesn't work :(
case class A_(objects: Option[C_]); case class C_(nodes: Option[C_])
case class A_(objects: Seq[C_]); case class C_(nodes: Seq[C_])
case class A_(objects: List[C_]); case class C_(nodes: List[C_])
implicitly[Reader[A_]]

While these work

case class A_(objects: Option[C_]); case class C_(nodes: Seq[C_])
case class A_(objects: List[C_]); case class C_(nodes: Seq[C_])
case class A_(objects: List[C_]); case class C_(nodes: Option[C_])
implicitly[Reader[A_]]

I haven't figured out why, but my $$$ is a bug in scalac's diverging implicit expansion checker which kicks in and kills the implicit search when it tries to cross two different implicits with the same type. This is normally a problem but should be OK in this case because the types in scope for the two implicits are different, so they should give different results.

If anyone wants to help dive into this I'd be grateful

@lihaoyi lihaoyi closed this as completed Jul 5, 2015
@lihaoyi lihaoyi reopened this Jul 5, 2015
@lihaoyi
Copy link
Member Author

lihaoyi commented Nov 2, 2015

Here's a more minimum repro

case class C(nodes: Option[C])
object Main{
  implicitly[upickle.default.Writer[Option[C]]]
}

@ellbur
Copy link

ellbur commented Feb 3, 2016

Another example:

import upickle.default._

object ImplicitJSONTest extends App {
  case class A(x: Seq[(Int, Int)])
  case class B(y: Seq[A])

  write[B](???)
}

@lihaoyi
Copy link
Member Author

lihaoyi commented Dec 19, 2017

Moot with 0.5.1

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

No branches or pull requests

4 participants