Skip to content

Divergence checker does not detect loop with higher-kinded type, unlike Scala 2 #9504

Closed
@smarter

Description

@smarter

Minimized code

trait Monad[F[_]] {
  def foo[A](fa: F[A]): Unit = {}
}

class Bla[F[_], A]

object Test {
  type Id[A] = A

  val bla: Bla[Id, Unit] = ???
  implicit def blaMonad[F[_]: Monad, S]: Monad[({type L[X] = Bla[F, X]})#L] = ???

  blaMonad.foo(bla)
}

Output

With Dotty, the compiler runs for ~20 seconds before producing a giant error message:

-- Error: try/divloop.scala:19:10 ----------------------------------------------
19 |  blaMonad.foo(bla)
   |          ^
   |no implicit argument of type Monad[([_$3] =>> Any)] was found for an implicit parameter of method blaMonad in object Test.
   |I found:
   |
   |    Test.blaMonad[F, S](
   |      Test.blaMonad[F, S](
   |        Test.blaMonad[F, S](
...

Expectation

With Scala 2, the compiler pretty much instantly stops with:

try/divloop.scala:19: error: diverging implicit expansion for type Monad[F]
starting with method blaMonad in object Test
  blaMonad.foo(bla)
  ^

This is not just a problem for malformed code: if I add another implicit to have a base case:

  implicit def idMonad: Monad[Id] = ???

Then Dotty still fails in the same way whereas Scala 2 is able to correctly resolve:

blaMonad(idMonad).foo(bla)

I came across this while trying to see what happens if cats Monad used dotty's extension method syntax (#9480).

Tentatively assigning to Miles since he wrote the divergence checker.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions