Skip to content

Expr.betaReduce can't reduce past the type ascription from inline def expansion #8250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
fhackett opened this issue Feb 8, 2020 · 1 comment · Fixed by #8251
Closed

Expr.betaReduce can't reduce past the type ascription from inline def expansion #8250

fhackett opened this issue Feb 8, 2020 · 1 comment · Fixed by #8251

Comments

@fhackett
Copy link
Contributor

fhackett commented Feb 8, 2020

minimized code

Macros_1.scala

import scala.quoted._

object Macros {
  inline def betaReduce[Arg,Result](inline fn: Arg=>Result)(inline arg: Arg): Result =
    ${ betaReduceImpl('{ fn })('{ arg }) }
  def betaReduceImpl[Arg,Result](fn: Expr[Arg=>Result])(arg: Expr[Arg]): Expr[Result] =
    Expr.betaReduce(fn)(arg)
}

Test_2.scala

import scala.compiletime._

object Test {
  inline def dummy: Int=>Int =
    (i: Int) => i + 1
  def main(argv: Array[String]): Unit = {
    println(code"${ Macros.betaReduce(dummy)(3) }")
  }
}

Output

(
  {
    def $anonfun(i: Int): Int = i.+(1)
    closure($anonfun)
  }
:Function1[Int, Int]).apply(
  {
    3
  }
)

expectation

4
fhackett added a commit to fhackett/dotty that referenced this issue Feb 8, 2020
When a blackbox inline def is inlined, a type ascription is added to preserve the apparent return type
of the inline def. Prior to this commit, the quoted.Expr.betaReduce function was unable to properly
inline a known lambda expression coming from an inline def as it would see the type ascription and
give up.

This change instead makes betaReduce drop type ascriptions, allowing these two features to interact properly.

Testing is done by verifying that betaReduce can correctly reduce the application of the result of an inline def
to a constant value, with the reduction result being printed using the `compiletime.code` interpolator.
@fhackett
Copy link
Contributor Author

fhackett commented Feb 8, 2020

I had a go at fixing the issue. See #8251 for the proposed fix as well as some discussion.

fhackett added a commit to fhackett/dotty that referenced this issue Feb 10, 2020
When a blackbox inline def is inlined, a type ascription is added to preserve the apparent return type
of the inline def. Prior to this commit, the quoted.Expr.betaReduce function was unable to properly
inline a known lambda expression coming from an inline def as it would see the type ascription and
give up.

This change makes betaReduce rewrite type ascriptions, allowing it to inline type-ascribed functions such as those coming
from inlined defs.

- When type ascriptions are not present, behaviour does not change.
- When type ascriptions are encountered, the outermost ascription is kept.
- If the inline is successful, then the result type of the ascribed function type is ascribed to the inlined body.
- If the inline is not successful, the outermost ascribed type is re-ascribed to the non-inlineable expression before
  inserting a call to that expression.

There are several test cases, covering:
- verifying that betaReduce can correctly reduce the application of the result of an inline def
  to a constant value, with the reduction result being printed using the `compiletime.code` interpolator.
- verifying that the result type ascription handles dependent function types
- inserting ??? as either the inlined body or a function expression that cannot be inlined compiles without error (by
  re-ascribing the apparent type)
- a neg-test that a function whose type is `Int=>Int` and whose body inlines to `4` does not typecheck against the
  singleton type `4`.
nicolasstucki added a commit that referenced this issue Feb 11, 2020
Fix #8250: Allow Expr.betaReduce to drop type ascriptions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants