scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.86k stars 1.06k forks source link

Regression in `jcouyang/dhall-generic` for implicit search #20298

Closed WojciechMazur closed 5 months ago

WojciechMazur commented 5 months ago

Based on OpenCB failures in jcouyang/dhall-generic - build logs

The compiler fails to search for implicit instances defined in companion of the typeclass. It requires explicit import at the place of usage

Compiler version

Last good release: 3.5.0-RC1-bin-20240406-521ce95-NIGHTLY First bad release: 3.5.0-RC1-bin-20240408-1e8a653-NIGHTLY

The compilation errors when building compiler prevented gathering the exact commit that coused regression it can be any of: d2a6392131001af941b0614c9e6d812e8c761965 1dc5b995cfb84dd3e2673041d6e954ed6043900e 321d0d2cdee757fe311c9959817794acaad0fbdb 1e8a653cce58ddb038c04a906448db92172828dd

The project-wise bisect nominated 90c3fbde37a70fdd366ed25d2082e05ddf24ac3e as the cause of the regression

Minimized code

Needs to be defined as 2 compilation units I was able to reproducer Decoder[Empty] in single file, but the other cases required definitions and usage to be split in previous Scala versions.

// 1_defns.scala
import scala.compiletime.*
import scala.deriving.*

sealed trait Decoder[T]
object Decoder:
  inline given summonEmptyTuple[H]: Tuple.Map[EmptyTuple.type, Decoder] = EmptyTuple
  inline given summonTuple[H, T <: Tuple](using
      hd: Decoder[H],
      td: Tuple.Map[T, Decoder]
  ): Tuple.Map[H *: T, Decoder] = hd *: td
  inline given derived[T](using
      m: Mirror.Of[T],
      d: Tuple.Map[m.MirroredElemTypes, Decoder]
  ): Decoder[T] = ???
  given Decoder[Double] = ???
// 2_usage.scala
case class Empty()
object Empty {
  val fails = Decoder.derived[Empty]
}

enum Shape:
  case Rectangle(width: Double, height: Double)
  case Circle(radius: Double)

object Shape:
  val fails1 = Decoder.derived[Rectangle]
  val fails2 = Decoder.derived[Shape]

Output

-- [E172] Type Error: /Users/wmazur/projects/sandbox/repro.test.scala:4:39 -----
4 |  val instance = Decoder.derived[Empty]
  |                                       ^
  |No given instance of type Tuple.Map[m.MirroredElemTypes, Decoder] was found for parameter d of given instance derived in object Decoder
  |
  |Note: a match type could not be fully reduced:
  |
  |  trying to reduce  Tuple.Map[m.MirroredElemTypes, Decoder]
  |  failed since selector m.MirroredElemTypes
  |  does not match  case EmptyTuple => EmptyTuple
  |  and cannot be shown to be disjoint from it either.
  |  Therefore, reduction cannot advance to the remaining case
  |
  |    case h *: t => Decoder[h] *: Tuple.Map[t, Decoder]
-- [E172] Type Error: /Users/wmazur/projects/sandbox/repro.test.scala:12:38 ----
12 |  val rec = Decoder.derived[Rectangle]
   |                                      ^
   |No given instance of type Tuple.Map[m.MirroredElemTypes, Decoder] was found for parameter d of given instance derived in object Decoder.
   |I found:
   |
   |    Decoder.summonTuple[Double, Double *: EmptyTuple.type](
   |      Decoder.given_Decoder_Double,
   |      Decoder.summonTuple[Double, EmptyTuple.type](Decoder.given_Decoder_Double,
   |        /* missing */summon[Tuple.Map[EmptyTuple.type, Decoder]])
   |    )
   |
   |But no implicit values were found that match type Tuple.Map[EmptyTuple.type, Decoder].
   |
   |Note: a match type could not be fully reduced:
   |
   |  trying to reduce  Tuple.Map[m.MirroredElemTypes, Decoder]
   |  failed since selector m.MirroredElemTypes
   |  does not match  case EmptyTuple => EmptyTuple
   |  and cannot be shown to be disjoint from it either.
   |  Therefore, reduction cannot advance to the remaining case
   |
   |    case h *: t => Decoder[h] *: Tuple.Map[t, Decoder]
3 errors found

Expectation

Should compile

EugeneFlesselle commented 5 months ago

I believe this is an expected error. Or at least, we intended for it to be an error in #20077. The i15183 test looks to be a very similar minimisation as above, it was changed in the PR to account for the fix in determining implicit scope.

TLDR the regression is necessary for the implicit scope to be the same for joint vs separate compilation. I believe it would be fixed here too by adding an import Decoder.given in 2_usage.scala.

Gedochao commented 5 months ago

Alright, there's nothing we can fix on our side, it seems. Code changes will be necessary. Closing this.