-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add unapply methods that return an Option for compatibility? #2335
Comments
Great that you got to the bottom of this! I think you meant:
It turns out that neither this method nor the original method in Ammonite is needed. They just duplicate the typecheck that the compiler does anyway. One can and should delete them. I am not very keen about generating a new method. It's ugly and will get us into overloading troubles. On the other hand, it certainly is a serious incompatibility with Scala 2. |
Yes, edited.
I tried to delete the |
I see. Well, in that case just inline |
Introducing an |
@olafurpg Could you try to get some statistics on how often Scala projects explicitly use |
Workaround #2335 issue in bootstraped REPL
I would expect the In the common case the dotty/scalac difference would result in a compilation error (the return type of unapply changed from @smarter I really don't see an alternative to your suggestion (maybe under case class A(i: Int, s: String)
val a: Option[(Int, String)] = A.unapply(A(1, "s")) |
I'd say, let's wait and see how much breaks in practice. |
Sure.
For future reference: I think we could get around overloading issue by marking the generated method as |
@smarter, using |
This would help play-json cross compilation in code like this case class Car(id: Long, models: Map[String, String])
implicit val CarFormat = (
(__ \ Symbol("id")).format[Long] and
(__ \ Symbol("models")).format[Map[String, String]]
)(Car.apply, unlift(Car.unapply)) Actually the |
Let's try: |
Indeed: scala> case class Car(id: Long, models: Map[String, String])
// defined case class Car
scala> def unapply(car: Car) = Tuple.fromProductTyped(car)
def unapply(car: Car): (Long, Map[String, String]) |
I think this secretly returns a hidden generic tuple type leading to #10958 |
Well, we missed the train on this for 3.0.0 and it hasn't seemed to be a major issue. Let's not do this. |
uh, excuse me, what was the point of replacing previously useful unapply with identity? |
It allowed us to generalise cheap, option-less unapply methods to all Product types, not just case classes. |
In case someone else comes here looking for the generated case class unapply function, here's how I replaced it: def unapply[P <: Product](p: P)(using m: scala.deriving.Mirror.ProductOf[P]): Option[m.MirroredElemTypes] =
Some(Tuple.fromProductTyped(p)) Now you can just use |
This is prompted by guardian/mobile-apps-api#3198 - we would like to be able to upgrade MAPI to Scala 3. As MAPI depends on https://github.com/guardian/cross-platform-navigation, it's good to have a Scala 3 version of this library. The only tricky part of upgrading `cross-platform-navigation` to Scala 3 is handling the explicit call to the `unapply()` method, which _used_ to return an `Option[(...,...,...)]` with all the parameters used to create the case class - in Scala 3 that's changed: * https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#explicit-call-to-unapply * scala/scala3#2335 The least magical way to cope with the changed `unapply()` method is to manually write out what the unapply method used to produce, and that's what I've done here. Looking at the discussion on the Scala issue, there are other workarounds which are Scala 3-only (and so wouldn't easily work in this project, which cross-compiles with Scala 2): * scala/scala3#2335 (comment) gives us this, which did work for me, but just in Scala 3: ``` def doOldUnapply(ns: NavigationSection) = Some(Tuple.fromProductTyped(ns)) ``` * scala/scala3#2335 (comment) - this is apparently a general version of the method above, but didn't work for me - complained that `NavigationSection` is not a `Product`, I think?
This is prompted by guardian/mobile-apps-api#3198 - we would like to be able to upgrade MAPI to Scala 3. As MAPI depends on https://github.com/guardian/cross-platform-navigation, it's good to have a Scala 3 version of this library. The only tricky part of upgrading `cross-platform-navigation` to Scala 3 is handling the explicit call to the `unapply()` method, which _used_ to return an `Option[(...,...,...)]` with all the parameters used to create the case class - in Scala 3 that's changed: * https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#explicit-call-to-unapply * scala/scala3#2335 The least magical way to cope with the changed `unapply()` method is to manually write out what the unapply method used to produce, and that's what I've done here. Looking at the discussion on the Scala issue, there are other workarounds which are Scala 3-only (and so wouldn't easily work in this project, which cross-compiles with Scala 2): * scala/scala3#2335 (comment) gives us this, which did work for me, but just in Scala 3: ``` def doOldUnapply(ns: NavigationSection) = Some(Tuple.fromProductTyped(ns)) ``` * scala/scala3#2335 (comment) - this is apparently a general version of the method above, but didn't work for me - complained that `NavigationSection` is not a `Product`, I think?
This is prompted by guardian/mobile-apps-api#3198 - we would like to be able to upgrade MAPI to Scala 3. As MAPI depends on https://github.com/guardian/cross-platform-navigation, it's good to have a Scala 3 version of this library. The only tricky part of upgrading `cross-platform-navigation` to Scala 3 is handling the explicit call to the `unapply()` method, which _used_ to return an `Option[(...,...,...)]` with all the parameters used to create the case class - in Scala 3 that's changed: * https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#explicit-call-to-unapply * scala/scala3#2335 The least magical way to cope with the changed `unapply()` method is to manually write out what the unapply method used to produce, and that's what I've done here. Looking at the discussion on the Scala issue, there are other workarounds which are Scala 3-only (and so wouldn't easily work in this project, which cross-compiles with Scala 2): * scala/scala3#2335 (comment) gives us this, which did work for me, but just in Scala 3: ``` def doOldUnapply(ns: NavigationSection) = Some(Tuple.fromProductTyped(ns)) ``` * scala/scala3#2335 (comment) - this is apparently a general version of the method above, but didn't work for me - complained that `NavigationSection` is not a `Product`, I think?
Here's an interesting problem minmized from https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/repl/ammonite/Protocol.scala that causes
dotty-compiler-bootstrapped/repl
to go into an infinite loop:With
scalac
, the unapply call goes to the generateddef unapply(x$1: Bar): Option[Int]
, but with dotty no such method exist, instead we only generate adef unapply(x$1: Bar): Bar
, so the previously perfectly correct code becomes an infinite loop!I think we can fix this by always generating an unapply method that returns an
Option
, even if we don't use it.The text was updated successfully, but these errors were encountered: