Skip to content

Fix #5152: Use context of the target location #5153

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

Merged
merged 2 commits into from
Sep 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
if (ctx.compilationUnit.containsQuotesOrSplices) super.run

protected def newTransformer(implicit ctx: Context): Transformer =
new Reifier(inQuote = false, null, 0, new LevelInfo, new mutable.ListBuffer[Tree])
new Reifier(inQuote = false, null, 0, new LevelInfo, new mutable.ListBuffer, ctx)

private class LevelInfo {
/** A map from locally defined symbols to the staging levels of their definitions */
Expand Down Expand Up @@ -120,16 +120,17 @@ class ReifyQuotes extends MacroTransformWithImplicits {
* and `l == -1` is code inside a top level splice (in an inline method).
* @param levels a stacked map from symbols to the levels in which they were defined
* @param embedded a list of embedded quotes (if `inSplice = true`) or splices (if `inQuote = true`
* @param rctx the contex in the destination lifted lambda
*/
private class Reifier(inQuote: Boolean, val outer: Reifier, val level: Int, levels: LevelInfo,
val embedded: mutable.ListBuffer[Tree]) extends ImplicitsTransformer {
val embedded: mutable.ListBuffer[Tree], val rctx: Context) extends ImplicitsTransformer {
import levels._
assert(level >= -1)

/** A nested reifier for a quote (if `isQuote = true`) or a splice (if not) */
def nested(isQuote: Boolean): Reifier = {
def nested(isQuote: Boolean)(implicit ctx: Context): Reifier = {
val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new mutable.ListBuffer[Tree]
new Reifier(isQuote, this, if (isQuote) level + 1 else level - 1, levels, nestedEmbedded)
new Reifier(isQuote, this, if (isQuote) level + 1 else level - 1, levels, nestedEmbedded, ctx)
}

/** We are in a `~(...)` context that is not shadowed by a nested `'(...)` */
Expand Down Expand Up @@ -493,8 +494,12 @@ class ReifyQuotes extends MacroTransformWithImplicits {
}
)
}
/* Lambdas are generated outside the quote that is beeing reified (i.e. in outer.rctx.owner).
* In case the case that level == -1 the code is not in a quote, it is in an inline method,
* hence we should take that as owner directly.
*/
val lambdaOwner = if (level == -1) ctx.owner else outer.rctx.owner

val lambdaOwner = ctx.owner.ownersIterator.find(o => levelOf.getOrElse(o, level) == level).get
val tpe = MethodType(defn.SeqType.appliedTo(defn.AnyType) :: Nil, tree.tpe.widen)
val meth = ctx.newSymbol(lambdaOwner, UniqueName.fresh(nme.ANON_FUN), Synthetic | Method, tpe)
Closure(meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth))
Expand Down
4 changes: 4 additions & 0 deletions tests/run-with-compiler/i5152.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
lazy val f: scala.Function1[scala.Int, scala.Int] = ((x: scala.Int) => scala.Predef.identity[scala.Int](x))
()
}
17 changes: 17 additions & 0 deletions tests/run-with-compiler/i5152.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import scala.quoted._

object Test {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make

def eval1(ff: Expr[Int => Int]): Expr[Int => Int] = '(identity)

def peval1(): Expr[Unit] = '{
lazy val f: Int => Int = ~eval1('((y: Int) => f(y)))
}

def main(args: Array[String]): Unit = {
val p = peval1()
println(p.show)
}

}