Skip to content

Commit

Permalink
Merge pull request #2814 from xeno-by/topic/auto-duplicate-expansions
Browse files Browse the repository at this point in the history
[nomaster] macro expansions are now auto-duplicated
  • Loading branch information
JamesIry committed Aug 16, 2013
2 parents 8053c19 + 75b44a6 commit ab8021f
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 5 deletions.
16 changes: 16 additions & 0 deletions bincompat-backward.whitelist.conf
Original file line number Diff line number Diff line change
Expand Up @@ -252,5 +252,21 @@ filter {
matchName="scala.reflect.internal.Types.uncheckedBounds"
problemName=MissingMethodProblem
}
{
matchName="scala.reflect.internal.Trees.scala$reflect$internal$Trees$$duplicator"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.internal.Trees.duplicateAndKeepPositions"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.internal.Trees.scala$reflect$internal$Trees$$duplicator"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.internal.SymbolTable.scala$reflect$internal$Trees$$duplicator"
problemName=IncompatibleResultTypeProblem
}
]
}
24 changes: 24 additions & 0 deletions bincompat-forward.whitelist.conf
Original file line number Diff line number Diff line change
Expand Up @@ -548,5 +548,29 @@ filter {
matchName="scala.reflect.internal.annotations.uncheckedBounds"
problemName=MissingClassProblem
}
{
matchName="scala.reflect.internal.Trees$Duplicator"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.internal.Trees.duplicateAndKeepPositions"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.internal.Trees.scala$reflect$internal$Trees$$duplicator"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.internal.Trees.scala$reflect$internal$Trees$$duplicator"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.internal.SymbolTable.duplicateAndKeepPositions"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.internal.SymbolTable.scala$reflect$internal$Trees$$duplicator"
problemName=IncompatibleResultTypeProblem
}
]
}
8 changes: 5 additions & 3 deletions src/compiler/scala/tools/nsc/typechecker/Macros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -713,9 +713,11 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {

var expectedTpe = expandee.tpe
if (isNullaryInvocation(expandee)) expectedTpe = expectedTpe.finalResultType
var typechecked = typecheck("macro def return type", expanded, expectedTpe)
typechecked = typecheck("expected type", typechecked, pt)
typechecked
// also see http://groups.google.com/group/scala-internals/browse_thread/thread/492560d941b315cc
val expanded0 = duplicateAndKeepPositions(expanded)
val expanded1 = typecheck("macro def return type", expanded0, expectedTpe)
val expanded2 = typecheck("expected type", expanded1, pt)
expanded2
} finally {
popMacroContext()
}
Expand Down
7 changes: 5 additions & 2 deletions src/reflect/scala/reflect/internal/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1526,15 +1526,18 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
}

private lazy val duplicator = new Transformer {
private lazy val duplicator = new Duplicator(focusPositions = true)
private class Duplicator(focusPositions: Boolean) extends Transformer {
override val treeCopy = newStrictTreeCopier
override def transform(t: Tree) = {
val t1 = super.transform(t)
if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus
if ((t1 ne t) && t1.pos.isRange && focusPositions) t1 setPos t.pos.focus
t1
}
}

def duplicateAndKeepPositions(tree: Tree) = new Duplicator(focusPositions = false) transform tree

// ------ copiers -------------------------------------------

def copyDefDef(tree: Tree)(
Expand Down
1 change: 1 addition & 0 deletions test/files/run/macro-auto-duplicate.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
42
17 changes: 17 additions & 0 deletions test/files/run/macro-auto-duplicate/Macros_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import scala.reflect.macros.Context
import language.experimental.macros

object Macros {
def impl(c: Context) = {
import c.universe._
val x = Ident(newTermName("x"))
def defAndUseX(rhs: Tree) = {
Block(List(ValDef(NoMods, newTermName("x"), TypeTree(), rhs)), x)
}
val xi4 = defAndUseX(Literal(Constant(4)))
val xs2 = defAndUseX(Literal(Constant("2")))
c.Expr[String](Apply(Select(xi4, newTermName("$plus")), List(xs2)))
}

def foo = macro impl
}
3 changes: 3 additions & 0 deletions test/files/run/macro-auto-duplicate/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object Test extends App {
println(Macros.foo)
}
Empty file.
1 change: 1 addition & 0 deletions test/files/run/macro-duplicate.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-language:experimental.macros
29 changes: 29 additions & 0 deletions test/files/run/macro-duplicate/Impls_Macros_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import scala.reflect.macros.Context

object Macros {
def impl(c: Context) = {
import c.universe._
val Expr(Block((cdef: ClassDef) :: Nil, _)) = reify { class C { def x = 2 } }
val cdef1 =
new Transformer {
override def transform(tree: Tree): Tree = tree match {
case Template(_, _, ctor :: defs) =>
val defs1 = defs collect {
case ddef @ DefDef(mods, name, tparams, vparamss, tpt, body) =>
val future = Select(Select(Select(Ident(newTermName("scala")), newTermName("concurrent")), newTermName("package")), newTermName("future"))
val Future = Select(Select(Ident(newTermName("scala")), newTermName("concurrent")), newTypeName("Future"))
val tpt1 = if (tpt.isEmpty) tpt else AppliedTypeTree(Future, List(tpt))
val body1 = Apply(future, List(body))
val name1 = newTermName("async" + name.toString.capitalize)
DefDef(mods, name1, tparams, vparamss, tpt1, body1)
}
Template(Nil, emptyValDef, ctor +: defs ::: defs1)
case _ =>
super.transform(tree)
}
} transform cdef
c.Expr[Unit](Block(cdef1 :: Nil, Literal(Constant(()))))
}

def foo = macro impl
}
6 changes: 6 additions & 0 deletions test/files/run/macro-duplicate/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import scala.concurrent._
import ExecutionContext.Implicits.global

object Test extends App {
Macros.foo
}

0 comments on commit ab8021f

Please sign in to comment.