question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using Scala 3 seriously breaks default value handing

See original GitHub issue

Minimal example:

case class A(a: Int = 1)

import upickle.default._
implicit val rw: ReadWriter[A] = macroRW[A]

println(read[A]("{\"a\":2}"))
println(read[A]("{}"))

Expected (upickle 1.4.0, Scala 2.13.6):

A(2)
A(1)

Got (upickle 1.4.0, Scala 3.0.1):

A(2)
A(2)

God knows how many projects are silently corrupting their databases. Or leaking data from another user in their API calls. Since the parser is keeping and leaking state, everything is possible.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:10 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
joderskycommented, Aug 26, 2021

Maven doesn’t work that way, you can’t unpublish something. Also, that would break even more people’s deployments. That being said, this is a very high prio issue of course.

0reactions
lihaoyicommented, Sep 23, 2021

@jodersky if I’m not mistaken I think this is the fix

lihaoyi upickle$ git diff
diff --git a/build.sc b/build.sc
index 133b30f..8664795 100644
--- a/build.sc
+++ b/build.sc
@@ -14,7 +14,7 @@ import com.github.lolgab.mill.mima._
 val scala211  = "2.11.12"
 val scala212  = "2.12.13"
 val scala213  = "2.13.4"
-val scala3    = "3.0.0"
+val scala3    = "3.0.2"
 val scalaJS06 = "0.6.33"
 val scalaJS1  = "1.5.1"
 val scalaNative = "0.4.0"
diff --git a/implicits/src-3/upickle/implicits/CaseClassReader.scala b/implicits/src-3/upickle/implicits/CaseClassReader.scala
index de66b16..e21a6b1 100644
--- a/implicits/src-3/upickle/implicits/CaseClassReader.scala
+++ b/implicits/src-3/upickle/implicits/CaseClassReader.scala
@@ -11,9 +11,8 @@ trait CaseClassReaderPiece extends MacrosCommon:

     def visitorForKey(currentKey: String): Visitor[_, _]

-    private val builder = collection.mutable.Map.empty[String, Any]
-
     override def visitObject(length: Int, index: Int) = new ObjVisitor[Any, T] {
+      private val builder = collection.mutable.Map.empty[String, Any]
       var currentKey: String = null

       def subVisitor: Visitor[_, _] = visitorForKey(currentKey)
diff --git a/implicits/src-3/upickle/implicits/CaseClassWriter.scala b/implicits/src-3/upickle/implicits/CaseClassWriter.scala
index f2802c0..f49368c 100644
--- a/implicits/src-3/upickle/implicits/CaseClassWriter.scala
+++ b/implicits/src-3/upickle/implicits/CaseClassWriter.scala
@@ -14,8 +14,8 @@ trait CaseClassWriterPiece extends MacrosCommon:
       var n = 0
       for
         (name, _, value) <- elemsInfo(v)
-        defaultValue <- defaultParams.get(name)
-        if defaultValue != value || serializeDefaults
+        defaultValue = defaultParams.get(name)
+        if serializeDefaults || defaultValue.isEmpty || defaultValue.get != value
       do n += 1
       n
     end length

Looking at the Scala 3 macro code, it diverges from the Scala 2 implementation considerably; I haven’t benched it, but I bet the Scala 3 performance won’t be as good, as it seems to allocate a ton of stuff (it uses for-loops!? collections!?!? hashtables!?!?!?) that the Scala 2 version painstakingly avoids. We should definitely look into unifying them. They may do the same thing, but for a performance critical piece of code the Scala 2 version is what we want

Regardless, this small patch should fix this particular issue

Read more comments on GitHub >

github_iconTop Results From Across the Web

Default values not working with @key annotation in Scala 3 ...
Exception in thread "main" java.lang.ExceptionInInitializerError at com.nitka.rb.RBSyncApp.main(RBSyncApp.scala) Caused by: upickle.core.
Read more >
Scala default parameters and null
The correct default value can be picked by Scala tools, ... check and actual default value will break the contract established by the...
Read more >
Optional Braces
Scala 3 enforces some rules on indentation and allows some occurrences of braces {. ... First, some badly indented programs are flagged with...
Read more >
Optional Braces - Scala 3 - EPFL
Scala 3 enforces some rules on indentation and allows some occurrences of braces {. ... First, some badly indented programs are flagged with...
Read more >
4. Functions - Learning Scala [Book]
With this procedure syntax, any return value (or final expression) will be discarded. To address this problem, it is recommended that developers stick...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found