amnaredo / test

0 stars 0 forks source link

Can't derive a type that involves a hierarchy of traits + scalajs #133

Open amnaredo opened 3 years ago

amnaredo commented 3 years ago

Input

class Field {}

class Abc {
  def p: (Field, Map[String, String]) = (null, null)
}

Output

[error] Couldn't derive type uni.Abc
[error]       read[uni.Abc]("")

ID: 97 Original Author: hrj

amnaredo commented 3 years ago

That shouldn't work afaict, since neither Field nor Abc are case classes neither of them have constructors or apply/unapply-companions that match their constructors. This compiles though


class Field

object Abc{
  implicit def fieldReader: upickle.default.Reader[Abc] =
    upickle.default.Reader {
      case x => new Abc
    }
}
class Abc {
  def p: (Field, Map[String, String]) = (null, null)
}
object Foox{
  upickle.default.read[Abc]("")
}

Perhaps you over-minimized your sample?

Original Author: lihaoyi

amnaredo commented 3 years ago

Oops! Yeah, that was some aggressive midnight minimisation, having just watched "Terminator - Genesis" :wink:

Here is a complete test project.

Strangely, the jvm sub project can be made to work by changing the scala-js version to 0.6.3. Something has changed in the scala-js plugin that trips up upickle / autowire.

Original Author: hrj

amnaredo commented 3 years ago

Can you minimize it more, ideally into a single file, without scala.js at all?

Original Author: lihaoyi

amnaredo commented 3 years ago

I couldn't minimize any further. scala-js seems to be crucial. In fact, if I downgrade scala-js to v0.6.3, it works. It has a problem only with scala-js v0.6.4.

Original Author: hrj

amnaredo commented 3 years ago

I am not sure my example has the same reason, but it shows the same error message:

package hierarchy
import upickle.default._

sealed trait X
case class Y(name: String, next: Option[X] = None) extends X

object Main extends App {
  val p = Y("Test", Some(Y("hello")))
  val s = write(p)
  println(s"The serialized form: $s")
  val pr = read[X](s) // here the compiler complains: Couldn't derive type Option[hierarchy.X]
  println(s"The read object is $pr")
  println(s"The objects are equal: ${p == pr}")
}

Original Author: gregor-rayman

amnaredo commented 3 years ago

The following works:

package hierarchy

import upickle.default._

sealed trait X
case class Y(name: String, next: Option[X]) extends X // Note: No default `None` here

object Main extends App {
  val p = Y("Test", Some(Y("hello", None)))
  val s = write(p)
  println(s"The serialized form: $s")
  val pr = read[X](s)
  println(s"The read object is $pr")
  println(s"The objects are equal: ${p == pr}")
}

Original Author: gregor-rayman

amnaredo commented 3 years ago

Same problem here:

package tutorial.webapp

import scala.scalajs.js.JSApp
import scala.scalajs.js.annotation.JSExport

import upickle.default._

object AutoWireUpickle extends JSApp {
  @JSExport
  override def main(): Unit = {
    basics
  }

  def basics: Unit = {
    println(write(true))
    println(write(12L))
    println(write(12.3))
    println(write(4321: Long)) // Long is too big for js VM, represented as string
    println(write(Float.PositiveInfinity))
    println(write(Float.NegativeInfinity))
    println(write(List(1, 2, 3)))
    println(write(Some(1))) // [1]
    println(write(None)) // []

    case class Thing(a: Int, b: String)
    case class Big(i: Int, b: Boolean, str: String, c: Char, t: Thing)
    println(write(Big(1, true, "lol", 'Z', Thing(7, ""))))

    trait IntOrTuple
    case class IntThing(i: Int) extends IntOrTuple
    case class TupleThing(name: String, t: (Int, Int)) extends IntOrTuple
    println(write(IntThing(1)))
    println(write(TupleThing("naam", (1, 2))))
  }
}

Error msg:

[info] Compiling 1 Scala source to /Users/kaiyin/personal_config_bin_files/workspace/scalajsHandson/target/scala-2.11/classes...
[error] /Users/kaiyin/personal_config_bin_files/workspace/scalajsHandson/src/main/scala/tutorial/webapp/AutoWireUpickle.scala:27: Couldn't derive type Big
[error]     println(write(Big(1, true, "lol", 'Z', Thing(7, ""))))
[error]                  ^
[error] /Users/kaiyin/personal_config_bin_files/workspace/scalajsHandson/src/main/scala/tutorial/webapp/AutoWireUpickle.scala:32: Couldn't derive type IntThing
[error]     println(write(IntThing(1)))
[error]                  ^
[error] /Users/kaiyin/personal_config_bin_files/workspace/scalajsHandson/src/main/scala/tutorial/webapp/AutoWireUpickle.scala:33: Couldn't derive type TupleThing
[error]     println(write(TupleThing("naam", (1, 2))))
[error]                  ^
[error] three errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 1 s, completed 30 oct. 2015 15:22:33

Original Author: kindlychung

amnaredo commented 3 years ago

This is still an issue in trunk despite https://github.com/Voltir/upickle/commit/832756d3d8e1083ec00af6806f120b76f43f26ef

Original Author: lihaoyi

amnaredo commented 3 years ago

We're not rolling back. The changes are irrelevant, the problem is the compiler is nondeterministic

Original Author: lihaoyi

amnaredo commented 3 years ago

I see, in my case it was nondeterministic in a way that first it didn't matter that parts of the model that is being serialized are in different file but then suddenly I had to put it all to the same file. Possibly some sbt imcremental compilation stuff... Thanks !

Original Author: l15k4

amnaredo commented 3 years ago

I've just run up against this. Is there really nothing that can be done about it? I'm not sure about the indeterminism being the cause since whenever i've tried to extend my class in any way while the codebase has been evolving, it's never worked.

@lihaoyi If you can give me some pointers I'll try my hand at digging into macros...

Original Author: boosh

amnaredo commented 3 years ago

The sealed trait problems should be work-aroundable by http://www.lihaoyi.com/upickle-pprint/upickle/#ManualSealedTraitPicklers in 0.4.3; I don't know wh

Original Author: lihaoyi

amnaredo commented 3 years ago

This runs ok from the REPL in Ammonite:

import upickle.default._

case class Datos(@key("Bytes enviados/min") enviados: Int,
                 Conectados: Int,
                 @key("Bytes recibidos/min") recibidos: Int,
                 @key("Tramas/min") tramas: Int,
                 @key("ErroresPost/min") errores: Int,
                 @key("Post/min") post: Int)
val d = read[Datos](".....")

but fails to compile when used inside an Ammonite script:

Couldn't derive type Datos
                val d = read[Datos]("......")

Should I open another bug issue? Original Author: DavidPerezIngeniero

amnaredo commented 3 years ago

Solved by making Datos a top level class, instead of nested inside a function. Original Author: DavidPerezIngeniero