From 5f19cf36e97994eab0a4ba30744f3905c3098ab2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 15 Dec 2020 14:13:51 +0100 Subject: [PATCH] Fix staging using inline methods in quotes Follow-up of #10709 --- .../dotty/tools/dotc/transform/Inlining.scala | 71 +++++++++++++++++++ .../scala/quoted/staging/QuoteCompiler.scala | 6 +- tests/run-staging/i3876-d.check | 2 +- .../{disabled => }/run-staging/i3876-d.scala | 0 tests/run-staging/quote-toExprOfTuple.check | 3 + tests/run-staging/quote-toExprOfTuple.scala | 2 +- 6 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/transform/Inlining.scala rename tests/{disabled => }/run-staging/i3876-d.scala (100%) diff --git a/compiler/src/dotty/tools/dotc/transform/Inlining.scala b/compiler/src/dotty/tools/dotc/transform/Inlining.scala new file mode 100644 index 000000000000..163bfb25ff4f --- /dev/null +++ b/compiler/src/dotty/tools/dotc/transform/Inlining.scala @@ -0,0 +1,71 @@ +package dotty.tools.dotc +package transform + +import core._ +import Decorators._ +import Flags._ +import Types._ +import Contexts._ +import Symbols._ +import Constants._ +import ast.Trees._ +import ast.{TreeTypeMap, untpd} +import util.Spans._ +import tasty.TreePickler.Hole +import SymUtils._ +import NameKinds._ +import dotty.tools.dotc.ast.tpd +import typer.Implicits.SearchFailureType + +import scala.collection.mutable +import dotty.tools.dotc.core.Annotations._ +import dotty.tools.dotc.core.Names._ +import dotty.tools.dotc.core.StdNames._ +import dotty.tools.dotc.core.StagingContext._ +import dotty.tools.dotc.quoted._ +import dotty.tools.dotc.transform.TreeMapWithStages._ +import dotty.tools.dotc.typer.Inliner +import dotty.tools.dotc.typer.ImportInfo.withRootImports + +import scala.annotation.constructorOnly + +/** Inlines all calls to inline methods that are not in an inline method or a quote */ +class Inlining extends MacroTransform { + import tpd._ + + override def phaseName: String = Inlining.name + + override def allowsImplicitSearch: Boolean = true + + override def checkPostCondition(tree: Tree)(using Context): Unit = + tree match { + case tree: RefTree if !Inliner.inInlineMethod && StagingContext.level == 0 => + assert(!tree.symbol.isInlineMethod) + case _ => + } + + protected def newTransformer(using Context): Transformer = new Transformer { + override def transform(tree: tpd.Tree)(using Context): tpd.Tree = + tree match + case tree: DefTree => + if tree.symbol.is(Inline) then tree + else super.transform(tree) + case _: Typed | _: Block => + super.transform(tree) + case _ if Inliner.isInlineable(tree) && !tree.tpe.widen.isInstanceOf[MethodOrPoly] && StagingContext.level == 0 => + val tree1 = super.transform(tree) + val inlined = Inliner.inlineCall(tree1) + if tree1 eq inlined then inlined + else transform(inlined) + case _: TypeApply if tree.symbol.isQuote => + ctx.compilationUnit.needsStaging = true + super.transform(tree) + case _ => + super.transform(tree) + + } +} + +object Inlining { + val name: String = "inlining" +} diff --git a/staging/src/scala/quoted/staging/QuoteCompiler.scala b/staging/src/scala/quoted/staging/QuoteCompiler.scala index 637d02a5492e..bc0f346b37a8 100644 --- a/staging/src/scala/quoted/staging/QuoteCompiler.scala +++ b/staging/src/scala/quoted/staging/QuoteCompiler.scala @@ -16,7 +16,7 @@ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Types.ExprType import dotty.tools.dotc.quoted.PickledQuotes import dotty.tools.dotc.transform.Splicer.checkEscapedVariables -import dotty.tools.dotc.transform.PickleQuotes +import dotty.tools.dotc.transform.{Inlining, PickleQuotes} import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.util.SourceFile import dotty.tools.io.{Path, VirtualFile} @@ -39,7 +39,9 @@ private class QuoteCompiler extends Compiler: List(List(new QuotedFrontend)) override protected def picklerPhases: List[List[Phase]] = - List(List(new PickleQuotes)) + List(new Inlining) :: + List(new PickleQuotes) :: + Nil override def newRun(implicit ctx: Context): ExprRun = reset() diff --git a/tests/run-staging/i3876-d.check b/tests/run-staging/i3876-d.check index 91dea2c76e75..9bf14ecdde1e 100644 --- a/tests/run-staging/i3876-d.check +++ b/tests/run-staging/i3876-d.check @@ -1,2 +1,2 @@ 6 -6 +Test.inlineLambda.apply(3) diff --git a/tests/disabled/run-staging/i3876-d.scala b/tests/run-staging/i3876-d.scala similarity index 100% rename from tests/disabled/run-staging/i3876-d.scala rename to tests/run-staging/i3876-d.scala diff --git a/tests/run-staging/quote-toExprOfTuple.check b/tests/run-staging/quote-toExprOfTuple.check index f1eef81e4df2..a399c027260a 100644 --- a/tests/run-staging/quote-toExprOfTuple.check +++ b/tests/run-staging/quote-toExprOfTuple.check @@ -21,3 +21,6 @@ (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25) diff --git a/tests/run-staging/quote-toExprOfTuple.scala b/tests/run-staging/quote-toExprOfTuple.scala index 9d4e729367a2..004b576a3d20 100644 --- a/tests/run-staging/quote-toExprOfTuple.scala +++ b/tests/run-staging/quote-toExprOfTuple.scala @@ -5,7 +5,7 @@ import scala.quoted.staging._ object Test { given Toolbox = Toolbox.make(getClass.getClassLoader) def main(args: Array[String]): Unit = { - for (n <- 0 to 22) { // FIXME should go up to 25. This should be fixed in #9984 + for (n <- 0 to 25) { prev = 0 println(run { Expr.ofTupleFromSeq(Seq.fill(n)('{next})) }) }