scala / scala3

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

FTypePolymorphism does not type check correctly using `typeChecks` #18150

Open dhinojosa opened 1 year ago

dhinojosa commented 1 year ago

Compiler version

3.2.2

Minimized code

object TypeCheck: 
  def main(args: Array[String]): Unit =
    val result = 
      scala.compiletime.testing.typeChecks(
        "trait RecursiveSelfTypeEntity[E <: RecursiveSelfTypeEntity[E]]: \n" +
        "  self: E => \n" +
        "  def create(): E \n" +
        "  def read(id: Long): Option[E] \n" +
        "  def update(f: E => E): E \n" +
        "  def delete(id: Long): Unit \n" +
        "\n" +
        "class Apple extends RecursiveSelfTypeEntity[Apple]: \n" +
        "  override def create(): Apple = ??? \n" +
        "  override def read(id: Long): Option[Apple] = ??? \n" +
        "  override def update(f: Apple => Apple): Apple = ??? \n" +
        "  override def delete(id: Long): Unit = ??? \n" +
        " \n" +
        "class Orange extends RecursiveSelfTypeEntity[Orange]: \n" +
        "  override def create(): Orange = ??? \n" +
        "  override def read(id: Long): Option[Orange] = ??? \n" +
        "  override def update(f: Orange => Orange): Orange = ??? \n" +
        "  override def delete(id: Long): Unit = ??? \n" + 
        " \n" +
        "class Banana extends RecursiveSelfTypeEntity[Apple]: \n" +
        "  override def create(): Apple = ??? \n" +
        "  override def read(id: Long): Option[Apple] = ??? \n" +
        "  override def update(f: Apple => Apple): Apple = ??? \n" +
        "  override def delete(id: Long): Unit = ???\n"
      )
    assert(result, "Should fail type check, but it didn't.")

Output

Nothing.

Expectation

It should throw an exception from typeChecks since Banana cannot extend from RecursiveSelfTypeEntity[Apple]

odersky commented 1 year ago

Bounds tests are run in the phase after type checking. So that's why typeChecks fails. We cannot run bounds tests during typer since F-bounds would cause cyclic dependencies.

Mitigation: Maybe scala.compiletime.testing.typeChecks should run bounds checks after type checking proper succeeds?

cheeseng commented 1 year ago

@odersky @smarter @dhinojosa Fyi we have another issue reported for assertDoesNotCompile that I think is related to this, with perhaps another minimal example?

https://github.com/scalatest/scalatest/issues/2283

One side note is that Scala 2's scala.reflect.macros.Context.typeCheck worked, so imho this will look like a regression for user migrating from Scala 2 to Scala 3.