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.

Add unapply methods that return an Option for compatibility?

See original GitHub issue

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:

class Foo
case class Bar(x: Int) extends Foo

object Bar {
  def unapply(foo: Foo): Option[Int] = foo match {
    case foo: Bar =>
      unapply(foo)
  }
}

With scalac, the unapply call goes to the generated def unapply(x$1: Bar): Option[Int] , but with dotty no such method exist, instead we only generate a def 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.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:18 (15 by maintainers)

github_iconTop GitHub Comments

1reaction
OlivierBlanvillaincommented, May 1, 2017

I would expect the unapply usage to be very high. What we are interested in are direct calls to compiler generated unapply, which won’t be so easy to differentiate from user defined ones…

In the common case the dotty/scalac difference would result in a compilation error (the return type of unapply changed from Option[TupleN] to A), this is a very sneaky example where it doesn’t break compilation (because of overloading)…

@smarter I really don’t see an alternative to your suggestion (maybe under -language:Scala2?), or snippets like the following won’t cross compile:

case class A(i: Int, s: String)
val a: Option[(Int, String)] = A.unapply(A(1, "s"))
0reactions
ornicarcommented, Nov 10, 2022

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 unapply where you would previously use Foo.unapply

Read more comments on GitHub >

github_iconTop Results From Across the Web

overloading unapply method in case classes: scala
Your unapply method could not be used in pattern matching. It works with def unapply(arg: <type to match>) : Option[(<matched fields types>) ...
Read more >
Seth Tisue
In Scala 2 you eta-expand `unapply` to get a conversion from case class to tuple: > case class Foo(a: Int, b: String) >...
Read more >
Option-less pattern matching - Scala 3 - EPFL
Extractors are objects that expose a method unapply or unapplySeq : ... for compatibility reasons, isEmpty on Some has return type Boolean rather...
Read more >
The case for unapply - Beyond the lines
The case for unapply. Scala's unapply method is often left unconsidered although it presents an elegant way to solve some specific problems.
Read more >
Data Exposure and Encapsulation
Scala looks for a method called unapply on the PersonName object; unapply should accept a PersonName and return an optional tuple of two...
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