summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-11-30 16:57:50 +0000
committerMartin Odersky <odersky@gmail.com>2005-11-30 16:57:50 +0000
commit634e743658f07343913457108339e5b93bb0ef14 (patch)
tree16f8e8116222893a475bb5e3c88b197d5e7c283b
parentc037162241748b0b19612051c6fded8dc81916ca (diff)
downloadscala-634e743658f07343913457108339e5b93bb0ef14.tar.gz
scala-634e743658f07343913457108339e5b93bb0ef14.tar.bz2
scala-634e743658f07343913457108339e5b93bb0ef14.zip
*** empty log message ***
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala5
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala10
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/UnPickler.scala4
-rwxr-xr-xsources/scala/tools/nsc/transform/ExplicitOuter.scala37
-rwxr-xr-xsources/scala/tools/nsc/transform/LambdaLift.scala2
-rwxr-xr-xsources/scala/tools/nsc/transform/UnCurry.scala45
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Contexts.scala16
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala8
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala7
9 files changed, 96 insertions, 38 deletions
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
index 92a4e05971..d47551b893 100644
--- a/sources/scala/tools/nsc/symtab/Flags.scala
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -51,7 +51,9 @@ object Flags {
final val PARAMACCESSOR = 0x20000000; // for value definitions: is an access method for a final val parameter
// for parameters: is a val parameter
- final val LABEL = 0x40000000; // symbol is a label. Set by TailCall
+ final val LABEL = 0x40000000; // method symbol is a label. Set by TailCall
+ final val INCONSTRUCTOR = 0x40000000; // class symbol is defined in this/superclass constructor.
+
final val CAPTURED = 0x80000000L; // variable is accessed from nested function. Set by LambdaLift
final val IS_ERROR = 0x100000000L; // symbol is an error symbol
@@ -63,7 +65,6 @@ object Flags {
final val EXPANDEDNAME = 0x1000000000L; // name has been expanded with class suffix
final val IMPLCLASS = 0x2000000000L; // symbol is an implementation class
final val TRANS_FLAG = 0x4000000000L; // transient flag guaranteed to be reset after each phase.
- final val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer
final val LOCKED = 0x8000000000L; // temporary flag to catch cyclic dependencies
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 80b037e068..132dafd6b2 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -163,6 +163,7 @@ import Flags._;
final def isAbstractType = isType && !isClass && hasFlag(DEFERRED);
final def isTypeParameterOrSkolem = isType && hasFlag(PARAM);
final def isTypeParameter = isTypeParameterOrSkolem && deSkolemize == this;
+ final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR);
final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME);
// startsWith necessary because name may grow when lifted and also because of anonymous function classes
final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes
@@ -192,10 +193,12 @@ import Flags._;
final def isModuleVar: boolean = isVariable && nme.isModuleVarName(name);
/** Is this symbol static (i.e. with no outer instance)? */
- final def isStatic: boolean = hasFlag(STATIC) || isRoot || owner.isStaticOwner;
+ final def isStatic: boolean =
+ hasFlag(STATIC) || isRoot || owner.isStaticOwner;
/** Does this symbol denote a class that defines static symbols? */
- final def isStaticOwner: boolean = isPackageClass || isStatic && isModuleClass;
+ final def isStaticOwner: boolean =
+ isPackageClass || isModuleClass && isStatic;
/** Is this symbol final?*/
final def isFinal: boolean =
@@ -260,6 +263,8 @@ import Flags._;
def owner: Symbol = rawowner;
final def owner_=(owner: Symbol): unit = { rawowner = owner }
+ def ownerChain: List[Symbol] = this :: owner.ownerChain;
+
def name: Name = rawname;
final def name_=(name: Name): unit = { rawname = name }
@@ -1017,6 +1022,7 @@ import Flags._;
override def toplevelClass: Symbol = this;
override def enclMethod: Symbol = this;
override def owner: Symbol = throw new Error();
+ override def ownerChain: List[Symbol] = List();
override def alternatives: List[Symbol] = List();
override def reset(completer: Type): unit = {}
def cloneSymbolImpl(owner: Symbol): Symbol = throw new Error();
diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 3205cb00c1..091e8024a8 100755
--- a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -177,12 +177,12 @@ abstract class UnPickler {
TypeBounds(readTypeRef(), readTypeRef())
case REFINEDtpe =>
val clazz = readSymbolRef();
+/*
val ps = until(end, readTypeRef);
val dcls = symScope(clazz);
new RefinedType(ps, dcls) { override def symbol = clazz }
-/* //todo replace with but need to rethink initialization first
- new RefinedType(until(end, readTypeRef), )) { override def symbol = clazz }
*/
+ new RefinedType(until(end, readTypeRef), symScope(clazz)) { override def symbol = clazz }
case CLASSINFOtpe =>
val clazz = readSymbolRef();
ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
diff --git a/sources/scala/tools/nsc/transform/ExplicitOuter.scala b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
index e68d68e77c..2c6e4272d9 100755
--- a/sources/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -24,6 +24,13 @@ abstract class ExplicitOuter extends InfoTransform {
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);
+
+ private def isStatic(clazz: Symbol) =
+ clazz.isPackageClass || outerClass(clazz).isStaticOwner;
+
/** The type transformation method:
* 1. Add an outer paramter to the formal parameters of a constructor or mixin constructor
* in a non-static class;
@@ -33,24 +40,23 @@ abstract class ExplicitOuter extends InfoTransform {
def transformInfo(sym: Symbol, tp: Type): Type = tp match {
case MethodType(formals, restpe) =>
if (sym.owner.isTrait && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED;
- if (sym.isConstructor && !sym.owner.isStatic)
- MethodType(formals ::: List(sym.owner.owner.enclClass.toInterface.thisType), restpe)
+ if (sym.isConstructor && !isStatic(sym.owner))
+ MethodType(formals ::: List(outerClass(sym.owner).toInterface.thisType), restpe)
else tp;
case ClassInfoType(parents, decls, clazz) =>
var decls1 = decls;
if (!(clazz hasFlag INTERFACE)) {
- if (!clazz.isStatic) {
+ if (!isStatic(clazz)) {
decls1 = new Scope(decls1.toList);
- val outerType = clazz.owner.enclClass.thisType;
val outerAcc = clazz.newMethod(clazz.pos, nme.OUTER);
if ((clazz hasFlag TRAIT) || (decls.toList exists (.isClass)))
outerAcc.expandName(clazz);
decls1 enter (
outerAcc setFlag (PARAMACCESSOR | ACCESSOR | STABLE)
- setInfo MethodType(List(), outerType));
+ setInfo MethodType(List(), outerClass(clazz).thisType));
decls1 enter (clazz.newValue(clazz.pos, nme.getterToLocal(outerAcc.name))
setFlag (LOCAL | PRIVATE | PARAMACCESSOR | (outerAcc getFlag EXPANDEDNAME))
- setInfo outerType);
+ setInfo outerClass(clazz).thisType);
}
if (clazz.isTrait) {
decls1 = new Scope(decls1.toList);
@@ -101,12 +107,10 @@ abstract class ExplicitOuter extends InfoTransform {
/** Select and apply outer accessor from `base'
*/
private def outerSelect(base: Tree): Tree = {
- assert(base.tpe != null, base);
- assert(base.tpe.symbol != null, base);
- val clazz = base.tpe.symbol.owner.enclClass;
+ val otp = outerClass(base.tpe.symbol).thisType;
Apply(
- Select(base, outerMember(base.tpe)) setType MethodType(List(), clazz.thisType),
- List()) setType clazz.thisType
+ Select(base, outerMember(base.tpe)) setType MethodType(List(), otp),
+ List()) setType otp
}
override def transform(tree: Tree): Tree = {
@@ -116,7 +120,7 @@ abstract class ExplicitOuter extends InfoTransform {
case Template(_, _) =>
outerParam = NoSymbol;
case DefDef(_, _, _, vparamss, _, _) =>
- if (tree.symbol.isConstructor && !(tree.symbol.owner.isStatic)) {
+ if (tree.symbol.isConstructor && !(isStatic(tree.symbol.owner))) {
val lastParam = vparamss.head.last;
assert(lastParam.name.startsWith(nme.OUTER), tree);
outerParam = lastParam.symbol
@@ -232,7 +236,7 @@ abstract class ExplicitOuter extends InfoTransform {
localTyper = localTyper.atOwner(tree, currentOwner);
var decls1 = decls;
if (!(currentOwner hasFlag INTERFACE)) {
- if (!currentOwner.isStatic)
+ if (!isStatic(currentOwner))
decls1 = decls1 ::: outerDefs(currentOwner); // (1)
if (currentOwner.isTrait)
decls1 = decls1 ::: List(mixinConstructorDef(currentOwner)) // (2)
@@ -242,7 +246,7 @@ abstract class ExplicitOuter extends InfoTransform {
case constrDef @ DefDef(mods, name, tparams, vparamss, tpt, rhs)
if (sym.isConstructor) =>
val vparamss1 =
- if (sym.owner.isStatic) vparamss
+ if (isStatic(sym.owner)) vparamss
else { // (4)
val outerField = outerMember(sym.owner.info).accessed;
val outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField.info;
@@ -257,14 +261,13 @@ abstract class ExplicitOuter extends InfoTransform {
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)
- && !sel.symbol.owner.isStatic) =>
+ if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) && !isStatic(sel.symbol.owner)) =>
val outerVal =
atPos(tree.pos) {
if (qual.isInstanceOf[This]) { assert(outerParam != NoSymbol); outerValue } // (8)
else {
var pre = qual.tpe.prefix;
- if (pre == NoPrefix) pre = sym.owner.owner.enclClass.thisType;
+ if (pre == NoPrefix) pre = outerClass(sym.owner).thisType;
gen.mkQualifier(pre)
}
}
diff --git a/sources/scala/tools/nsc/transform/LambdaLift.scala b/sources/scala/tools/nsc/transform/LambdaLift.scala
index 04baae1782..21a0870bd0 100755
--- a/sources/scala/tools/nsc/transform/LambdaLift.scala
+++ b/sources/scala/tools/nsc/transform/LambdaLift.scala
@@ -207,7 +207,7 @@ abstract class LambdaLift extends InfoTransform {
case None => searchIn(outer(owner))
}
}
- if (settings.debug.value) log("proxy " + sym + " in " + sym.owner + " from " + currentOwner + " " + enclMethOrClass(sym.owner));//debug
+ if (settings.debug.value) log("proxy " + sym + " in " + sym.owner + " from " + currentOwner.ownerChain + " " + enclMethOrClass(sym.owner));//debug
if (enclMethOrClass(sym.owner) == enclMethOrClass(currentOwner)) sym
else searchIn(currentOwner)
}
diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala
index 4a22f9711f..c778be212d 100755
--- a/sources/scala/tools/nsc/transform/UnCurry.scala
+++ b/sources/scala/tools/nsc/transform/UnCurry.scala
@@ -37,8 +37,6 @@ abstract class UnCurry extends InfoTransform {
def newTransformer(unit: CompilationUnit): Transformer = new UnCurryTransformer(unit);
override def changesBaseClasses = false;
- var needTryLift = false;
-
private val uncurry = new TypeMap {
def apply(tp: Type): Type = tp match {
case MethodType(formals, MethodType(formals1, restpe)) =>
@@ -65,7 +63,9 @@ abstract class UnCurry extends InfoTransform {
class UnCurryTransformer(unit: CompilationUnit) extends Transformer {
+ private var needTryLift = false;
private var inPattern = false;
+ private var inConstructorFlag = 0;
override def transform(tree: Tree): Tree = try { //debug
postTransform(mainTransform(tree));
@@ -121,7 +121,8 @@ abstract class UnCurry extends InfoTransform {
* def isDefinedAt(x: T): boolean = true
*/
def transformFunction(fun: Function): Tree = {
- val anonClass = fun.symbol.owner.newAnonymousFunctionClass(fun.pos) setFlag (FINAL | SYNTHETIC);
+ val anonClass = fun.symbol.owner.newAnonymousFunctionClass(fun.pos)
+ setFlag (FINAL | SYNTHETIC | inConstructorFlag);
val formals = fun.tpe.typeArgs.init;
val restpe = fun.tpe.typeArgs.last;
anonClass setInfo ClassInfoType(
@@ -197,6 +198,7 @@ abstract class UnCurry extends InfoTransform {
}
def mainTransform(tree: Tree): Tree = {
+
def withNeedLift(needLift: Boolean)(f: => Tree): Tree = {
val savedNeedTryLift = needTryLift;
needTryLift = needLift;
@@ -205,9 +207,36 @@ abstract class UnCurry extends InfoTransform {
t
}
+ def withInConstructorFlag(inConstructorFlag: int)(f: => Tree): Tree = {
+ val savedInConstructorFlag = this.inConstructorFlag;
+ this.inConstructorFlag = inConstructorFlag;
+ val t = f;
+ this.inConstructorFlag = savedInConstructorFlag;
+ t
+ }
+
tree match {
- case DefDef(_, _, _, _, _, _) =>
- withNeedLift(false) { super.transform(tree) }
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ withNeedLift(false) {
+ if (tree.symbol.isConstructor) {
+ atOwner(tree.symbol) {
+ val rhs1 = rhs match {
+ case Block(stat :: stats, expr) =>
+ copy.Block(
+ rhs,
+ withInConstructorFlag(INCONSTRUCTOR) { transform(stat) } :: transformTrees(stats),
+ transform(expr));
+ case _ =>
+ withInConstructorFlag(INCONSTRUCTOR) { transform(rhs) }
+ }
+ copy.DefDef(
+ tree, mods, name, transformAbsTypeDefs(tparams),
+ transformValDefss(vparamss), transform(tpt), rhs1)
+ }
+ } else {
+ super.transform(tree)
+ }
+ }
case ValDef(_, _, _, rhs)
if (!tree.symbol.owner.isSourceMethod) =>
@@ -249,10 +278,14 @@ abstract class UnCurry extends InfoTransform {
val pat1 = transform(pat);
inPattern = false;
copy.CaseDef(tree, pat1, transform(guard), transform(body))
+
case fun @ Function(_, _) =>
mainTransform(transformFunction(fun))
+
+ case Template(_, _) =>
+ withInConstructorFlag(0) { super.transform(tree) }
+
case _ =>
- assert(!tree.isInstanceOf[Function]);
val tree1 = super.transform(tree);
if (isByNameRef(tree1))
typed(atPos(tree1.pos)(
diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala
index 8035c227a0..3130252f74 100755
--- a/sources/scala/tools/nsc/typechecker/Contexts.scala
+++ b/sources/scala/tools/nsc/typechecker/Contexts.scala
@@ -64,6 +64,8 @@ import scala.tools.nsc.util.Position;
var imports: List[ImportInfo] = List();
var prefix: Type = NoPrefix;
+ var inConstructorSuffix = false; // are we in a secondary constructor
+ // after the this constructor call?
var reportAmbiguousErrors = false;
var reportGeneralErrors = false;
var checking = false;
@@ -85,10 +87,12 @@ import scala.tools.nsc.util.Position;
tree match {
case Template(_, _) | PackageDef(_, _) =>
c.enclClass = c;
- c.prefix = skolemizedThisType(this.tree, this.prefix, c.owner)
+ c.prefix = skolemizedThisType(this.tree, this.prefix, c.owner);
+ c.inConstructorSuffix = false;
case _ =>
c.enclClass = this.enclClass;
- c.prefix = if (c.owner != this.owner && c.owner.isTerm) NoPrefix else this.prefix
+ c.prefix = if (c.owner != this.owner && c.owner.isTerm) NoPrefix else this.prefix;
+ c.inConstructorSuffix = this.inConstructorSuffix;
}
c.variance = this.variance;
c.depth = if (scope == this.scope) this.depth else this.depth + 1;
@@ -129,13 +133,19 @@ import scala.tools.nsc.util.Position;
c
}
- def constructorContext = {
+ def makeConstructorContext = {
val baseContext = enclClass.outer;
val argContext = baseContext.makeNewScope(tree, owner);
for (val sym <- scope.toList) argContext.scope enter sym;
argContext
}
+ def makeConstructorSuffixContext = {
+ val c = make(tree);
+ c.inConstructorSuffix = true;
+ c
+ }
+
def skolemizedThisType(encl: Tree, pre: Type, clazz: Symbol): Type = if (settings.Xgadt.value) {
encl match {
case ClassDef(_, _, tparamdefs, _, _) =>
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index ae41a3067b..a40a6ea5d8 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -95,12 +95,16 @@ trait Namers: Analyzer {
}
}
+ private def inConstructorFlag: long =
+ if (context.owner.isConstructor && !context.inConstructorSuffix) INCONSTRUCTOR
+ else 0l;
+
private def enterClassSymbol(pos: int, mods: int, name: Name): Symbol = {
var c: Symbol = context.scope.lookup(name);
if (c.isType && c.isExternal && context.scope == c.owner.info.decls) {
updatePosFlags(c, pos, mods);
} else {
- c = enterInScope(context.owner.newClass(pos, name).setFlag(mods))
+ c = enterInScope(context.owner.newClass(pos, name).setFlag(mods | inConstructorFlag))
}
if (c.owner.isPackageClass) currentRun.symSource(c) = context.unit.source.getFile();
c
@@ -115,7 +119,7 @@ trait Namers: Analyzer {
context.scope.unlink(m);
m = context.owner.newModule(pos, name);
m.setFlag(mods);
- m.moduleClass.setFlag(mods);
+ m.moduleClass.setFlag(mods | inConstructorFlag);
enterInScope(m)
}
if (m.owner.isPackageClass) currentRun.symSource(m) = context.unit.source.getFile();
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 97a56f75f4..0df5c37f30 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -581,7 +581,7 @@ import collection.mutable.HashMap;
def typedValDef(vdef: ValDef): ValDef = {
val sym = vdef.symbol;
val typer1 = if (sym.hasFlag(PARAM) && sym.owner.isConstructor)
- newTyper(context.constructorContext)
+ newTyper(context.makeConstructorContext)
else this;
var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt));
checkNonCyclic(vdef.pos, tpt1.tpe, sym);
@@ -676,7 +676,8 @@ import collection.mutable.HashMap;
val result = ddef.rhs match {
case Block(stat :: stats, expr) =>
val stat1 = typedSuperCall(stat);
- typed(copy.Block(ddef.rhs, stats, expr), UnitClass.tpe) match {
+ newTyper(context.makeConstructorSuffixContext).typed(
+ copy.Block(ddef.rhs, stats, expr), UnitClass.tpe) match {
case block1 @ Block(stats1, expr1) =>
copy.Block(block1, stat1 :: stats1, expr1)
}
@@ -840,7 +841,7 @@ import collection.mutable.HashMap;
}
def typedArg(arg: Tree, pt: Type): Tree = {
- val argTyper = if ((mode & INCONSTRmode) != 0) newTyper(context.constructorContext)
+ val argTyper = if ((mode & INCONSTRmode) != 0) newTyper(context.makeConstructorContext)
else this;
argTyper.typed(arg, mode & stickyModes, pt)
}