dotty-feature-requests icon indicating copy to clipboard operation
dotty-feature-requests copied to clipboard

Infer `this` prefix to extension methods called within a template of a matching type

Open ibaklan opened this issue 6 years ago • 1 comments

After recently merged extension methods pull request it still remain issue with accessing to extension methods which apples to this. It is naturally expected behavior that this.extensionMethod() should be also available as simply extensionMethod() (without this. prefix) at least in case when extensionMethod name does not clash with other names available in scope. So that one may expect that this.extensionMethod() <==> extensionMethod() in cases when this.extensionMethod() is valid/available.

Demonstrating examples:

object TestMainV0 {
  def main(args: Array[String]): Unit = {
    extensionTargetTest()
  }

  trait ExtensionTarget

  def (`this`: ExtensionTarget) testedExtensionMethod (): String = "hardcode"

  object extensionTargetTest extends ExtensionTarget {
    def apply() : Unit = {
      assert("hardcode" == this.testedExtensionMethod()) // this line works as expected
      assert(this.testedExtensionMethod() == testedExtensionMethod()) // <-- this line cause compilation error
    }
  }
}

Compilation fails with error

      assert(this.testedExtensionMethod() == testedExtensionMethod()) // <-- this line cause compilation error
                                             ^^^^^^^^^^^^^^^^^^^^^^^
      missing argument for parameter this of method testedExtensionMethod: (this: M04_02_v0.ExtensionTarget)(): String
object TestMainV1 {
  def main(args: Array[String]): Unit = {
    extensionTargetTest()
  }

  trait ExtensionTarget

  implicit object extensionProvider {
    def (`this`: ExtensionTarget) testedExtensionMethod (): String = "hardcode"
  }

  object extensionTargetTest extends ExtensionTarget {
    def apply() : Unit = {
      assert("hardcode" == this.testedExtensionMethod()) // this line works as expected
      assert(this.testedExtensionMethod() == testedExtensionMethod()) // <-- this line cause compilation error
    }
  }
}
object TestMainV2 {
  def main(args: Array[String]): Unit = {
    extensionTargetTest()
  }

  trait ExtensionTarget

  trait ExtensionProvider {
    def (`this`: ExtensionTarget) testedExtensionMethod (): String = "hardcode"
  }

  object extensionTargetTest extends ExtensionTarget {
    def apply() : Unit = {
      implicit object extensionProvider extends ExtensionProvider
      assert("hardcode" == this.testedExtensionMethod()) // this line works as expected
      assert(this.testedExtensionMethod() == testedExtensionMethod()) // <-- this line cause compilation error
    }
  }
}

Compilation fails with error

      assert(this.testedExtensionMethod() == testedExtensionMethod()) // <-- this line cause compilation error
                                             ^^^^^^^^^^^^^^^^^^^^^
                                        not found: testedExtensionMethod

FYI In Kotlin extension methods applied to this could be called without this. prefix (so that it works as expected in Kotlin)

similar kotlin snippet: (compiles and runs as is)

object TestsMain {

    @JvmStatic
    fun main(args: Array<String>) {
        extensionTargetTest()
    }

    fun ExtensionTarget2.testedExtensionMethod(): String = "hardcode"

    interface ExtensionTarget2

    object extensionTargetTest : ExtensionTarget2 {
        operator fun invoke() : Unit {
            assert("hardcode" == this.testedExtensionMethod())
            assert(this.testedExtensionMethod() == testedExtensionMethod())
        }
    }
}

Previous discussion: [1] , [2]

ibaklan avatar Dec 10 '18 19:12 ibaklan

Bigger motivational example in this post

ibaklan avatar Dec 11 '18 09:12 ibaklan