playframework / play-json

The Play JSON library
Apache License 2.0
361 stars 134 forks source link

Constructing Writes fail to compile with Scala 3 #1039

Open levinson opened 6 months ago

levinson commented 6 months ago

Play JSON Version (2.5.x / etc)

Affected versions:

API (Scala / Java / Neither / Both)

Scala

Operating System (Ubuntu 15.10 / MacOS 10.10 / Windows 10)

MacOS 14.3.1

JDK (Oracle 1.8.0_72, OpenJDK 1.8.x, Azul Zing)

Paste the output from java -version at the command line.

java version "17.0.10" 2024-01-16 LTS Java(TM) SE Runtime Environment (build 17.0.10+11-LTS-240) Java HotSpot(TM) 64-Bit Server VM (build 17.0.10+11-LTS-240, mixed mode, sharing)

Library Dependencies

None

Expected Behavior

Constructing Writes according to the README should succeed in Scala 3. For example:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Location(lat: Double, long: Double)

object ConstructingWrites {
  implicit val locationWrites: Writes[Location] = (
    (JsPath \ "lat").write[Double] and
      (JsPath \ "long").write[Double]
    ) (unlift(Location.unapply))
}

Actual Behavior

The above code from README fails to compile with Scala 3. The compiler gives the following error:

[error] -- [E007] Type Mismatch Error:
[error] 11 |  )(unlift(Location.unapply))
[error]    |           ^^^^^^^^^^^^^^^^
[error]    |           Found:    Location
[error]    |           Required: Option[Any]

As a workaround a custom unapply method can be defined:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Location(lat: Double, long: Double)

object ConstructingWrites {
  def locationUnapply(loc: Location): Option[(Double, Double)] = Some((loc.lat, loc.long))

  implicit val locationWrites: Writes[Location] = (
    (JsPath \ "lat").write[Double] and
      (JsPath \ "long").write[Double]
    )(unlift(locationUnapply))
}

Reproducible Test Case

Compile the code from Expected Behavior with Scala 3 in order to reproduce the issue:

scalaVersion := "3.3.3" // works with "2.13.14"

libraryDependencies += "org.playframework" %% "play-json" % "3.0.3" // same behavior with 2.10.5
levinson commented 5 months ago

Updated the linked PR based on guidance from https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#explicit-call-to-unapply