summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-09-11 19:49:03 +0000
committerMartin Odersky <odersky@gmail.com>2006-09-11 19:49:03 +0000
commit1237c5202669272825990e0c41803bd39a0846c8 (patch)
tree2583a67e460da54fd23acfeb1887f0e7a47ec51a /src
parent9a8e9075dc345207d1979e703907ce923fff8691 (diff)
downloadscala-1237c5202669272825990e0c41803bd39a0846c8.tar.gz
scala-1237c5202669272825990e0c41803bd39a0846c8.tar.bz2
scala-1237c5202669272825990e0c41803bd39a0846c8.zip
changed explicit outer scheme
repaired tree checkers
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala41
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala21
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala592
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/TypingTransformers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala53
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala24
13 files changed, 389 insertions, 389 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 00d336cc1e..c38f462857 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -337,8 +337,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, newScope))
def phaseDescriptors: List[SubComponent] = List(
- analyzer.namerFactory,
- analyzer.typerFactory,
+ analyzer.namerFactory: SubComponent, // note: types are there because otherwise
+ analyzer.typerFactory: SubComponent, // consistency check after refchecks would fail.
superAccessors,
pickler,
refchecks,
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 64daebb8a7..c69f55da1b 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -144,7 +144,7 @@ abstract class TreePrinters {
printModifiers(tree, mods)
print((if (mods hasFlag TRAIT) "trait " else "class ") + symName(tree, name))
printTypeParams(tparams)
- printOpt("requires ", tp); print(" extends "); print(impl)
+ printOpt(" requires ", tp); print(" extends "); print(impl)
case PackageDef(packaged, stats) =>
printAttributes(tree)
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index d2214148b6..002ffb2ba3 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -85,7 +85,9 @@ trait StdNames requires SymbolTable {
def isSetterName(name: Name) = name.endsWith(SETTER_SUFFIX)
def isLocalDummyName(name: Name) = name.startsWith(LOCALDUMMY_PREFIX)
-// def originalName(name: Name): Name = {
+ /** If `name' is an expandedName, the original name. Otherwise `name' itself.
+ * @see Symbol.expandedName
+ */
def originalName(name: Name): Name = {
var i = name.length;
while (i >= 2 && !(name(i - 1) == '$' && name(i - 2) == '$')) i = i - 1;
@@ -94,10 +96,6 @@ trait StdNames requires SymbolTable {
name.subName(i, name.length)
} else name
}
-// val result = originalName(name)
-// System.out.println("oroginal " + name + " = " + result)
-// result
-// }
def localToGetter(name: Name): Name = {
assert(isLocalName(name))//debug
@@ -192,7 +190,6 @@ trait StdNames requires SymbolTable {
val Function = newTermName("Function")
val Int = newTermName("Int")
val Labelled = newTermName("Labelled")
- val List = newTermName("List")
val Long = newTermName("Long")
val Nil = newTermName("Nil")
val Object = newTermName("Object")
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 7784bd24b8..bd191710bf 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -124,6 +124,15 @@ trait Symbols requires SymbolTable {
.setFlag(OVERLOADED)
.setInfo(OverloadedType(pre, alternatives))
+ final def newOuterAccessor(pos: PositionType) = {
+ val sym = newMethod(pos, nme.OUTER)
+ sym setFlag STABLE
+ if (isTrait) sym setFlag DEFERRED
+ sym.expandName(this)
+ sym.referenced = this
+ sym
+ }
+
final def newErrorValue(name: Name) =
newValue(pos, name).setFlag(SYNTHETIC | IS_ERROR).setInfo(ErrorType)
final def newAliasType(pos: PositionType, name: Name) =
@@ -316,8 +325,12 @@ trait Symbols requires SymbolTable {
def ownerChain: List[Symbol] = this :: owner.ownerChain
def name: Name = rawname
+
final def name_=(name: Name): unit = { rawname = name }
+ /** If this symbol has an expanded name, its original name, otherwise its name itself.
+ * @see expandName
+ */
def originalName = nme.originalName(name)
final def flags = {
@@ -616,10 +629,24 @@ trait Symbols requires SymbolTable {
final def implClass: Symbol = owner.info.decl(nme.implClassName(name))
+ /** The class that is logically an outer class of given `clazz'.
+ * This is the enclosing class, except for classes defined locally to constructors,
+ * where it is the outer class of the enclosing class
+ */
+ final def outerClass: Symbol =
+ if (owner.isClass) owner
+ else if (isClassLocalToConstructor) owner.owner.outerClass
+ else owner.outerClass
+
/** For a paramaccessor: a superclass paramaccessor for which this symbol
* is an alias, NoSymbol for all others */
def alias: Symbol = NoSymbol
+ /** For an outer accessor: The class from which the outer originates.
+ * For all other symbols: NoSymbol
+ */
+ def outerSource: Symbol = NoSymbol
+
/** The superclass of this class */
def superClass: Symbol = if (info.parents.isEmpty) NoSymbol else info.parents.head.symbol
@@ -780,8 +807,10 @@ trait Symbols requires SymbolTable {
/** The expanded name of `name' relative to this class as base
*/
- def expandedName(name: Name): Name =
+ def expandedName(name: Name): Name = {
+
newTermName(fullNameString('$') + nme.EXPAND_SEPARATOR_STRING + name)
+ }
def sourceFile: AbstractFile =
(if (isModule) moduleClass else toplevelClass).sourceFile
@@ -798,7 +827,7 @@ trait Symbols requires SymbolTable {
/** A tag which (in the ideal case) uniquely identifies class symbols */
final def tag: int = fullNameString.hashCode()
- /** The simple name of this Symbol (this is always a term name) */
+ /** The simple name of this Symbol */
final def simpleName: Name = name
/** String representation of symbol's definition key word */
@@ -848,8 +877,8 @@ trait Symbols requires SymbolTable {
final def fullNameString(separator: char): String = {
assert(owner != NoSymbol, this)
var str =
- if (owner.isRoot || owner.isEmptyPackageClass) simpleName.toString()
- else owner.fullNameString(separator) + separator + simpleName
+ if (owner.isRoot || owner.isEmptyPackageClass) simpleName.toString
+ else owner.enclClass.fullNameString(separator) + separator + simpleName
if (str.charAt(str.length - 1) == ' ') str = str.substring(0, str.length - 1)
str
}
@@ -953,6 +982,10 @@ trait Symbols requires SymbolTable {
this
}
+ override def outerSource: Symbol =
+ if (name endsWith nme.OUTER) initialize.referenced
+ else NoSymbol
+
override def moduleClass: Symbol =
if (hasFlag(MODULE)) referenced else NoSymbol
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 36d9b6b08c..a1787b8c3c 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -916,7 +916,7 @@ trait Types requires SymbolTable {
packagePrefix + str
else if (sym.isModuleClass)
objectPrefix + str
- else if (sym.isAnonymousClass && sym.isInitialized)
+ else if (sym.isAnonymousClass && sym.isInitialized && !settings.debug.value)
sym.info.parents.mkString("", " with ", "{ ... }")
else if (sym.isRefinementClass && sym.isInitialized)
sym.info.toString()
@@ -1719,7 +1719,9 @@ trait Types requires SymbolTable {
(tparams.head.isContravariant || (tps1.head <:< tps2.head)) &&
isSubArgs(tps1.tail, tps2.tail, tparams.tail)
);
- (sym1 == sym2 && (pre1 <:< pre2) && isSubArgs(args1, args2, sym1.typeParams)
+ (sym1 == sym2 &&
+ (phase.erasedTypes || pre1 <:< pre2) &&
+ isSubArgs(args1, args2, sym1.typeParams)
||
sym1.isAbstractType && !(tp1 =:= tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
||
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 64030f0c45..2ca9c99296 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -45,10 +45,13 @@ abstract class Constructors extends Transform {
assert(constr != null && constrBody != null, impl)
val paramAccessors = clazz.constrParamAccessors
- def parameter(acc: Symbol) = {
- val accname = nme.getterName(acc.originalName)
- val ps = constrParams.filter { param => accname == param.name }
- if (ps.isEmpty) assert(false, "" + accname + " not in " + constrParams)
+
+ def parameter(acc: Symbol): Symbol =
+ parameterNamed(nme.getterName(acc.originalName))
+
+ def parameterNamed(name: Name): Symbol = {
+ val ps = constrParams.filter(param => param.name == name)
+ if (ps.isEmpty) assert(false, "" + name + " not in " + constrParams)
ps.head
}
@@ -56,9 +59,13 @@ abstract class Constructors extends Transform {
val intoConstructorTransformer = new Transformer {
override def transform(tree: Tree): Tree = tree match {
- case Apply(Select(This(_), _), List())
- if ((tree.symbol hasFlag PARAMACCESSOR) && tree.symbol.owner == clazz) =>
- gen.mkAttributedIdent(parameter(tree.symbol.accessed)) setPos tree.pos
+ case Apply(Select(This(_), _), List()) =>
+ if ((tree.symbol hasFlag PARAMACCESSOR) && tree.symbol.owner == clazz)
+ gen.mkAttributedIdent(parameter(tree.symbol.accessed)) setPos tree.pos
+ else if (tree.symbol.outerSource == clazz && !clazz.isImplClass)
+ gen.mkAttributedIdent(parameterNamed(nme.OUTER))
+ else
+ super.transform(tree)
case Select(This(_), _)
if ((tree.symbol hasFlag PARAMACCESSOR) && tree.symbol.owner == clazz) =>
gen.mkAttributedIdent(parameter(tree.symbol)) setPos tree.pos
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index f02d662149..f99daa5cc8 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -602,7 +602,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
if (fn.symbol == Any_asInstanceOf || fn.symbol == Any_asInstanceOfErased)
fn match {
case TypeApply(Select(qual, _), List(targ)) =>
- if (qual.tpe <:< targ.tpe) Typed(qual, TypeTree(qual.tpe))
+ if (qual.tpe <:< targ.tpe) atPos(tree.pos) { Typed(qual, TypeTree(qual.tpe)) }
else tree
}
// todo: get rid of instanceOfErased
@@ -613,7 +613,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
targ.tpe match {
case SingleType(pre, sym) =>
val cmpOp = if (targ.tpe <:< AnyValClass.tpe) Any_equals else Object_eq
- Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe)))
+ atPos(tree.pos) {
+ Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe)))
+ }
case _ =>
tree
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 762572b7af..d85e491739 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -10,65 +10,92 @@ import symtab._
import Flags._
import scala.collection.mutable.{HashMap, ListBuffer}
import matching.{TransMatcher, PatternNodes, CodeFactory, PatternMatchers}
-abstract class ExplicitOuter extends InfoTransform
-with TransMatcher
-with PatternNodes
-with CodeFactory
-with PatternMatchers {
+
+abstract class ExplicitOuter extends InfoTransform with TransMatcher with PatternNodes with CodeFactory with PatternMatchers with TypingTransformers {
import global._
import definitions._
import posAssigner.atPos
+ /** The following flags may be set by this phase: */
override def phaseNewFlags: long = notPRIVATE | notPROTECTED
- /** the following two members override abstract members in Transform */
+ /** the name of the phase: */
val phaseName: String = "explicitouter"
+
+ /** This class does not change linearization */
override def changesBaseClasses = false
protected def newTransformer(unit: CompilationUnit): Transformer =
new ExplicitOuterTransformer(unit)
- private def outerClass(clazz: Symbol): Symbol =
- if (clazz.owner.isClass) clazz.owner
- else outerClass(if (clazz.isClassLocalToConstructor) clazz.owner.owner else clazz.owner)
+ /** Is given `clazz' an inner class? */
+ private def isInner(clazz: Symbol) =
+ !clazz.isPackageClass && !clazz.outerClass.isStaticOwner
+
+ private def outerField(clazz: Symbol): Symbol = {
+ val result = clazz.info.member(nme.getterToLocal(nme.OUTER))
+ if (result == NoSymbol) assert(false, "no outer field in "+clazz+clazz.info.decls+" at "+phase)
+ result
+ }
- private def isStatic(clazz: Symbol) =
- clazz.isPackageClass || outerClass(clazz).isStaticOwner
+ private def outerAccessor(clazz: Symbol): Symbol = {
+ val firstTry = clazz.info.decl(clazz.expandedName(nme.OUTER))
+ if (firstTry != NoSymbol && firstTry.outerSource == clazz) firstTry
+ else {
+ var e = clazz.info.decls.elems;
+ while (e != null && e.sym.outerSource != clazz) e = e.next
+ if (e != null) e.sym else NoSymbol
+ }
+ }
/** The type transformation method:
- * 1. Add an outer paramter to the formal parameters of a constructor or mixin constructor
- * in a non-static class;
- * 2. Add a mixin constructor $init$ to all mixins except interfaces
- * Leave all other types unchanged.
+ * 1. Add an outer parameter to the formal parameters of a constructor
+ * in a inner non-trait class;
+ * 2. Add a protected $outer field to an inner class which is not a trait.
+ * 3. Add an outer accessor $outer$$C to every inner class with fully qualified name C
+ * that is not an interface. The outer accesssor is abstract for traits, concrete
+ * for other classes.
+ * 3a. Also add overriding accessor defs to every class that inherits mixin classes
+ * with outer accessor defs (unless the superclass already inherits the same mixin).
+ * 4. Add a mixin constructor $init$ to all mixins except interfaces
+ * Leave all other types unchanged. todo: move to later
+ * 5. Make all super accessors and modules in traits non-private, mangling their names.
+ * 6. Remove protected flag from all members of traits.
*/
def transformInfo(sym: Symbol, tp: Type): Type = tp match {
case MethodType(formals, restpe) =>
- if (sym.owner.isTrait && ((sym hasFlag SUPERACCESSOR) || sym.isModule))
- sym.makeNotPrivate(sym.owner);
- if (sym.owner.isTrait && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED
- if (sym.isConstructor && !isStatic(sym.owner)) {
- // Move outer paramater to first position
- MethodType(outerClass(sym.owner).toInterface.thisType :: formals, restpe)
- //MethodType(formals ::: List(outerClass(sym.owner).toInterface.thisType), restpe)
- }
+ if (sym.owner.isTrait && ((sym hasFlag SUPERACCESSOR) || sym.isModule)) // 5
+ sym.makeNotPrivate(sym.owner)
+ if (sym.owner.isTrait && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED // 6
+ if (sym.isClassConstructor && isInner(sym.owner)) // 1
+ MethodType(sym.owner.outerClass.thisType :: formals, restpe)
else tp
case ClassInfoType(parents, decls, clazz) =>
var decls1 = decls
if (!(clazz hasFlag INTERFACE)) {
- if (!isStatic(clazz)) {
- decls1 = newScope(decls1.toList)
- val outerAcc = clazz.newMethod(clazz.pos, nme.OUTER)
- if (clazz.isTrait || (decls.toList exists (.isClass)))
- outerAcc.expandName(clazz);
+ if (isInner(clazz)) {
+ if (decls1 eq decls) decls1 = newScope(decls1.toList)
+ val outerAcc = clazz.newMethod(clazz.pos, nme.OUTER) // 3
+ outerAcc.expandName(clazz)
decls1 enter (
- outerAcc setFlag (PARAMACCESSOR | ACCESSOR | STABLE)
- setInfo MethodType(List(), outerClass(clazz).thisType));
- decls1 enter (clazz.newValue(clazz.pos, nme.getterToLocal(outerAcc.name))
- setFlag (LOCAL | PRIVATE | PARAMACCESSOR | (outerAcc getFlag EXPANDEDNAME))
- setInfo outerClass(clazz).thisType)
+ clazz.newOuterAccessor(clazz.pos)
+ setInfo MethodType(List(), clazz.outerClass.thisType))
+ if (!parents.isEmpty) {
+ for (val mc <- clazz.mixinClasses) {
+ val mixinOuterAcc: Symbol = atPhase(phase.next)(outerAccessor(mc))
+ if (mixinOuterAcc != NoSymbol)
+ decls1 enter (mixinOuterAcc.cloneSymbol(clazz) resetFlag DEFERRED)
+ }
+ }
+ if (!clazz.isTrait) // 2
+ //todo: avoid outer field if superclass has same outer value?
+ decls1 enter (
+ clazz.newValue(clazz.pos, nme.getterToLocal(nme.OUTER))
+ setFlag (PROTECTED | PARAMACCESSOR)
+ setInfo clazz.outerClass.thisType)
}
- if (clazz.isTrait) {
- decls1 = newScope(decls1.toList)
+ if (clazz.isTrait) { // 4 (todo: can go into next phase?)
+ if (decls1 eq decls) decls1 = newScope(decls1.toList)
decls1 enter makeMixinConstructor(clazz)
}
}
@@ -80,16 +107,6 @@ with PatternMatchers {
tp
}
- private def outerMember(tp: Type): Symbol = {
- var e = tp.symbol.info.decls.elems
- // note: tp.decls does not work here, because tp might be a ThisType, in which case
- // its decls would be the decls of the required type of the class.
- while (e != null && !(e.sym.originalName.startsWith(nme.OUTER) && (e.sym hasFlag ACCESSOR)))
- e = e.next;
- assert(e != null, tp)
- e.sym
- }
-
private def makeMixinConstructor(clazz: Symbol): Symbol =
clazz.newMethod(clazz.pos, nme.MIXIN_CONSTRUCTOR) setInfo MethodType(List(), UnitClass.tpe)
@@ -97,348 +114,291 @@ with PatternMatchers {
* outer parameters of constructors.
* The class provides methods for referencing via outer.
*/
- class OuterPathTransformer extends Transformer {
+ abstract class OuterPathTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
/** The directly enclosing outer parameter, if we are in a constructor */
protected var outerParam: Symbol = NoSymbol
- /** The first outer selection from currently transformed tree
+ /** The first outer selection from currently transformed tree.
+ * The result is typed but not positioned.
*/
protected def outerValue: Tree =
if (outerParam != NoSymbol) gen.mkAttributedIdent(outerParam)
- else outerSelect(gen.mkAttributedThis(currentOwner.enclClass))
-
- /** The path
- * `base'.$outer ... .$outer
- * which refers to the outer instance 'to' of value 'base'
- */
- protected def outerPath(base: Tree, to: Symbol): Tree =
- if (base.tpe.symbol == to) base else outerPath(outerSelect(base), to)
+ else outerSelect(gen.mkAttributedThis(currentClass))
/** Select and apply outer accessor from 'base'
+ * The result is typed but not positioned.
*/
private def outerSelect(base: Tree): Tree = {
- val otp = outerClass(base.tpe.symbol).thisType
- Apply(
- Select(base, outerMember(base.tpe)) setType MethodType(List(), otp),
- List()) setType otp
+ localTyper.typed(Apply(Select(base, outerAccessor(base.tpe.symbol)), List()))
+ }
+
+ /** The path
+ * `base'.$outer$$C1 ... .$outer$$Cn
+ * which refers to the outer instance of class 'to' of value 'base'
+ * The result is typed but not positioned.
+ */
+ protected def outerPath(base: Tree, from: Symbol, to: Symbol): Tree = {
+ //Console.println("outerPath from "+from+" to "+to+" at "+base+":"+base.tpe)
+ assert(base.tpe.baseType(from.toInterface) != NoType, base.tpe)
+ if (from == to || from.isImplClass && from.toInterface == to) base
+ else outerPath(outerSelect(base), from.outerClass, to)
}
override def transform(tree: Tree): Tree = {
- try {//debug
- val savedOuterParam = outerParam;
+ val savedOuterParam = outerParam;
+ try {
tree match {
case Template(_, _) =>
outerParam = NoSymbol
case DefDef(_, _, _, vparamss, _, _) =>
- if (tree.symbol.isConstructor && !(isStatic(tree.symbol.owner))) {
- // moved outer param to first position
- val firstParam = vparamss.head.head
-// val lastParam = vparamss.head.last
- assert(firstParam.name.startsWith(nme.OUTER), tree)
- outerParam = firstParam.symbol
+ if (tree.symbol.isClassConstructor && isInner(tree.symbol.owner)) {
+ outerParam = vparamss.head.head.symbol
+ assert(outerParam.name == nme.OUTER)
}
case _ =>
}
- val result = super.transform(tree);
- outerParam = savedOuterParam
- result
+ super.transform(tree)
} catch {//debug
case ex: Throwable =>
System.out.println("exception when transforming " + tree)
throw ex
+ } finally {
+ outerParam = savedOuterParam
}
}
}
- class ExplicitOuterTransformer(unit: CompilationUnit) extends Transformer {
-
- /** The first step performs the following transformations:
- * 1. A class which is not an interface and is not static gets an outer link
- * (@see outerDefs)
- * 2. A mixin which is not also an interface gets a mixin constructor
- * (@see mixinConstructorDef)
- * 3. Constructor bodies are augmented by calls to supermixin constructors
- * (@see addMixinConstructorCalls)
- * 4. A constructor of a class with an outer link gets an outer parameter.
- * 5. A reference C.this where C refers to an outer class is replaced by a selection
- * this.$outer ... .$outer (@see outerPath)
- * 7. A call to a constructor Q.<init>(args) or Q.$init$(args) where Q != this and
- * the constructor belongs to a non-static class is augmented by an outer argument.
- * E.g. Q.<init>(args, OUTER) where OUTER is the qualifier corresponding to the
- * singleton type Q.
- * 8. A call to a constructor this.<init>(args) in a secondary constructor
- * is augmented to this.<init>(args, OUTER) where OUTER is the last parameter
- * of the secondary constructor.
+ /** The phase performs the following transformations on terms:
+ * 1. An class which is not an interface and is not static gets an outer accessor
+ * (@see outerDefs)
+ * 1a. A class which is not a trait gets an outer field.
+ * 2. A mixin which is not also an interface gets a mixin constructor
+ * (@see mixinConstructorDef)
+ * 3. Constructor bodies are augmented by calls to supermixin constructors
+ * (@see addMixinConstructorCalls)
+ * 4. A constructor of a non-trait inner class gets an outer parameter.
+ * 5. A reference C.this where C refers to an outer class is replaced by a selection
+ * this.$outer$$C1 ... .$outer$$Cn (@see outerPath)
+ * 7. A call to a constructor Q.<init>(args) or Q.$init$(args) where Q != this and
+ * the constructor belongs to a non-static class is augmented by an outer argument.
+ * E.g. Q.<init>(OUTER, args) where OUTER is the qualifier corresponding to the
+ * singleton type Q.
+ * 8. A call to a constructor this.<init>(args) in a secondary constructor
+ * is augmented to this.<init>(OUTER, args) where OUTER is the last parameter
+ * of the secondary constructor.
+ * 9. Remove `private' modifier from class members M that are accessed from an inner class.
+ * 10.Remove `protected' modifier from class members M that are accessed
+ * without a super qualifier accessed from an inner class or trait.
+ * 11. Remove `private' and `protected' modifiers from type symbols
+ * 12. Remove `private' modifiers from members of traits
+ * Note: The whole transform is run in phase explicitOuter.next
+ */
+ class ExplicitOuterTransformer(unit: CompilationUnit) extends OuterPathTransformer(unit) {
+
+ /** The definition tree of the outer accessor of current class
*/
- private val firstTransformer = new OuterPathTransformer {
-
- var localTyper: analyzer.Typer = typer
-
- /** The two definitions
- * val outer: C.this.type _;
- * def outer(): C.this.type = outer ;
- * Here, C is the class enclosing the class `clazz' containing the two definitions.
- */
- def outerDefs(clazz: Symbol): List[Tree] = {
- val outerDef = outerMember(clazz.info)
- val outerVal = outerDef.accessed
- List(
- localTyper.typed {
- atPos(clazz.pos) {
- ValDef(outerVal)
- }
- },
- localTyper.typed {
- atPos(clazz.pos) {
- DefDef(outerDef, vparamss => Select(This(clazz), outerVal))
- }
- })
+ def outerFieldDef: Tree = {
+ val outerF = outerField(currentClass)
+ ValDef(outerF, EmptyTree)
+ }
+
+ /** The definition tree of the outer accessor of current class
+ */
+ def outerAccessorDef: Tree = {
+ val outerAcc = outerAccessor(currentClass)
+ var rhs = if (outerAcc hasFlag DEFERRED) EmptyTree
+ else Select(This(currentClass), outerField(currentClass))
+ localTyper.typed {
+ atPos(currentClass.pos) {
+ DefDef(outerAcc, vparamss => rhs)
+ }
}
+ }
- /** The mixin constructor definition
- * def $init$(): Unit = ()
- */
- def mixinConstructorDef(clazz: Symbol): Tree =
- localTyper.typed {
- val constr = clazz.primaryConstructor
- atPhase(currentRun.explicitOuterPhase) {
- // necessary so that we do not include an outer parameter already here;
- // this will be added later in transform.
- DefDef(constr, vparamss => Literal(()))
- }
+ /** The definition tree of the outer accessor for class `mixinClass'
+ * @param mixinClass The mixin class which defines the abstract outer accessor which is
+ * implemented by the generated one.
+ * @pre mixinClass is an inner class
+ */
+ def mixinOuterAccessorDef(mixinClass: Symbol): Tree = {
+ val outerAcc = outerAccessor(mixinClass).overridingSymbol(currentClass)
+ if (outerAcc == NoSymbol) Console.println("cc "+currentClass+":"+currentClass.info.decls)//debug
+ assert(outerAcc != NoSymbol)
+ val path = gen.mkAttributedQualifier(currentClass.thisType.baseType(mixinClass).prefix)
+ val rhs = ExplicitOuterTransformer.this.transform(path)
+ localTyper.typed {
+ atPos(currentClass.pos) {
+ DefDef(outerAcc, vparamss => rhs)
}
+ }
+ }
- /** Add calls to supermixin constructors
- * super[mix].$init$()
- * to `tree'. `tree' which is assumed to be the body of a constructor of class `clazz'.
- */
- def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = {
- def mixinConstructorCall(mixinClass: Symbol): Tree =
- atPos(tree.pos) {
- Apply(
- localTyper.typedOperator {
- Select(This(clazz), mixinClass.primaryConstructor)
- },
- List()) setType UnitClass.tpe; // don't type this with typed(...),
- // as constructor arguments might be missing
- }
- /*
- val mixinConstructorCalls =
- for (val mixinClass <- clazz.info.parents.tail;
- !(mixinClass.symbol hasFlag INTERFACE) && mixinClass.symbol != ScalaObjectClass) yield
- mixinConstructorCall(mixinClass.symbol);
- tree match {
- */
- val mixinConstructorCalls: List[Tree] = {
- val ps = clazz.info.parents
- if (ps.isEmpty) List()
- else {
- val superClass = ps.head.symbol
- for {
- val mclazz <- clazz.info.baseClasses.tail.takeWhile(superClass ne).reverse
- mclazz.needsImplClass && mclazz != ScalaObjectClass
- } yield mixinConstructorCall(mclazz)
- }
+ /** The mixin constructor definition
+ * def $init$(): Unit = ()
+ */
+ def mixinConstructorDef(clazz: Symbol): Tree =
+ localTyper.typed {
+ val constr = clazz.primaryConstructor
+ atPhase(currentRun.explicitOuterPhase) {
+ // necessary so that we do not include an outer parameter already here
+ // this will be added later in transform.
+ DefDef(constr, vparamss => Block(List(), Literal(())))
}
+ }
- //val result =
- tree match {
- case Block(supercall :: stats, expr) =>
- assert(supercall match {
- case Apply(Select(Super(_, _), _), _) => true
- case _ => false
- })
- copy.Block(tree, supercall :: mixinConstructorCalls ::: stats, expr)
- case Block(_, _) =>
- assert(false, tree); tree
+ /** Add calls to supermixin constructors
+ * super[mix].$init$()
+ * to `tree'. `tree' which is assumed to be the body of a constructor of class `clazz'.
+ */
+ def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = {
+ def mixinConstructorCall(mixinClass: Symbol): Tree =
+ atPos(tree.pos) {
+ Apply(
+ localTyper.typedOperator {
+ Select(This(clazz), mixinClass.primaryConstructor)
+ },
+ List()) setType UnitClass.tpe; // don't type this with typed(...),
+ // as constructor arguments might be missing
}
- //System.out.println("new constructor of "+clazz+": "+result);
- //result
+ val mixinConstructorCalls: List[Tree] = {
+ for (val mc <- clazz.mixinClasses.reverse; mc.needsImplClass && mc != ScalaObjectClass)
+ yield mixinConstructorCall(mc)
}
- /** The first-step transformation method */
- override def transform(tree: Tree): Tree = {
- val sym = tree.symbol
- val tree1 = tree match {
- case Template(parents, decls) =>
- val savedLocalTyper = localTyper
- localTyper = localTyper.atOwner(tree, currentOwner)
- var decls1 = decls
- if (!(currentOwner hasFlag INTERFACE) || (currentOwner hasFlag lateINTERFACE)) {
- if (!isStatic(currentOwner))
- decls1 = decls1 ::: outerDefs(currentOwner); // (1)
- if (currentOwner.isTrait)
- decls1 = decls1 ::: List(mixinConstructorDef(currentOwner)) // (2)
+ //begin mixin constructor calls
+ tree match {
+ case Block(supercall :: stats, expr) =>
+ assert(supercall match {
+ case Apply(Select(Super(_, _), _), _) => true
+ case _ => false
+ })
+ copy.Block(tree, supercall :: mixinConstructorCalls ::: stats, expr)
+ case Block(_, _) =>
+ assert(false, tree); tree
+ }
+ }
+
+ /** The main transformation method */
+ override def transform(tree: Tree): Tree = {
+ val sym = tree.symbol
+ if (sym != null && sym.isType) {//(9)
+ if (sym hasFlag PRIVATE) sym setFlag notPRIVATE
+ if (sym hasFlag PROTECTED) sym setFlag notPROTECTED
+ }
+ tree match {
+ case Template(parents, decls) =>
+ val newDefs = new ListBuffer[Tree]
+ atOwner(tree, currentOwner) {
+ if (!(currentClass hasFlag INTERFACE) || (currentClass hasFlag lateINTERFACE)) {
+ if (isInner(currentClass)) {
+ if (!currentClass.isTrait) newDefs += outerFieldDef // (1a)
+ newDefs += outerAccessorDef // (1)
+ }
+ if (currentClass.isTrait)
+ newDefs += mixinConstructorDef(currentClass)
+ else
+ for (val mc <- currentClass.mixinClasses)
+ if (outerAccessor(mc) != NoSymbol)
+ newDefs += mixinOuterAccessorDef(mc)
}
- localTyper = savedLocalTyper
- copy.Template(tree, parents, decls1)
- case constrDef @ DefDef(mods, name, tparams, vparamss, tpt, rhs)
- if (sym.isConstructor) =>
+ }
+ super.transform(
+ copy.Template(tree, parents, if (newDefs.isEmpty) decls else decls ::: newDefs.toList))
+
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ if (sym.isClassConstructor) {
rhs match {
case Literal(_) =>
- val rhs1 = Block(List(), rhs) setPos rhs.pos setType rhs.tpe;
+ // replace unit rhs () by empty block {()}
+ val rhs1 = Block(List(), rhs) setPos rhs.pos setType rhs.tpe
transform(copy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs1))
case _ =>
- val clazz = sym.owner.toInterface
+ val clazz = sym.owner
val vparamss1 =
- if (isStatic(clazz)) vparamss
- else { // (4)
- val outerField = outerMember(clazz.info).accessed;
- val outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField.info;
- // moved outer param to first position
- List((ValDef(outerParam) setType NoType) :: vparamss.head)
-// List(vparamss.head ::: List(ValDef(outerParam) setType NoType))
- }
+ if (isInner(clazz)) { // (4)
+ val outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField(clazz).info
+ ((ValDef(outerParam) setType NoType) :: vparamss.head) :: vparamss.tail
+ } else vparamss
+ // todo: move
val rhs1 =
if (sym.isPrimaryConstructor && sym.isClassConstructor && clazz != ArrayClass)
addMixinConstructorCalls(rhs, clazz); // (3)
- else rhs;
- copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1)
- }
- case This(qual) =>
- if (sym == currentOwner.enclClass || (sym hasFlag MODULE) && sym.isStatic) tree
- else atPos(tree.pos)(outerPath(outerValue, sym)); // (5)
- case Apply(sel @ Select(qual, name), args)
- if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) && !isStatic(sel.symbol.owner)) =>
- val outerVal = atPos(tree.pos) {
- if (name == nme.MIXIN_CONSTRUCTOR) {
- val mclazz = sym.owner.toInterface
- //System.out.println("adding mixin constructor for " + currentOwner.enclClass + " " + mclazz + " " + currentOwner.enclClass.thisType.baseType(mclazz));//DEBUG
- var pre = currentOwner.enclClass.thisType.baseType(mclazz).prefix
- if (pre == NoPrefix) pre = outerClass(mclazz).thisType
- gen.mkAttributedQualifier(pre)
- } else if (qual.isInstanceOf[This]) {
- assert(outerParam != NoSymbol); outerValue
- } else {
- var pre = qual.tpe.prefix
- if (pre == NoPrefix) pre = outerClass(sym.owner).thisType;
- gen.mkAttributedQualifier(pre)
- }
+ else rhs
+ super.transform(copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1))
}
- // moved outer parameter to first position
- copy.Apply(tree, sel, outerVal :: args)
-// copy.Apply(tree, sel, args ::: List(outerVal))
-
- case _ =>
- tree
- }
- super.transform(tree1)
- }
- }
+ } else { //todo: see whether we can move this to transformInfo
+ if (sym.owner.isTrait && (sym hasFlag (ACCESSOR | SUPERACCESSOR)))
+ sym.makeNotPrivate(sym.owner); //(2)
+ super.transform(tree)
+ }
- /** The second step performs the following transformations:
- * 2. Remove private modifiers from members M of mixins T. (@see makeNotPrivate)
- * 3. Remove `private' modifier from class members M that are accessed from an inner class.
- * 4. Remove `protected' modifier from class members M that are accessed
- * without a super qualifier accessed from an inner class or trait.
- * 5. Remove `private' and `protected' modifiers from type symbols
- */
- private val secondTransformer = new OuterPathTransformer {
+ case This(qual) =>
+ if (sym == currentClass || (sym hasFlag MODULE) && sym.isStatic) tree
+ else atPos(tree.pos)(outerPath(outerValue, currentClass.outerClass, sym)) // (5)
- def handleSelect(tree:Select) = tree match {
case Select(qual, name) =>
- val sym = tree.symbol
- val enclClass = currentOwner.enclClass
- if (enclClass != sym.owner && enclClass != sym.moduleClass) // (3)
- sym.makeNotPrivate(sym.owner);
+ if (currentClass != sym.owner && currentClass != sym.moduleClass) // (3)
+ sym.makeNotPrivate(sym.owner)
val qsym = qual.tpe.widen.symbol
if ((sym hasFlag PROTECTED) && //(4)
- (qsym.isTrait || !(qual.isInstanceOf[Super] || (qsym isSubClass enclClass))))
- sym setFlag notPROTECTED;
- }
-
- /** The second-step transformation method */
- override def transform(tree: Tree): Tree = {
- val sym = tree.symbol
- val tree1 =
- if(tree.isInstanceOf[Match]) {
- //Console.println("calling super.transform of Match with ncases "+
- // tree.asInstanceOf[Match].cases.length)
- tree
- } else {
- super.transform(tree)
- }
- tree1 match {
- case DefDef(_, _, _, _, _, _) =>
- if (sym.owner.isTrait && (sym hasFlag (ACCESSOR | SUPERACCESSOR)))
- sym.makeNotPrivate(sym.owner); //(2)
- tree1
- case tree @ Select(qual, name) =>
- handleSelect(tree)
- tree1
+ (qsym.isTrait || !(qual.isInstanceOf[Super] || (qsym isSubClass currentClass))))
+ sym setFlag notPROTECTED
+ super.transform(tree)
- case Match(selector, cases) => // <----- transmatch hook
- val tid = cunit.fresh.newName("tidmark")
+ case Apply(sel @ Select(qual, name), args)
+ if (name == nme.CONSTRUCTOR && isInner(sel.symbol.owner)) =>
+ val outerVal = atPos(tree.pos) {
+ if (qual.isInstanceOf[This]) { // it's a call between constructors of same class
+ assert(outerParam != NoSymbol)
+ outerValue
+ } else {
+ var pre = qual.tpe.prefix
+ if (pre == NoPrefix) pre = sym.owner.outerClass.thisType
+ gen.mkAttributedQualifier(pre)
+ }
+ }
+ super.transform(copy.Apply(tree, sel, outerVal :: args))
+ case Match(selector, cases) => // <----- transmatch hook
+ val tid = unit.fresh.newName("tidmark")
if(settings.debug.value)
Console.println("transforming patmat with tidmark "+tid+" ncases = "+cases.length)
- if((cases.length > 1)&&( treeInfo.isDefaultCase(cases(0))))
- assert(false,"transforming too much, "+tid)
- val nselector = transform(selector).setType(selector.tpe)
- val ncases = cases map { transform }
- ExplicitOuter.this.resultType = tree.tpe
- //Console.println("TransMatcher currentOwner ="+currentOwner+")")
- //Console.println("TransMatcher selector.tpe ="+selector.tpe+")")
- //Console.println("TransMatcher resultType ="+resultType+")")
- def mytransform(tree: Tree): Tree = {
- val sym = tree.symbol
- tree match {
- case This(qual) =>
- if (sym == currentOwner.enclClass || (sym hasFlag Flags.MODULE) && sym.isStatic) tree
- else atPos(tree.pos)(outerPath(outerValue, sym)); // (5)
- case Select(qual,name) =>
- val s = copy.Select(tree, mytransform(qual), name)
- handleSelect(s)
- s
- case x =>
- if(settings.debug.value)
- Console.println(x.getClass())
- x
- }
- }
- val t_untyped = ExplicitOuter.this.handlePattern(nselector, ncases.asInstanceOf[List[CaseDef]], currentOwner, mytransform)
+ if((cases.length > 1)&&( treeInfo.isDefaultCase(cases(0))))
+ assert(false,"transforming too much, "+tid)
+ val nselector = transform(selector)
+ assert(nselector.tpe =:= selector.tpe)
+ val ncases = transformCaseDefs(cases)
- //Console.println("t_untyped "+t_untyped.toString())
- val t = atPos(tree.pos) { typer.atOwner(tree,currentOwner).typed(t_untyped, resultType) }
+ ExplicitOuter.this.resultType = tree.tpe
+ //Console.println("TransMatcher currentOwner ="+currentOwner+")")
+ //Console.println("TransMatcher selector.tpe ="+selector.tpe+")")
+ //Console.println("TransMatcher resultType ="+resultType+")")
+
+ val t_untyped = handlePattern(nselector, ncases, currentOwner, transform)
+ //Console.println("t_untyped "+t_untyped.toString())
+ val t = atPos(tree.pos) { localTyper.typed(t_untyped, resultType) }
//t = transform(t)
- //val t = atPos(tree.pos) { typed(t_untyped, resultType) }
- //val t = atPos(tree.pos) { typed(t_untyped) }
- //Console.println("t typed "+t.toString())
+ //val t = atPos(tree.pos) { typed(t_untyped, resultType) }
+ //val t = atPos(tree.pos) { typed(t_untyped) }
+ //Console.println("t typed "+t.toString())
if(settings.debug.value)
Console.println("finished translation of "+tid)
- t
-/*<--- end transmatch experimental */
+ t
- case _ =>
- if (sym != null && sym.isType) {//(5)
- if (sym hasFlag PRIVATE) sym setFlag notPRIVATE
- if (sym hasFlag PROTECTED) sym setFlag notPROTECTED
- }
- tree1
- }
+ case _ =>
+ super.transform(tree)
}
}
- // needed in TransMatcher
- override def transformUnit(unit: CompilationUnit) = {
+ /** The transformation method for whole compilation units */
+ override def transformUnit(unit: CompilationUnit): unit = {
cunit = unit
- super.transformUnit(unit)
- cunit = null
+ atPhase(phase.next) { super.transformUnit(unit) }
}
-
-
- /** The main transformation method:
- * First, perform step 1 on whole tree of compilation unit.
- * Then, perform step 2 on resulting tree
- */
- override def transform(tree: Tree) =
- atPhase(phase.next) {
- secondTransformer.transform(firstTransformer.transform(tree))
- }
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 1b9bf64dfd..d259a1468a 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -41,7 +41,7 @@ abstract class LambdaLift extends InfoTransform {
protected def newTransformer(unit: CompilationUnit): Transformer =
new LambdaLifter(unit)
- class LambdaLifter(unit: CompilationUnit) extends explicitOuter.OuterPathTransformer {
+ class LambdaLifter(unit: CompilationUnit) extends explicitOuter.OuterPathTransformer(unit) {
/** A map storing free variables of functions and classes */
private val free = new HashMap[Symbol, SymSet]
@@ -286,11 +286,12 @@ abstract class LambdaLift extends InfoTransform {
private def memberRef(sym: Symbol) = {
val clazz = sym.owner.enclClass
- val qual = if (clazz == currentOwner.enclClass) gen.mkAttributedThis(clazz)
+ //Console.println("memberRef from "+currentClass+" to "+sym+" in "+clazz)
+ val qual = if (clazz == currentClass) gen.mkAttributedThis(clazz)
else {
sym resetFlag(LOCAL | PRIVATE)
if (clazz.isStaticOwner) gen.mkAttributedQualifier(clazz.thisType)
- else outerPath(outerValue, clazz)
+ else outerPath(outerValue, currentClass.outerClass, clazz)
}
Select(qual, sym) setType sym.tpe
}
@@ -360,7 +361,7 @@ abstract class LambdaLift extends InfoTransform {
case Return(Block(stats, value)) =>
Block(stats, copy.Return(tree, value)) setType tree.tpe setPos tree.pos
case Return(expr) =>
- assert(sym == currentOwner.enclMethod, sym)
+ assert(sym == currentMethod, sym)
tree
case Apply(fn, args) =>
copy.Apply(tree, fn, addFreeArgs(tree.pos, sym, args))
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 167f4959e3..98ee4c001d 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -392,7 +392,7 @@ abstract class Mixin extends InfoTransform {
/** Attribute given tree and anchor at given position */
def attributedDef(pos: PositionType, tree: Tree): Tree = {
- if (settings.debug.value) System.out.println("add new def to " + clazz + ": " + tree);
+ if (settings.debug.value) log("add new def to " + clazz + ": " + tree);
localTyper.typed { atPos(pos) { tree } }
}
diff --git a/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala b/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala
index 1e345a930a..c4de6f6fab 100644
--- a/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala
+++ b/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala
@@ -15,12 +15,15 @@ trait TypingTransformers {
import global._
abstract class TypingTransformer(unit: CompilationUnit) extends Transformer {
- var localTyper: analyzer.Typer = analyzer.newTyper(analyzer.rootContext(unit))
+ var localTyper: analyzer.Typer = analyzer.newTyper(
+ analyzer.rootContext(unit, EmptyTree, true))
private var curTree: Tree = _
- override def atOwner[A](owner: Symbol)(trans: => A): A = {
+ override def atOwner[A](owner: Symbol)(trans: => A): A = atOwner(curTree, owner)(trans)
+
+ def atOwner[A](tree: Tree, owner: Symbol)(trans: => A): A = {
val savedLocalTyper = localTyper
- localTyper = localTyper.atOwner(curTree, owner)
+ localTyper = localTyper.atOwner(tree, owner)
val result = super.atOwner(owner)(trans)
localTyper = savedLocalTyper
result
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index f198881d7e..0e032321e0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -22,17 +22,6 @@ abstract class TreeCheckers extends Analyzer {
}
def check(unit: CompilationUnit): unit = {
- val areporter = reporter match {
- case ar: AbstractReporter => ar
- case _ => null
- }
-
- val curPrompt = if (areporter != null) {
- val ret = areporter.prompt
- areporter.prompt = true
- ret
- } else false
-
val context = rootContext(unit)
context.checking = true
tpeOfTree.clear
@@ -46,9 +35,6 @@ abstract class TreeCheckers extends Analyzer {
currentRun.advanceUnit
assert(currentRun.currentUnit == unit)
currentRun.currentUnit = unit0
-
- if (areporter != null)
- areporter.prompt = curPrompt
}
override def newTyper(context: Context): Typer = new TreeChecker(context)
@@ -99,7 +85,10 @@ abstract class TreeCheckers extends Analyzer {
var o = currentOwner
while (o != tree.symbol) {
o = o.owner
- assert(o != NoSymbol, tree)
+ if (o == NoSymbol) {
+ error(tree.pos, "tree symbol "+tree.symbol+" does not point to enclosing class; tree = "+tree)
+ return
+ }
}
}
case _ =>
@@ -129,20 +118,28 @@ abstract class TreeCheckers extends Analyzer {
}
object postcheck extends Traverser {
- override def traverse(tree: Tree): unit = tree match {
- case EmptyTree | TypeTree() =>
- ;
- case _ =>
- tpeOfTree.get(tree) match {
- case Some(oldtpe) =>
- if (!(oldtpe =:= tree.tpe))
- error(tree.pos, "types differ\n old: " + oldtpe +
- "\n new: " + tree.tpe + "\n tree: " + tree)
- tree.tpe = oldtpe
- super.traverse(tree)
- case None =>
+ override def traverse(tree: Tree): unit =
+ try {
+ tree match {
+ case EmptyTree | TypeTree() =>
+ ;
+ case _ =>
+ tpeOfTree.get(tree) match {
+ case Some(oldtpe) =>
+ if (!(oldtpe =:= tree.tpe))
+ error(tree.pos, "types differ\n old: " + oldtpe +
+ "\n new: " + tree.tpe + "\n tree: " + tree)
+ tree.tpe = oldtpe
+ super.traverse(tree)
+ case None =>
+ }
}
- }
+ } catch {
+ case ex: Throwable =>
+ if (settings.debug.value)
+ System.out.println("exception when traversing " + tree);
+ throw(ex)
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 64e367bb33..1bfba3fc3c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -24,8 +24,6 @@ trait Typers requires Analyzer {
var implcnt = 0
var impltime = 0l
- final val xviews = true
-
private val transformed = new HashMap[Tree, Tree]
private val superDefs = new HashMap[Symbol, ListBuffer[Tree]]
@@ -631,7 +629,7 @@ trait Typers requires Analyzer {
}
}
- if (!parents.head.tpe.isError)
+ if (!parents.isEmpty && !parents.head.tpe.isError)
for (val p <- parents) validateParentClass(p, parents.head.tpe.symbol)
}
@@ -665,7 +663,7 @@ trait Typers requires Analyzer {
val vdef = copy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs)
val value = vdef.symbol
val getter = if (mods hasFlag DEFERRED) value else value.getter(value.owner)
- assert(getter != NoSymbol, getter);//debug
+ assert(getter != NoSymbol, stat)
val getterDef: DefDef = {
val result = DefDef(getter, vparamss =>
if (mods hasFlag DEFERRED) EmptyTree
@@ -714,7 +712,9 @@ trait Typers requires Analyzer {
// the following is necessary for templates generated later
new Namer(context.outer.make(templ, clazz, clazz.info.decls)).enterSyms(templ.body)
validateParentClasses(parents1, selfType);
- val body1 = typedStats(templ.body flatMap addGetterSetter, templ.symbol)
+ val body = if (phase.id <= currentRun.typerPhase.id) templ.body flatMap addGetterSetter
+ else templ.body
+ val body1 = typedStats(body, templ.symbol)
copy.Template(templ, parents1, body1) setType clazz.tpe
}
@@ -844,7 +844,7 @@ trait Typers requires Analyzer {
case _ =>
typedSuperCall(ddef.rhs, UnitClass.tpe)
}
- if (meth.isPrimaryConstructor && !phase.erasedTypes && reporter.errors == 0)
+ if (meth.isPrimaryConstructor && phase.id <= currentRun.typerPhase.id && reporter.errors == 0)
computeParamAliases(meth.owner, vparamss1, result)
result
} else transformedOrTyped(ddef.rhs, tpt1.tpe)
@@ -1086,9 +1086,8 @@ trait Typers requires Analyzer {
case _ => tp
}
if (fun.symbol == List_apply && args.isEmpty) {
- gen.mkNil setType restpe
- }
- else if ((mode & CONSTmode) != 0 && fun.symbol.owner == PredefModule.tpe.symbol && fun.symbol.name == nme.Array) {
+ atPos(tree.pos) { gen.mkNil setType restpe }
+ } else if ((mode & CONSTmode) != 0 && fun.symbol.owner == PredefModule.tpe.symbol && fun.symbol.name == nme.Array) {
val elems = new Array[Constant](args1.length)
var i = 0;
for (val arg <- args1) arg match {
@@ -1665,7 +1664,7 @@ trait Typers requires Analyzer {
typedTypeApply(typed(fun, funMode(mode) | TAPPmode, WildcardType), args1)
case Apply(Block(stats, expr), args) =>
- typed1(Block(stats, Apply(expr, args)), mode, pt)
+ typed1(atPos(tree.pos)(Block(stats, Apply(expr, args))), mode, pt)
case Apply(fun, args) =>
val stableApplication = fun.symbol != null && fun.symbol.isMethod && fun.symbol.isStable
@@ -1680,8 +1679,7 @@ trait Typers requires Analyzer {
// number of arguments and expected result type.
if (settings.debug.value) log("trans app "+fun1+":"+fun1.symbol+":"+fun1.tpe+" "+args);//DEBUG
if (util.Statistics.enabled) appcnt = appcnt + 1
- if (xviews &&
- phase.id <= currentRun.typerPhase.id &&
+ if (phase.id <= currentRun.typerPhase.id &&
fun1.isInstanceOf[Select] &&
!fun1.tpe.isInstanceOf[ImplicitMethodType] &&
(fun1.symbol == null || !fun1.symbol.isConstructor) &&
@@ -1708,7 +1706,7 @@ trait Typers requires Analyzer {
else {
val ps = clazz.info.parents filter (p => p.symbol.name == mix)
if (ps.isEmpty) {
- if (settings.debug.value) System.out.println(clazz.info.parents map (.symbol.name));//debug
+ if (settings.debug.value) System.out.println(clazz.info.parents map (.symbol.name));//debug
error(tree.pos, ""+mix+" does not name a parent class of "+clazz)
ErrorType
} else if (ps.tail.isEmpty) {