optics-dev / Monocle

Optics library for Scala
https://www.optics.dev/Monocle/
MIT License
1.65k stars 205 forks source link

Lenses can't be created for classes with private constructors for Scala 3 #1426

Open vadzim-marchanka opened 8 months ago

vadzim-marchanka commented 8 months ago

Hello,

I've noticed that the code that compiles and works fine in scala 2 doesn't work for scala 3.

Scastie: Scala 2 -> https://scastie.scala-lang.org/FmuLKaM0TpmNvQ3xHdpUSg Scala 3 -> https://scastie.scala-lang.org/7FBOxnIPQbemh5TomJrUig

Code:

import monocle.syntax.all._

case class A private (field1: String, field2: String)
object A {
  def apply(field1: String, field2: String): A = new A(field1, field2)

  val copiedObject = A("1", "2").copy(field1 = "3")
  val modifiedObject = A("1", "2").focus(_.field1).replace("3")

  println(copiedObject)
  println(modifiedObject)
}

val copiedObject = A("1", "2").copy(field1 = "3") //compile error
val modifiedObject = A("1", "2").focus(_.field1).replace("3") //compile error
println(copiedObject)
println(modifiedObject) 

Error:

missing argument for parameter field2 of method copy in class A: (field1: String, field2: String): Playground.A
method copy cannot be accessed as a member of (from : Playground.A) from module class Playground$.

Could you please clarify whether it is expected behavior?

julien-truffaut commented 8 months ago

I believe it is expected when you use private in your case class definition.

vadzim-marchanka commented 7 months ago

Thank you for the response. Should the library behavior be the same for Scala 2 and 3? I expect that people migrating their codebase from Scala 2 to Scala 3 may face this issue.

julien-truffaut commented 7 months ago

Ideally, yes it should be the same but I believe this is due to a change of semantic between Scala 2 and 3 for private case class constructors. So Monocle is just following the Scala language.