diff options
author | Paul Phillips <paulp@improving.org> | 2012-03-15 09:28:07 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-03-15 19:59:46 -0700 |
commit | acb2c851720141982514b11b4b34ba68dc868bf2 (patch) | |
tree | c6aa85586f6f673e5975266314cc613a7d36ed05 | |
parent | 2dd0af0675ea0c4d696a46bf36d7bd9406a64cd0 (diff) | |
download | scala-acb2c851720141982514b11b4b34ba68dc868bf2.tar.gz scala-acb2c851720141982514b11b4b34ba68dc868bf2.tar.bz2 scala-acb2c851720141982514b11b4b34ba68dc868bf2.zip |
New option -Ypos-debug, and fixed range position breakage.
(Looks like there is more range position breakage yet, but
this gets the outermost layer.)
Channeling my struggles into a slightly easier future.
% scalac -Ypos-debug -d /tmp ./src/library/scala/Predef.scala
./src/library/scala/Predef.scala:222: warning: Positioned tree has unpositioned child in phase extmethods
def x = __resultOfEnsuring
^
parent: #7109 line 222 Select // (value __resultOfEnsuring in class Ensuring)
child: #7108 Ident // (value $this)
./src/library/scala/Predef.scala:258: warning: Positioned tree has unpositioned child in phase extmethods
def x = __leftOfArrow
^
parent: #7280 line 258 Select // (value __leftOfArrow in class ArrowAssoc)
child: #7279 Ident // (value $this)
two warnings found
Or try this to really see some output:
% scalac -Yrangepos -Ypos-debug
17 files changed, 136 insertions, 75 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index febc2ef330..9678d2b8cd 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -500,8 +500,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR) final def isDerivedValueClass = - isClass && info.parents.headOption.getOrElse(AnyClass.tpe).typeSymbol == AnyValClass && - !isPrimitiveValueClass + isClass && info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass final def isMethodWithExtension = isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 77ea7392a8..9b1712b790 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -283,10 +283,16 @@ trait Trees extends api.Trees { self: SymbolTable => } } - private object posAssigner extends Traverser { + trait PosAssigner extends Traverser { + var pos: Position + } + protected[this] lazy val posAssigner: PosAssigner = new DefaultPosAssigner + + protected class DefaultPosAssigner extends PosAssigner { var pos: Position = _ override def traverse(t: Tree) { - if (t != EmptyTree && t.pos == NoPosition) { + if (t eq EmptyTree) () + else if (t.pos == NoPosition) { t.setPos(pos) super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if? // @PP: it's pruning whenever it encounters a node with a diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index a1d3846557..43c231cf2d 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -16,6 +16,47 @@ import scala.reflect.internal.Flags.TRAIT trait Trees extends reflect.internal.Trees { self: Global => + def treeLine(t: Tree): String = + if (t.pos.isDefined && t.pos.isRange) t.pos.lineContent.drop(t.pos.column - 1).take(t.pos.end - t.pos.start + 1) + else t.summaryString + + def treeStatus(t: Tree, enclosingTree: Tree = null) = { + val parent = if (enclosingTree eq null) " " else " P#%5s".format(enclosingTree.id) + + "[L%4s%8s] #%-6s %-15s %-10s // %s".format(t.pos.safeLine, parent, t.id, t.pos.show, t.shortClass, treeLine(t)) + } + def treeSymStatus(t: Tree) = { + val line = if (t.pos.isDefined) "line %-4s".format(t.pos.safeLine) else " " + "#%-5s %s %-10s // %s".format(t.id, line, t.shortClass, + if (t.symbol ne NoSymbol) "(" + t.symbol.fullLocationString + ")" + else treeLine(t) + ) + } + + class ValidatingPosAssigner extends PosAssigner { + var pos: Position = _ + override def traverse(t: Tree) { + if (t eq EmptyTree) () + else if (t.pos == NoPosition) super.traverse(t setPos pos) + else if (globalPhase.id <= currentRun.picklerPhase.id) { + // 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 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)) + inform(" child: " + treeSymStatus(c) + "\n") + } + } + } + } + } + + override protected[this] lazy val posAssigner: PosAssigner = + if (settings.Yrangepos.value && settings.debug.value || settings.Yposdebug.value) new ValidatingPosAssigner + else new DefaultPosAssigner + // --- additional cases -------------------------------------------------------- /** Only used during parsing */ case class Parens(args: List[Tree]) extends Tree diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index ab6125df61..ccebcfa54d 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -394,7 +394,7 @@ self => // object Main def moduleName = newTermName(ScriptRunner scriptMain settings) - def moduleBody = Template(List(scalaAnyRefConstr), emptyValDef, List(emptyInit, mainDef)) + def moduleBody = Template(List(atPos(o2p(in.offset))(scalaAnyRefConstr)), emptyValDef, List(emptyInit, mainDef)) def moduleDef = ModuleDef(NoMods, moduleName, moduleBody) // package <empty> { ... } @@ -2738,7 +2738,7 @@ self => def anyrefParents() = { val caseParents = if (mods.isCase) List(productConstr, serializableConstr) else Nil parents0 ::: caseParents match { - case Nil => List(scalaAnyRefConstr) + case Nil => List(atPos(o2p(in.offset))(scalaAnyRefConstr)) case ps => ps } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 0d2fbc5372..661f893c59 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -206,7 +206,7 @@ abstract class TreeBuilder { 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, argss, npos, cpos) + makeNew(List(atPos(npos union cpos)(scalaAnyRefConstr)), self, stats, argss, npos, cpos) else if (parents.tail.isEmpty && stats.isEmpty) atPos(npos union cpos) { New(parents.head, argss) } else { diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index d1f738a435..d08a363a9d 100644 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -168,7 +168,7 @@ self: scala.tools.nsc.Global => /** Position a tree. * This means: Set position of a node and position all its unpositioned children. */ - override def atPos[T <: Tree](pos: Position)(tree: T): T = + override def atPos[T <: Tree](pos: Position)(tree: T): T = { if (pos.isOpaqueRange) { if (!tree.isEmpty && tree.pos == NoPosition) { tree.setPos(pos) @@ -182,6 +182,7 @@ self: scala.tools.nsc.Global => } else { super.atPos(pos)(tree) } + } // ---------------- Validating positions ---------------------------------- @@ -190,26 +191,33 @@ self: scala.tools.nsc.Global => val source = if (tree.pos.isDefined) tree.pos.source else "" inform("== "+prefix+" tree ["+tree.id+"] of type "+tree.productPrefix+" at "+tree.pos.show+source) inform("") - inform(tree.toString) + inform(treeStatus(tree)) inform("") } def positionError(msg: String)(body : => Unit) { - inform("======= Bad positions: "+msg) - inform("") + inform("======= Position error\n" + msg) body - inform("=== While validating") - inform("") - inform(tree.toString) - inform("") + inform("\nWhile validating #" + tree.id) + inform(treeStatus(tree)) + inform("\nChildren:") + tree.children map (t => " " + treeStatus(t, tree)) foreach inform inform("=======") throw new ValidateException(msg) } def validate(tree: Tree, encltree: Tree): Unit = { + if (!tree.isEmpty) { + if (settings.Yposdebug.value && (settings.verbose.value || settings.Yrangepos.value)) + println("[%10s] %s".format("validate", treeStatus(tree, encltree))) + if (!tree.pos.isDefined) - positionError("Unpositioned tree ["+tree.id+"]") { reportTree("Unpositioned", tree) } + positionError("Unpositioned tree #"+tree.id) { + inform("%15s %s".format("unpositioned", treeStatus(tree, encltree))) + inform("%15s %s".format("enclosing", treeStatus(encltree))) + encltree.children foreach (t => inform("%15s %s".format("sibling", treeStatus(t, encltree)))) + } if (tree.pos.isRange) { if (!encltree.pos.isRange) positionError("Synthetic tree ["+encltree.id+"] contains nonsynthetic tree ["+tree.id+"]") { diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index e949cb3eb2..5f3c7ec32c 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -162,6 +162,7 @@ trait ScalaSettings extends AbsScalaSettings val Ybuildmanagerdebug = BooleanSetting ("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.") val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignments.") + val Yposdebug = BooleanSetting ("-Ypos-debug", "Trace position validation.") val Yinferdebug = BooleanSetting ("-Yinfer-debug", "Trace type inference and implicit search.") val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.") val Yreifycopypaste = diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 555d0700ae..39e2cbe694 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -264,11 +264,10 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => else DefDef(clazz.primaryConstructor, Block(List(), Literal(Constant()))) :: stats private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos) { - val templ1 = atPos(templ.pos) { - Template(templ.parents, emptyValDef, - addMixinConstructorDef(clazz, templ.body map implMemberDef)) - .setSymbol(clazz.newLocalDummy(templ.pos)) - } + val templ1 = ( + Template(templ.parents, emptyValDef, addMixinConstructorDef(clazz, templ.body map implMemberDef)) + setSymbol clazz.newLocalDummy(templ.pos) + ) templ1.changeOwner(templ.symbol.owner -> clazz, templ.symbol -> templ1.symbol) templ1 } diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index e6ad7cb922..4c3972519a 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -105,7 +105,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { } else if (currentOwner.isStaticOwner) { super.transform(tree) } else tree - case DefDef(mods, name, tparams, vparamss, tpt, rhs) if tree.symbol.isMethodWithExtension => + case DefDef(_, _, tparams, vparamss, _, rhs) if tree.symbol.isMethodWithExtension => val companion = currentOwner.companionModule val origMeth = tree.symbol val extensionName = extensionNames(origMeth).head @@ -132,15 +132,13 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { gen.mkTypeApply(gen.mkAttributedRef(companion), extensionMeth, origTpeParams map (_.tpe)), List(This(currentOwner))) val extensionCall = atOwner(origMeth) { - localTyper.typed { - atPos(rhs.pos) { - (extensionCallPrefix /: vparamss) { - case (fn, params) => Apply(fn, params map (param => Ident(param.symbol))) - } + localTyper.typedPos(rhs.pos) { + (extensionCallPrefix /: vparamss) { + case (fn, params) => Apply(fn, params map (param => Ident(param.symbol))) } } } - treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, extensionCall) + deriveDefDef(tree)(_ => extensionCall) case _ => super.transform(tree) } @@ -148,14 +146,12 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = super.transformStats(stats, exprOwner) map { - case stat @ ModuleDef(mods, name, tmpl @ Template(parents, self, body)) => - extensionDefs.remove(stat.symbol) match { - case Some(buf) => - val extensionDefs = buf.toList map { mdef => atOwner(stat.symbol) { localTyper.typed(mdef) } } - treeCopy.ModuleDef(stat, mods, name, treeCopy.Template(tmpl, parents, self, body ++ extensionDefs)) - case None => - stat - } + case md @ ModuleDef(_, _, _) if extensionDefs contains md.symbol => + val defns = extensionDefs(md.symbol).toList map (member => + atOwner(md.symbol)(localTyper.typedPos(md.pos.focus)(member)) + ) + extensionDefs -= md.symbol + deriveModuleDef(md)(tmpl => deriveTemplate(tmpl)(_ ++ defns)) case stat => stat } diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 088a56cd7b..f32ad9293c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -69,6 +69,9 @@ trait MethodSynthesis { import synthesisUtil._ class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) { + def mkThis = This(clazz) setPos clazz.pos.focus + def mkThisSelect(sym: Symbol) = atPos(clazz.pos.focus)(Select(mkThis, sym)) + private def isOverride(name: TermName) = clazzMember(name).alternatives exists (sym => !sym.isDeferred && (sym.owner != clazz)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 955d51bf8d..c5fb13a5a9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -456,7 +456,7 @@ trait Namers extends MethodSynthesis { // The object Foo is still in scope, but because it is not compiled in current run // it should be ditched and a new one created. if (m != NoSymbol && currentRun.compiles(m)) m - else enterSyntheticSym(creator(cdef)) + else enterSyntheticSym(atPos(cdef.pos.focus)(creator(cdef))) } private def checkSelectors(tree: Import): Unit = { @@ -1270,11 +1270,12 @@ trait Namers extends MethodSynthesis { if (sym.isModule) annotate(sym.moduleClass) def getSig = tree match { - case cdef @ ClassDef(_, _, tparams, impl) => + case cdef @ ClassDef(_, name, tparams, impl) => val clazz = tree.symbol val result = createNamer(tree).classSig(tparams, impl) clazz setInfo result if (clazz.isDerivedValueClass) { + log("Ensuring companion for derived value class " + name + " at " + cdef.pos.show) clazz setFlag FINAL enclosingNamerWithScope(clazz.owner.info.decls).ensureCompanionObject(cdef) } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 1e17cb2e3f..ec42d251ff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1523,16 +1523,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R case _ => () } - // verify classes extending AnyVal meet the requirements - // (whatever those are to be, but at least: @inline annotation) + // Verify classes extending AnyVal meet the requirements private def checkAnyValSubclass(clazz: Symbol) = { - if ((clazz isSubClass AnyValClass) && (clazz ne AnyValClass) && !isPrimitiveValueClass(clazz)) { + if ((clazz isSubClass AnyValClass) && !isPrimitiveValueClass(clazz)) { if (clazz.isTrait) unit.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") - /* [Martin] That one is already taken care of by Typers - if (clazz.tpe <:< AnyRefClass.tpe) - unit.error(clazz.pos, "Classes which extend AnyVal may not have an ancestor which inherits AnyRef") - */ } } diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index f9d41bcc5e..2f4eff30d2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -51,11 +51,9 @@ trait SyntheticMethods extends ast.TreeDSL { if (clazz0 == AnyValClass || isPrimitiveValueClass(clazz0)) return { if (clazz0.info member nme.getClass_ isDeferred) { - val getClassMethod = createMethod(nme.getClass_, getClassReturnType(clazz.tpe)) { sym => - // XXX dummy implementation for now - NULL - } - treeCopy.Template(templ, templ.parents, templ.self, templ.body :+ getClassMethod) + // XXX dummy implementation for now + val getClassMethod = createMethod(nme.getClass_, getClassReturnType(clazz.tpe))(_ => NULL) + deriveTemplate(templ)(_ :+ getClassMethod) } else templ } @@ -89,7 +87,7 @@ trait SyntheticMethods extends ast.TreeDSL { ) def forwardToRuntime(method: Symbol): Tree = - forwardMethod(method, getMember(ScalaRunTimeModule, method.name prepend "_"))(This(clazz) :: _) + forwardMethod(method, getMember(ScalaRunTimeModule, method.name prepend "_"))(mkThis :: _) // Any member, including private def hasConcreteImpl(name: Name) = @@ -109,7 +107,7 @@ trait SyntheticMethods extends ast.TreeDSL { } def productIteratorMethod = { createMethod(nme.productIterator, iteratorOfType(accessorLub))(_ => - gen.mkMethodCall(ScalaRunTimeModule, nme.typedProductIterator, List(accessorLub), List(This(clazz))) + gen.mkMethodCall(ScalaRunTimeModule, nme.typedProductIterator, List(accessorLub), List(mkThis)) ) } def projectionMethod(accessor: Symbol, num: Int) = { @@ -157,8 +155,8 @@ trait SyntheticMethods extends ast.TreeDSL { def equalsCore(eqmeth: Symbol, accessors: List[Symbol]) = { val otherName = context.unit.freshTermName(clazz.name + "$") val otherSym = eqmeth.newValue(otherName, eqmeth.pos, SYNTHETIC) setInfo clazz.tpe - val pairwise = accessors map (acc => fn(Select(This(clazz), acc), acc.tpe member nme.EQ, Select(Ident(otherSym), acc))) - val canEq = gen.mkMethodCall(otherSym, nme.canEqual_, Nil, List(This(clazz))) + val pairwise = accessors map (acc => fn(Select(mkThis, acc), acc.tpe member nme.EQ, Select(Ident(otherSym), acc))) + val canEq = gen.mkMethodCall(otherSym, nme.canEqual_, Nil, List(mkThis)) val tests = if (clazz.isDerivedValueClass || clazz.isFinal && syntheticCanEqual) pairwise else pairwise :+ canEq thatTest(eqmeth) AND Block( @@ -181,9 +179,9 @@ trait SyntheticMethods extends ast.TreeDSL { def equalsCaseClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => if (accessors.isEmpty) if (clazz.isFinal) thatTest(m) - else thatTest(m) AND ((thatCast(m) DOT nme.canEqual_)(This(clazz))) + else thatTest(m) AND ((thatCast(m) DOT nme.canEqual_)(mkThis)) else - (This(clazz) ANY_EQ Ident(m.firstParam)) OR equalsCore(m, accessors) + (mkThis ANY_EQ Ident(m.firstParam)) OR equalsCore(m, accessors) } /** The equality method for value classes @@ -200,9 +198,7 @@ trait SyntheticMethods extends ast.TreeDSL { * def hashCode(): Int = this.underlying.hashCode */ def hashCodeDerivedValueClassMethod: Tree = createMethod(nme.hashCode_, Nil, IntClass.tpe) { m => - Select( - Select(This(clazz), clazz.firstParamAccessor), - nme.hashCode_) + Select(mkThisSelect(clazz.firstParamAccessor), nme.hashCode_) } /** The _1, _2, etc. methods to implement ProductN. @@ -217,7 +213,7 @@ trait SyntheticMethods extends ast.TreeDSL { List( Product_productPrefix -> (() => constantNullary(nme.productPrefix, clazz.name.decode)), Product_productArity -> (() => constantNullary(nme.productArity, arity)), - Product_productElement -> (() => perElementMethod(nme.productElement, accessorLub)(Select(This(clazz), _))), + Product_productElement -> (() => perElementMethod(nme.productElement, accessorLub)(mkThisSelect)), Product_iterator -> (() => productIteratorMethod), Product_canEqual -> (() => canEqualMethod) // This is disabled pending a reimplementation which doesn't add any diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9a2ef88821..973e26af41 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1295,7 +1295,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } def parentTypes(templ: Template): List[Tree] = - if (templ.parents.isEmpty) List(TypeTree(AnyRefClass.tpe)) + if (templ.parents.isEmpty) List(atPos(templ.pos.focus)(TypeTree(AnyRefClass.tpe))) else try { val clazz = context.owner // Normalize supertype and mixins so that supertype is always a class, not a trait. @@ -1723,7 +1723,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { * @param rhs ... */ def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) { - debuglog("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug + log("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug def decompose(call: Tree): (Tree, List[Tree]) = call match { case Apply(fn, args) => val (superConstr, args1) = decompose(fn) @@ -1902,11 +1902,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe) } - if (meth.isPrimaryConstructor && meth.isClassConstructor && !isPastTyper && !reporter.hasErrors && !meth.owner.isSubClass(AnyValClass)) { - // At this point in AnyVal there is no supercall, which will blow up - // in computeParamAliases; there's nothing to be computed for Anyval anyway. - computeParamAliases(meth.owner, vparamss1, rhs1) - } + if (meth.isPrimaryConstructor && meth.isClassConstructor && !isPastTyper && !reporter.hasErrors && !meth.owner.isSubClass(AnyValClass)) { + // At this point in AnyVal there is no supercall, which will blow up + // in computeParamAliases; there's nothing to be computed for Anyval anyway. + computeParamAliases(meth.owner, vparamss1, rhs1) + } + if (tpt1.tpe.typeSymbol != NothingClass && !context.returnsSeen && rhs1.tpe.typeSymbol != NothingClass) rhs1 = checkDead(rhs1) @@ -1925,6 +1926,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } if (meth.isStructuralRefinementMember) checkMethodStructuralCompatible(meth) + treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType } @@ -3264,6 +3266,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } def typedAnnotated(ann: Tree, arg1: Tree): Tree = { + def mkTypeTree(tpe: Type) = TypeTree(tpe) setOriginal tree setPos tree.pos.focus /** mode for typing the annotation itself */ val annotMode = mode & ~TYPEmode | EXPRmode @@ -3309,19 +3312,20 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { arg1 // simply drop erroneous annotations else { ann.tpe = atype - TypeTree(atype) setOriginal tree + mkTypeTree(atype) } } else { // the annotation was typechecked before - TypeTree(ann.tpe) setOriginal tree + mkTypeTree(ann.tpe) } - } else { + } + else { if (ann.tpe == null) { val annotInfo = typedAnnotation(ann, annotMode) ann.tpe = arg1.tpe.withAnnotation(annotInfo) } val atype = ann.tpe - Typed(arg1, TypeTree(atype) setOriginal tree setPos tree.pos.focus) setPos tree.pos setType atype + Typed(arg1, mkTypeTree(atype)) setPos tree.pos setType atype } } diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 181ce85dac..a355207ff0 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -309,7 +309,7 @@ trait Trees { self: Universe => * quite frequently called modules to reduce ambiguity. */ case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) - extends ImplDef + extends ImplDef /** A common base class for ValDefs and DefDefs. */ @@ -319,8 +319,13 @@ trait Trees { self: Universe => def rhs: Tree } - /** A value definition (this includes vars as well, which differ from - * vals only in having the MUTABLE flag set in their Modifiers.) + /** Broadly speaking, a value definition. All these are encoded as ValDefs: + * + * - immutable values, e.g. "val x" + * - mutable values, e.g. "var x" - the MUTABLE flag set in mods + * - lazy values, e.g. "lazy val x" - the LAZY flag set in mods + * - method parameters, see vparamss in DefDef - the PARAM flag is set in mods + * - explicit self-types, e.g. class A { self: Bar => } - !!! not sure what is set. */ case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef @@ -390,7 +395,6 @@ trait Trees { self: Universe => // { // def bar // owner is local dummy // } - // System.err.println("TEMPLATE: " + parents) } /** Block of expressions (semicolon separated expressions) */ @@ -741,6 +745,12 @@ trait Trees { self: Universe => case t => sys.error("Not a ClassDef: " + t + "/" + t.getClass) } + def deriveModuleDef(mdef: Tree)(applyToImpl: Template => Template): ModuleDef = mdef match { + case ModuleDef(mods0, name0, impl0) => + treeCopy.ModuleDef(mdef, mods0, name0, applyToImpl(impl0)) + case t => + sys.error("Not a ModuleDef: " + t + "/" + t.getClass) + } def deriveCaseDef(cdef: Tree)(applyToBody: Tree => Tree): CaseDef = cdef match { case CaseDef(pat0, guard0, body0) => treeCopy.CaseDef(cdef, pat0, guard0, applyToBody(body0)) diff --git a/test/files/pos/anyval-rangepos.flags b/test/files/pos/anyval-rangepos.flags new file mode 100644 index 0000000000..fcf951d907 --- /dev/null +++ b/test/files/pos/anyval-rangepos.flags @@ -0,0 +1 @@ +-Yrangepos
\ No newline at end of file diff --git a/test/files/pos/anyval-rangepos.scala b/test/files/pos/anyval-rangepos.scala new file mode 100644 index 0000000000..8d79793c0d --- /dev/null +++ b/test/files/pos/anyval-rangepos.scala @@ -0,0 +1 @@ +class Foo(val x: Double) extends AnyVal { } |