Dotty: Error on calling a method on the result of a Scala 2 style polymorphic extension method

Created on 30 Oct 2020  路  5Comments  路  Source: lampepfl/dotty

Minimized code

// build.sbt
lazy val root = project
  .in(file("."))
  .settings(
    scalaVersion := "3.0.0-M1-bin-20201027-b5a1715-NIGHTLY",
    libraryDependencies ++= Seq(
      "com.sksamuel.elastic4s" % "elastic4s-embedded_2.13" % "5.6.11"
    )
  )

```scala
//src/main/scala/Main.scala
import com.sksamuel.elastic4s.TcpClient
import com.sksamuel.elastic4s.ElasticDsl
import org.elasticsearch.cluster.health.ClusterHealthStatus

object Main {
import ElasticDsl._

def status1(client: TcpClient): ClusterHealthStatus = {
val response = client.execute(clusterHealth()).await
response.getStatus()
}

def status2(client: TcpClient): ClusterHealthStatus =
client.execute(clusterHealth()).await.getStatus()
}



## Output

```scala
[info] compiling 1 Scala source to /target/scala-3.0.0-M1/classes ...
[error] -- [E008] Not Found Error: /src/main/scala/Main.scala:15:42 
[error] 15 |    client.execute(clusterHealth()).await.getStatus()
[error]    |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value getStatus is not a member of org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse - did you mean org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse.getStatus
[error] one error found

Expectation

Method status1 does compile and so method status2 should compile as well.

typer scala2 bug

Most helpful comment

Ironically, I got the same error for the compiler source when trying to debug this.

              typed(app, pt, locked)
                .reporting(i"typed: $result: ${result.tpe}")  // I tried to add this line

Here's what I got:

typer/Typer.scala:3141:54 
[error] 3141 |                .reporting(i"typed: $result: ${result.tpe}")
[error]      |                                               ^^^^^^^^^^
[error]      |value tpe is not a member of T
[error]      |
[error]      |where:    T is a type variable with constraint >: dotty.tools.dotc.ast.Trees.Tree[dotty.tools.dotc.core.Types.Type]

A meta-circular error, so to speak...

All 5 comments

Error on calling a method in a Java class

  • It looks like you're depending on a Scala 2 library, can the problem be reproduced without the Scala 2 dependency?
  • Can this be minimized to not depend on any external library?

I think the problem can be minimized into:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._

class Foo() {
  val status: Int = 0
}

object Main {
  implicit class RichFuture[T](future: Future[T]) {
    def await(implicit duration: Duration = 10.seconds): T = Await.result(future, duration)
  }

  def test1: Int = {
    val foo = Future(new Foo()).await
    foo.status
  }

  val test2 = Future(new Foo()).await.status
}

Then the error message is more precise:

[error] -- [E008] Not Found Error: /src/main/scala/Main.scala:20:38 
[error] 20 |  val test2 = Future(new Foo()).await.status
[error]    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |              value status is not a member of T
[error]    |
[error]    |              where:    T is a type variable with constraint >: Foo

Minimized further without references to stdlib:

class D
class C[+T](x: T)

class Foo() {
  val status: Int = 0
}

object Main {
  implicit class RichC[T](c: C[T]) {
    def await(implicit d: D = ???): T = ???   
      // it's critical that the default is selected on the call below
      // it works if there is an implicit in scope for `d`
  }

  def test1: Int = {
    val foo = new C(new Foo()).await
    foo.status
  }

  val test2 = new C(new Foo()).await.status
}

Ironically, I got the same error for the compiler source when trying to debug this.

              typed(app, pt, locked)
                .reporting(i"typed: $result: ${result.tpe}")  // I tried to add this line

Here's what I got:

typer/Typer.scala:3141:54 
[error] 3141 |                .reporting(i"typed: $result: ${result.tpe}")
[error]      |                                               ^^^^^^^^^^
[error]      |value tpe is not a member of T
[error]      |
[error]      |where:    T is a type variable with constraint >: dotty.tools.dotc.ast.Trees.Tree[dotty.tools.dotc.core.Types.Type]

A meta-circular error, so to speak...

Was this page helpful?
0 / 5 - 0 ratings