Skip to content
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

[nomaster] SI-7064 Reflection: forward compat for 2.10.1 #2068

Merged
merged 9 commits into from Feb 7, 2013
4 changes: 1 addition & 3 deletions src/compiler/scala/reflect/reify/codegen/GenTrees.scala
Expand Up @@ -45,9 +45,7 @@ trait GenTrees {
case global.EmptyTree =>
reifyMirrorObject(EmptyTree)
case global.emptyValDef =>
mirrorSelect(nme.emptyValDef)
case global.pendingSuperCall =>
mirrorSelect(nme.pendingSuperCall)
mirrorBuildSelect(nme.emptyValDef)
case FreeDef(_, _, _, _, _) =>
reifyNestedFreeDef(tree)
case FreeRef(_, _) =>
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/scala/reflect/reify/codegen/GenUtils.scala
Expand Up @@ -34,6 +34,9 @@ trait GenUtils {
def mirrorSelect(name: String): Tree =
termPath(nme.UNIVERSE_PREFIX + name)

def mirrorBuildSelect(name: String): Tree =
termPath(nme.UNIVERSE_BUILD_PREFIX + name)

def mirrorMirrorSelect(name: String): Tree =
termPath(nme.MIRROR_PREFIX + name)

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/ast/Positions.scala
Expand Up @@ -20,7 +20,7 @@ trait Positions extends scala.reflect.internal.Positions {
// When we prune due to encountering a position, traverse the
// pruned children so we can warn about those lacking positions.
t.children foreach { c =>
if (!c.canHaveAttrs) ()
if ((c eq EmptyTree) || (c eq emptyValDef)) ()
else if (c.pos == NoPosition) {
reporter.warning(t.pos, " Positioned tree has unpositioned child in phase " + globalPhase)
inform("parent: " + treeSymStatus(t))
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/ast/TreeGen.scala
Expand Up @@ -58,7 +58,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
def mkUnchecked(expr: Tree): Tree = atPos(expr.pos) {
// This can't be "Annotated(New(UncheckedClass), expr)" because annotations
// are very picky about things and it crashes the compiler with "unexpected new".
Annotated(New(scalaDot(UncheckedClass.name), Nil), expr)
Annotated(New(scalaDot(UncheckedClass.name), ListOfNil), expr)
}
// if it's a Match, mark the selector unchecked; otherwise nothing.
def mkUncheckedMatch(tree: Tree) = tree match {
Expand Down
29 changes: 8 additions & 21 deletions src/compiler/scala/tools/nsc/ast/Trees.scala
Expand Up @@ -65,13 +65,6 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>

// --- factory methods ----------------------------------------------------------

/** Factory method for a primary constructor super call `super.<init>(args_1)...(args_n)`
*/
def PrimarySuperCall(argss: List[List[Tree]]): Tree = argss match {
case Nil => Apply(gen.mkSuperSelect, Nil)
case xs :: rest => rest.foldLeft(Apply(gen.mkSuperSelect, xs): Tree)(Apply.apply)
}

/** Generates a template with constructor corresponding to
*
* constrmods (vparams1_) ... (vparams_n) preSuper { presupers }
Expand All @@ -89,7 +82,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
* body
* }
*/
def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): Template = {
def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): Template = {
/* Add constructor to template */

// create parameters for <init> as synthetic trees.
Expand Down Expand Up @@ -124,16 +117,9 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit)
vparamss1 = List() :: vparamss1;
val superRef: Tree = atPos(superPos)(gen.mkSuperSelect)
val superCall = pendingSuperCall // we can't know in advance which of the parents will end up as a superclass
// this requires knowing which of the parents is a type macro and which is not
// and that's something that cannot be found out before typer
// (the type macros aren't in the trunk yet, but there is a plan for them to land there soon)
// this means that we don't know what will be the arguments of the super call
// therefore here we emit a dummy which gets populated when the template is named and typechecked
val superCall = (superRef /: argss) (Apply.apply)
List(
// TODO: previously this was `wrappingPos(superPos, lvdefs ::: argss.flatten)`
// is it going to be a problem that we can no longer include the `argss`?
atPos(wrappingPos(superPos, lvdefs)) (
atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) (
DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant())))))
}
}
Expand All @@ -151,10 +137,11 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
* @param constrMods the modifiers for the class constructor, i.e. as in `class C private (...)`
* @param vparamss the value parameters -- if they have symbols they
* should be owned by `sym`
* @param argss the supercall arguments
* @param body the template statements without primary constructor
* and value parameter fields.
*/
def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): ClassDef = {
def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef = {
// "if they have symbols they should be owned by `sym`"
assert(
mforall(vparamss)(p => (p.symbol eq NoSymbol) || (p.symbol.owner == sym)),
Expand All @@ -164,7 +151,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
ClassDef(sym,
Template(sym.info.parents map TypeTree,
if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
constrMods, vparamss, body, superPos))
constrMods, vparamss, argss, body, superPos))
}

// --- subcomponents --------------------------------------------------
Expand Down Expand Up @@ -337,8 +324,6 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
else
super.transform {
tree match {
case tree if !tree.canHaveAttrs =>
tree
case tpt: TypeTree =>
if (tpt.original != null)
transform(tpt.original)
Expand All @@ -352,6 +337,8 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
transform(fn)
case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
tree
case EmptyTree =>
tree
case _ =>
val dupl = tree.duplicate
if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel))
Expand Down
66 changes: 34 additions & 32 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -1559,9 +1559,9 @@ self =>
val nstart = in.skipToken()
val npos = r2p(nstart, nstart, in.lastOffset)
val tstart = in.offset
val (parents, self, stats) = template()
val (parents, argss, self, stats) = template(isTrait = false)
val cpos = r2p(tstart, tstart, in.lastOffset max tstart)
makeNew(parents, self, stats, npos, cpos)
makeNew(parents, self, stats, argss, npos, cpos)
case _ =>
syntaxErrorOrIncomplete("illegal start of simple expression", true)
errorTermTree
Expand Down Expand Up @@ -2103,7 +2103,7 @@ self =>
def annotationExpr(): Tree = atPos(in.offset) {
val t = exprSimpleType()
if (in.token == LPAREN) New(t, multipleArgumentExprs())
else New(t, Nil)
else New(t, ListOfNil)
}

/* -------- PARAMETERS ------------------------------------------- */
Expand Down Expand Up @@ -2739,17 +2739,20 @@ self =>
* TraitParents ::= AnnotType {with AnnotType}
* }}}
*/
def templateParents(): List[Tree] = {
val parents = new ListBuffer[Tree]
def readAppliedParent() = {
val start = in.offset
val parent = startAnnotType()
val argss = if (in.token == LPAREN) multipleArgumentExprs() else Nil
parents += atPos(start)((parent /: argss)(Apply.apply))
def templateParents(isTrait: Boolean): (List[Tree], List[List[Tree]]) = {
val parents = new ListBuffer[Tree] += startAnnotType()
val argss = (
// TODO: the insertion of ListOfNil here is where "new Foo" becomes
// indistinguishable from "new Foo()".
if (in.token == LPAREN && !isTrait) multipleArgumentExprs()
else ListOfNil
)

while (in.token == WITH) {
in.nextToken()
parents += startAnnotType()
}
readAppliedParent()
while (in.token == WITH) { in.nextToken(); readAppliedParent() }
parents.toList
(parents.toList, argss)
}

/** {{{
Expand All @@ -2759,12 +2762,12 @@ self =>
* EarlyDef ::= Annotations Modifiers PatDef
* }}}
*/
def template(): (List[Tree], ValDef, List[Tree]) = {
def template(isTrait: Boolean): (List[Tree], List[List[Tree]], ValDef, List[Tree]) = {
newLineOptWhenFollowedBy(LBRACE)
if (in.token == LBRACE) {
// @S: pre template body cannot stub like post body can!
val (self, body) = templateBody(isPre = true)
if (in.token == WITH && (self eq emptyValDef)) {
if (in.token == WITH && self.isEmpty) {
val earlyDefs: List[Tree] = body flatMap {
case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred =>
List(copyValDef(vdef)(mods = mods | Flags.PRESUPER))
Expand All @@ -2776,16 +2779,16 @@ self =>
case _ => List()
}
in.nextToken()
val parents = templateParents()
val (self1, body1) = templateBodyOpt(parenMeansSyntaxError = false)
(parents, self1, earlyDefs ::: body1)
val (parents, argss) = templateParents(isTrait = isTrait)
val (self1, body1) = templateBodyOpt(traitParentSeen = isTrait)
(parents, argss, self1, earlyDefs ::: body1)
} else {
(List(), self, body)
(List(), ListOfNil, self, body)
}
} else {
val parents = templateParents()
val (self, body) = templateBodyOpt(parenMeansSyntaxError = false)
(parents, self, body)
val (parents, argss) = templateParents(isTrait = isTrait)
val (self, body) = templateBodyOpt(traitParentSeen = isTrait)
(parents, argss, self, body)
}
}

Expand All @@ -2799,15 +2802,15 @@ self =>
* }}}
*/
def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]], tstart: Int): Template = {
val (parents0, self, body) = (
val (parents0, argss, self, body) = (
if (in.token == EXTENDS || in.token == SUBTYPE && mods.isTrait) {
in.nextToken()
template()
template(isTrait = mods.isTrait)
}
else {
newLineOptWhenFollowedBy(LBRACE)
val (self, body) = templateBodyOpt(parenMeansSyntaxError = mods.isTrait || name.isTermName)
(List(), self, body)
val (self, body) = templateBodyOpt(traitParentSeen = false)
(List(), ListOfNil, self, body)
}
)
def anyrefParents() = {
Expand All @@ -2829,7 +2832,7 @@ self =>
if (inScalaRootPackage && ScalaValueClassNames.contains(name))
Template(parents0, self, anyvalConstructor :: body)
else
Template(anyrefParents, self, constrMods, vparamss, body, o2p(tstart))
Template(anyrefParents, self, constrMods, vparamss, argss, body, o2p(tstart))
}
}

Expand All @@ -2844,15 +2847,14 @@ self =>
case (self, Nil) => (self, EmptyTree.asList)
case result => result
}
def templateBodyOpt(parenMeansSyntaxError: Boolean): (ValDef, List[Tree]) = {
def templateBodyOpt(traitParentSeen: Boolean): (ValDef, List[Tree]) = {
newLineOptWhenFollowedBy(LBRACE)
if (in.token == LBRACE) {
templateBody(isPre = false)
} else {
if (in.token == LPAREN) {
if (parenMeansSyntaxError) syntaxError(s"traits or objects may not have parameters", true)
else abort("unexpected opening parenthesis")
}
if (in.token == LPAREN)
syntaxError((if (traitParentSeen) "parents of traits" else "traits or objects")+
" may not have parameters", true)
(emptyValDef, List())
}
}
Expand Down
22 changes: 8 additions & 14 deletions src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
Expand Up @@ -205,39 +205,33 @@ abstract class TreeBuilder {
*/
def makeAnonymousNew(stats: List[Tree]): Tree = {
val stats1 = if (stats.isEmpty) List(Literal(Constant(()))) else stats
makeNew(Nil, emptyValDef, stats1, NoPosition, NoPosition)
makeNew(Nil, emptyValDef, stats1, ListOfNil, NoPosition, NoPosition)
}

/** Create positioned tree representing an object creation <new parents { stats }
* @param npos the position of the new
* @param cpos the position of the anonymous class starting with parents
*/
def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree],
def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]],
npos: Position, cpos: Position): Tree =
if (parents.isEmpty)
makeNew(List(scalaAnyRefConstr), self, stats, npos, cpos)
else if (parents.tail.isEmpty && stats.isEmpty) {
// `Parsers.template` no longer differentiates tpts and their argss
// e.g. `C()` will be represented as a single tree Apply(Ident(C), Nil)
// instead of parents = Ident(C), argss = Nil as before
// this change works great for things that are actually templates
// but in this degenerate case we need to perform postprocessing
val app = treeInfo.dissectApplied(parents.head)
atPos(npos union cpos) { New(app.callee, app.argss) }
} else {
makeNew(List(scalaAnyRefConstr), self, stats, argss, npos, cpos)
else if (parents.tail.isEmpty && stats.isEmpty)
atPos(npos union cpos) { New(parents.head, argss) }
else {
val x = tpnme.ANON_CLASS_NAME
atPos(npos union cpos) {
Block(
List(
atPos(cpos) {
ClassDef(
Modifiers(FINAL), x, Nil,
Template(parents, self, NoMods, ListOfNil, stats, cpos.focus))
Template(parents, self, NoMods, ListOfNil, argss, stats, cpos.focus))
}),
atPos(npos) {
New(
Ident(x) setPos npos.focus,
Nil)
ListOfNil)
}
)
}
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/scala/tools/nsc/interactive/RangePositions.scala
Expand Up @@ -144,7 +144,7 @@ self: scala.tools.nsc.Global =>
*/
private def setChildrenPos(pos: Position, trees: List[Tree]): Unit = try {
for (tree <- trees) {
if (!tree.isEmpty && tree.canHaveAttrs && tree.pos == NoPosition) {
if (!tree.isEmpty && tree.pos == NoPosition) {
val children = tree.children
if (children.isEmpty) {
tree setPos pos.focus
Expand All @@ -165,7 +165,7 @@ self: scala.tools.nsc.Global =>
*/
override def atPos[T <: Tree](pos: Position)(tree: T): T = {
if (pos.isOpaqueRange) {
if (!tree.isEmpty && tree.canHaveAttrs && tree.pos == NoPosition) {
if (!tree.isEmpty && tree.pos == NoPosition) {
tree.setPos(pos)
val children = tree.children
if (children.nonEmpty) {
Expand Down Expand Up @@ -203,7 +203,7 @@ self: scala.tools.nsc.Global =>

def validate(tree: Tree, encltree: Tree): Unit = {

if (!tree.isEmpty && tree.canHaveAttrs) {
if (!tree.isEmpty) {
if (settings.Yposdebug.value && (settings.verbose.value || settings.Yrangepos.value))
println("[%10s] %s".format("validate", treeStatus(tree, encltree)))

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/javac/JavaParsers.scala
Expand Up @@ -551,7 +551,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
if (parentToken == AT && in.token == DEFAULT) {
val annot =
atPos(pos) {
New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), Nil)
New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), ListOfNil)
}
mods1 = mods1 withAnnotations List(annot)
skipTo(SEMI)
Expand Down
1 change: 1 addition & 0 deletions src/compiler/scala/tools/nsc/transform/Constructors.scala
Expand Up @@ -511,6 +511,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
sym = closureClass,
constrMods = Modifiers(0),
vparamss = List(List(outerFieldDef)),
argss = ListOfNil,
body = List(applyMethodDef),
superPos = impl.pos)
}
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/scala/tools/nsc/transform/UnCurry.scala
Expand Up @@ -277,7 +277,7 @@ abstract class UnCurry extends InfoTransform

localTyper.typedPos(fun.pos) {
Block(
List(ClassDef(anonClass, NoMods, ListOfNil, List(applyMethodDef), fun.pos)),
List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, List(applyMethodDef), fun.pos)),
Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
}

Expand Down Expand Up @@ -403,7 +403,7 @@ abstract class UnCurry extends InfoTransform

localTyper.typedPos(fun.pos) {
Block(
List(ClassDef(anonClass, NoMods, ListOfNil, List(applyOrElseMethodDef, isDefinedAtMethodDef), fun.pos)),
List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, List(applyOrElseMethodDef, isDefinedAtMethodDef), fun.pos)),
Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
}
}
Expand Down