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

Allow specifying this to be an inline parameter on inline methods

Open fhackett opened this issue 5 years ago • 0 comments

This request is paraphrased from this issue on Dotty proper, which started as an improvement I was planning on implementing for inliner internals: https://github.com/lampepfl/dotty/issues/8294#issuecomment-585328641. Now it seems we need a new language feature to get the feature I wanted working...

Take this example:

import scala.compiletime._

object Test {
  case class B(i: Int)
  case class C(b: B) {
    inline def giveMeI: Int =
      inline b match {
        case B(i) => i
      }
  }

  def main(argv: Array[String]): Unit =
    println(code"${ C(B(12)).giveMeI }")
}

Even with the improvement mentioned in the issue I reference above, the best we can hope for is this kind of expansion:

{
  val C_b: Test.B = B(12)
  val B_i: Int = C_b.i
  i
}

This is OK as a simple performance-minded elision of the C instance, but if we actually intended to fully destructure C(B(12)) at compile-time then we reach an impasse where it would be unsound to treat the members of C as inline because nowhere have they been defined as such.

Really, we need the ability to specify an inline method's this as inline, like we can for all its other parameters.

Here is a straw-man of this idea:

import scala.compiletime._

object Test {
  case class B(i: Int)
  case class C(b: B) {
    inline[this] def giveMeI: Int =
      inline b match {
        case B(i) => i
      }
  }

  def main(argv: Array[String]): Unit =
    println(code"${ C(B(12)).giveMeI }")
}

inline[this] tells the inliner that we intend to treat this as an inline parameter, so we end up with this kind of substitution when expanding giveMeI:

inline C(B(12)).b match {
  case B(i) => i
}

Unlike before, we can fully expect to see C(B(12)) evaluated any number of times (including 0!), so it's fine to just paste it everywhere. Then, the rest of the inliner's rules can (in this case) reduce the expression to the 12 we wanted while completely eliding both nested case class instances.

One thing I have not fully thought through: in my straw man syntax, can you put something other than this in inline[this], similar to private[...]? Would that make any semantic sense / have any use?

fhackett avatar Feb 12 '20 18:02 fhackett