summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-09-20 17:45:45 +0000
committerMartin Odersky <odersky@gmail.com>2005-09-20 17:45:45 +0000
commit3761cb4b3a1c03f5daa2fac28d19f6f398072ffe (patch)
treeaf915e38284d71f68b9986f7050e0aa5555345f0 /sources
parenta2231f55a00c96ecf670e0f02ed026c0ff956ecc (diff)
downloadscala-3761cb4b3a1c03f5daa2fac28d19f6f398072ffe.tar.gz
scala-3761cb4b3a1c03f5daa2fac28d19f6f398072ffe.tar.bz2
scala-3761cb4b3a1c03f5daa2fac28d19f6f398072ffe.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rwxr-xr-xsources/scala/tools/nsc/Global.scala13
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeGen.scala19
-rw-r--r--sources/scala/tools/nsc/ast/TreePrinters.scala6
-rw-r--r--sources/scala/tools/nsc/symtab/InfoTransformers.scala5
-rwxr-xr-xsources/scala/tools/nsc/symtab/Scopes.scala11
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolTable.scala1
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala27
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala39
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rwxr-xr-xsources/scala/tools/nsc/transform/Erasure.scala70
-rwxr-xr-xsources/scala/tools/nsc/transform/ExplicitOuter.scala1
-rwxr-xr-xsources/scala/tools/nsc/transform/Flatten.scala14
-rwxr-xr-xsources/scala/tools/nsc/transform/InfoTransform.scala3
-rwxr-xr-xsources/scala/tools/nsc/transform/Mixin.scala34
-rwxr-xr-xsources/scala/tools/nsc/transform/OverridingPairs.scala126
-rw-r--r--sources/scala/tools/nsc/transform/SyntheticMethods.scala124
-rwxr-xr-xsources/scala/tools/nsc/transform/UnCurry.scala1
-rw-r--r--sources/scala/tools/nsc/typechecker/Analyzer.scala3
-rwxr-xr-xsources/scala/tools/nsc/typechecker/RefChecks.scala12
-rwxr-xr-xsources/scala/tools/nsc/typechecker/SyntheticMethods.scala108
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala5
21 files changed, 415 insertions, 209 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
index a53da84903..30e05a306d 100755
--- a/sources/scala/tools/nsc/Global.scala
+++ b/sources/scala/tools/nsc/Global.scala
@@ -66,6 +66,10 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this
}
+ object overridingPairs extends OverridingPairs {
+ val global: Global.this.type = Global.this
+ }
+
val copy = new LazyTreeCopier();
type AttrInfo = Pair[Type, List[Any]];
@@ -179,10 +183,11 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this
}
+/*
object syntheticMethods extends SyntheticMethods {
val global: Global.this.type = Global.this
}
-
+*/
object refchecks extends RefChecks {
val global: Global.this.type = Global.this;
}
@@ -240,10 +245,10 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
}
def phaseDescriptors: List[SubComponent] = List(
- analyzer.namerFactory, // needs to be first
- analyzer.typerFactory, // needs to be second
+ analyzer.namerFactory,
+ analyzer.typerFactory,
pickler,
- syntheticMethods,
+// syntheticMethods,
refchecks,
uncurry,
tailCalls,
diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala
index a2541d8e74..d5f465dcf3 100755
--- a/sources/scala/tools/nsc/ast/TreeGen.scala
+++ b/sources/scala/tools/nsc/ast/TreeGen.scala
@@ -84,17 +84,22 @@ abstract class TreeGen {
def This(sym: Symbol): Tree =
global.This(sym.name) setSymbol sym setType sym.thisType;
- def Ident(sym: Symbol) = {
+ def Ident(sym: Symbol): Tree = {
assert(sym.isTerm);
global.Ident(sym.name) setSymbol sym setType sym.tpe;
}
- def Select(qual: Tree, sym: Symbol) = {
- assert(sym.isTerm);
- val result = global.Select(qual, sym.name) setSymbol sym;
- if (qual.tpe != null) result setType qual.tpe.memberType(sym);
- result
- }
+ def Select(qual: Tree, sym: Symbol): Tree =
+ if (qual.symbol != null &&
+ (qual.symbol.name.toTermName == nme.ROOT ||
+ qual.symbol.name.toTermName == nme.EMPTY_PACKAGE_NAME)) {
+ this.Ident(sym)
+ } else {
+ assert(sym.isTerm);
+ val result = global.Select(qual, sym.name) setSymbol sym;
+ if (qual.tpe != null) result setType qual.tpe.memberType(sym);
+ result
+ }
/** Builds an instance test with given value and type. */
def mkIsInstanceOf(value: Tree, tpe: Type, erased: Boolean): Tree = {
diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala
index 9678a70c9b..bda8158881 100644
--- a/sources/scala/tools/nsc/ast/TreePrinters.scala
+++ b/sources/scala/tools/nsc/ast/TreePrinters.scala
@@ -222,11 +222,7 @@ abstract class TreePrinters {
print("this");
case Select(qualifier, name) =>
- if (global.settings.debug.value || qualifier.symbol == null ||
- (!qualifier.symbol.isRoot && !qualifier.symbol.isEmptyPackage)) {
- print(qualifier); print(".");
- }
- print(symName(tree, name))
+ print(qualifier); print("."); print(symName(tree, name))
case Ident(name) =>
print(symName(tree, name))
diff --git a/sources/scala/tools/nsc/symtab/InfoTransformers.scala b/sources/scala/tools/nsc/symtab/InfoTransformers.scala
index d74a099537..bb03eaac8e 100644
--- a/sources/scala/tools/nsc/symtab/InfoTransformers.scala
+++ b/sources/scala/tools/nsc/symtab/InfoTransformers.scala
@@ -8,10 +8,11 @@ package scala.tools.nsc.symtab;
abstract class InfoTransformers: SymbolTable {
abstract class InfoTransformer {
- private var prev: InfoTransformer = this;
- private var next: InfoTransformer = this;
+ var prev: InfoTransformer = this;
+ var next: InfoTransformer = this;
val phase: Phase;
+ val changesBaseClasses: boolean;
def transform(sym: Symbol, tpe: Type): Type;
def insert(that: InfoTransformer): unit = {
diff --git a/sources/scala/tools/nsc/symtab/Scopes.scala b/sources/scala/tools/nsc/symtab/Scopes.scala
index cc2da304c0..47c1bcb226 100755
--- a/sources/scala/tools/nsc/symtab/Scopes.scala
+++ b/sources/scala/tools/nsc/symtab/Scopes.scala
@@ -7,7 +7,7 @@ package scala.tools.nsc.symtab;
abstract class Scopes: SymbolTable {
- abstract class ScopeEntry(val sym: Symbol, val owner: Scope) {
+ class ScopeEntry(val sym: Symbol, val owner: Scope) {
/** the next entry in the hash bucket
*/
@@ -21,9 +21,11 @@ abstract class Scopes: SymbolTable {
override def toString(): String = sym.toString();
}
- def newScopeEntry(sym: Symbol, owner: Scope) = new ScopeEntry(sym, owner) {
- next = owner.elems;
- owner.elems = this;
+ def newScopeEntry(sym: Symbol, owner: Scope): ScopeEntry = {
+ val e = new ScopeEntry(sym, owner);
+ e.next = owner.elems;
+ owner.elems = e;
+ e
}
object NoScopeEntry extends ScopeEntry(NoSymbol, null);
@@ -98,7 +100,6 @@ abstract class Scopes: SymbolTable {
/** enter a scope entry
*/
def enter(e: ScopeEntry): unit = {
- elems = e;
elemsCache = null;
if (hashtable != null) {
val i = e.sym.name.start & HASHMASK;
diff --git a/sources/scala/tools/nsc/symtab/SymbolTable.scala b/sources/scala/tools/nsc/symtab/SymbolTable.scala
index a7c0a61328..ba15a14b19 100755
--- a/sources/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/sources/scala/tools/nsc/symtab/SymbolTable.scala
@@ -37,6 +37,7 @@ abstract class SymbolTable extends Names
var infoTransformers = new InfoTransformer {
val phase = NoPhase;
+ val changesBaseClasses = true;
def transform(sym: Symbol, tpe: Type): Type = tpe;
}
}
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 0a27a03948..abd68a107c 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -115,6 +115,7 @@ abstract class Symbols: SymbolTable {
final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR);
final def isConstructor = isTerm && (name == nme.CONSTRUCTOR) || (name == nme.MIXIN_CONSTRUCTOR);
final def isModule = isTerm && hasFlag(MODULE);
+ final def isStaticModule = isModule && isStatic && !isMethod;
final def isPackage = isModule && hasFlag(PACKAGE);
final def isThisSym = isTerm && name == nme.this_;
final def isError = hasFlag(IS_ERROR);
@@ -128,6 +129,7 @@ abstract class Symbols: SymbolTable {
final def isModuleClass = isClass && hasFlag(MODULE);
final def isPackageClass = isClass && hasFlag(PACKAGE);
final def isRoot = isPackageClass && name == nme.ROOT.toTypeName;
+ final def isRootPackage = isPackage && name == nme.ROOT;
final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME;
final def isEmptyPackageClass = isPackageClass && name == nme.EMPTY_PACKAGE_NAME.toTypeName;
@@ -483,7 +485,7 @@ abstract class Symbols: SymbolTable {
*/
final def linkedClass: Symbol = {
if (owner.isPackageClass)
- owner.info.decl(name.toTypeName).suchThat(sym => sym.rawInfo != NoType)
+ owner.info.decl(name.toTypeName).suchThat(sym => sym.rawInfo ne NoType)
else NoSymbol;
}
@@ -493,7 +495,7 @@ abstract class Symbols: SymbolTable {
final def linkedModule: Symbol =
if (owner.isPackageClass)
owner.info.decl(name.toTermName).suchThat(
- sym => (sym hasFlag MODULE) && (sym.rawInfo != NoType));
+ sym => (sym hasFlag MODULE) && (sym.rawInfo ne NoType));
else NoSymbol;
/** The top-level class containing this symbol */
@@ -504,7 +506,7 @@ abstract class Symbols: SymbolTable {
final def linkedSym: Symbol =
if (isTerm) linkedClass
else if (isClass && owner.isPackageClass)
- owner.info.decl(name.toTermName).suchThat(sym => sym.rawInfo != NoType)
+ owner.info.decl(name.toTermName).suchThat(sym => sym.rawInfo ne NoType)
else NoSymbol;
final def toInterface: Symbol =
@@ -723,6 +725,17 @@ abstract class Symbols: SymbolTable {
private var referenced: Symbol = NoSymbol;
+ override def owner: Symbol =
+ if (phase.flatClasses && hasFlag(MODULE) && !hasFlag(METHOD) &&
+ rawowner != NoSymbol && !rawowner.isPackageClass) rawowner.owner
+ else rawowner;
+
+ override def name: Name =
+ if (phase.flatClasses && hasFlag(MODULE) && !hasFlag(METHOD) &&
+ rawowner != NoSymbol && !rawowner.isPackageClass)
+ newTermName(rawowner.name.toString() + "$" + rawname);
+ else rawname;
+
def cloneSymbolImpl(owner: Symbol): Symbol = {
val clone = new TermSymbol(owner, pos, name);
clone.referenced = referenced;
@@ -758,7 +771,7 @@ abstract class Symbols: SymbolTable {
private var tpeCache: Type = _;
private var tpePhase: Phase = null;
override def tpe: Type = {
- assert(tpeCache != NoType, this);
+ assert(tpeCache ne NoType, this);
if (tpePhase != phase) {
if (isValid(tpePhase)) {
tpePhase = phase
@@ -805,12 +818,12 @@ abstract class Symbols: SymbolTable {
thissym = this;
}
+ private var flatname = nme.EMPTY;
+
override def owner: Symbol =
if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) rawowner.owner
else rawowner;
- private var flatname = nme.EMPTY;
-
override def name: Name =
if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) {
if (flatname == nme.EMPTY) {
@@ -875,7 +888,7 @@ abstract class Symbols: SymbolTable {
/** An object repreesenting a missing symbol */
object NoSymbol extends Symbol(null, Position.NOPOS, nme.NOSYMBOL) {
super.setInfo(NoType);
- override def setInfo(info: Type): this.type = { assert(info == NoType); this }
+ override def setInfo(info: Type): this.type = { assert(info eq NoType); this }
override def enclClass: Symbol = this;
override def toplevelClass: Symbol = this;
override def enclMethod: Symbol = this;
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
index 366d9995b2..31126f8169 100755
--- a/sources/scala/tools/nsc/symtab/Types.scala
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -194,12 +194,12 @@ abstract class Types: SymbolTable {
/** Is this type a subtype of that type? */
def <:<(that: Type): boolean =
if (explainSwitch) explain("<", isSubType, this, that)
- else this == that || isSubType(this, that);
+ else (this eq that) || isSubType(this, that);
/** Is this type equivalent to that type? */
def =:=(that: Type): boolean =
if (explainSwitch) explain("<", isSameType, this, that)
- else this == that || isSameType(this, that);
+ else (this eq that) || isSameType(this, that);
/** Does this type implement symbol `sym' with same or stronger type? */
def specializes(sym: Symbol): boolean =
@@ -494,9 +494,6 @@ abstract class Types: SymbolTable {
/** A common base class for intersection types and class types
*/
abstract class CompoundType extends Type {
- override val parents: List[Type];
- override val decls: Scope;
-
assert(!parents.exists (.isInstanceOf[TypeBounds]), this);//debug
private var closureCache: Array[Type] = _;
@@ -519,7 +516,7 @@ abstract class Types: SymbolTable {
val p = closurePhase;
if (p != phase) {
closurePhase = phase;
- if (!isValid(p)) {
+ if (!isValidForBaseClasses(p)) {
closureCache = null;
closureCache = computeClosure
}
@@ -559,7 +556,7 @@ abstract class Types: SymbolTable {
val p = baseClassesPhase;
if (p != phase) {
baseClassesPhase = phase;
- if (!isValid(p)) {
+ if (!isValidForBaseClasses(p)) {
baseClassesCache = null;
baseClassesCache = computeBaseClasses;
}
@@ -639,7 +636,7 @@ abstract class Types: SymbolTable {
val p = parentsPhase;
if (p != phase) {
parentsPhase = phase;
- if (!isValid(p)) {
+ if (!isValidForBaseClasses(p)) {
parentsCache = sym.info.parents map transform
}
}
@@ -668,7 +665,7 @@ abstract class Types: SymbolTable {
val p = closurePhase;
if (p != phase) {
closurePhase = phase;
- if (!isValid(p)) {
+ if (!isValidForBaseClasses(p)) {
typerefClosureCount = typerefClosureCount + 1;
closureCache =
if (sym.isAbstractType) addClosure(this, transform(bounds.hi).closure)
@@ -770,7 +767,7 @@ abstract class Types: SymbolTable {
case class TypeVar(origin: Type, constr: TypeConstraint) extends Type {
override def symbol = origin.symbol;
override def toString(): String =
- if (constr.inst == NoType) "?" + origin else constr.inst.toString();
+ if (constr.inst eq NoType) "?" + origin else constr.inst.toString();
}
/** A class representing an as-yet unevaluated type.
@@ -1114,17 +1111,17 @@ abstract class Types: SymbolTable {
/** A map to compute the asSeenFrom method */
class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap {
def apply(tp: Type): Type =
- if (pre == NoType || pre == NoPrefix || !clazz.isClass) tp
+ if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
else tp match {
case ThisType(sym) =>
def toPrefix(pre: Type, clazz: Symbol): Type =
- if (pre == NoType || pre == NoPrefix || !clazz.isClass) tp
+ if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
else if ((sym isSubClass clazz) && (pre.widen.symbol isSubClass sym)) pre
else toPrefix(pre.baseType(clazz).prefix, clazz.owner);
toPrefix(pre, clazz)
case TypeRef(prefix, sym, args) if (sym.isTypeParameter) =>
def toInstance(pre: Type, clazz: Symbol): Type =
- if (pre == NoType || pre == NoPrefix || !clazz.isClass) tp
+ if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
else {
val symclazz = sym.owner;
def throwError =
@@ -1256,10 +1253,20 @@ abstract class Types: SymbolTable {
// Helper Methods -------------------------------------------------------------
final def isValid(p: Phase): boolean =
- p != null &&
- (if (phase.id > p.id) infoTransformers.nextFrom(p).phase.id >= phase.id
- else infoTransformers.nextFrom(phase).phase.id >= p.id);
+ p != null && {
+ if (phase.id > p.id) infoTransformers.nextFrom(p).phase.id >= phase.id
+ else infoTransformers.nextFrom(phase).phase.id >= p.id
+ }
+ final def isValidForBaseClasses(p: Phase): boolean = {
+ def noChangeInBaseClasses(it: InfoTransformer, limit: Phase): boolean =
+ it.phase.id >= limit.id ||
+ !it.changesBaseClasses && noChangeInBaseClasses(it.next, limit);
+ p != null && {
+ if (phase.id > p.id) noChangeInBaseClasses(infoTransformers.nextFrom(p), phase)
+ else noChangeInBaseClasses(infoTransformers.nextFrom(phase), p)
+ }
+ }
/** Do tp1 and tp2 denote equivalent types? */
def isSameType(tp1: Type, tp2: Type): boolean = (tp1 eq tp2) || {
diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index a1da6db8fa..beb70991a5 100755
--- a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -289,7 +289,7 @@ abstract class ClassfileParser {
if (name == nme.CONSTRUCTOR)
info match {
case MethodType(formals, restpe) =>
- assert(restpe == definitions.UnitClass.tpe);
+ assert(restpe.symbol == definitions.UnitClass);
info = MethodType(formals, clazz.tpe)
}
val sym = getOwner(jflags)
diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala
index b50edd055b..f0a7e0d1f8 100755
--- a/sources/scala/tools/nsc/transform/Erasure.scala
+++ b/sources/scala/tools/nsc/transform/Erasure.scala
@@ -337,6 +337,24 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
e = e.next
}
+ val opc = new overridingPairs.Cursor(root) {
+ override def exclude(sym: Symbol): boolean =
+ !sym.isTerm || (sym hasFlag (PRIVATE | BRIDGE)) || super.exclude(sym);
+ override def matches(sym1: Symbol, sym2: Symbol): boolean =
+ atPhase(phase.next)(sym1.tpe =:= sym2.tpe)
+ }
+ while (opc.hasNext) {
+ if (!atPhase(refchecksPhase.next)(
+ root.thisType.memberType(opc.overriding) matches
+ root.thisType.memberType(opc.overridden))) {
+ if (settings.debug.value) log("" + opc.overriding.locationString + " " + opc.overriding.infosString + opc.overridden.locationString + " " + opc.overridden.infosString);
+ doubleDefError(opc.overriding, opc.overridden)
+ }
+ opc.next
+ }
+ }
+
+/*
for (val bc <- root.info.baseClasses.tail; val other <- bc.info.decls.toList) {
if (other.isTerm && !other.isConstructor && !(other hasFlag (PRIVATE | BRIDGE))) {
for (val member <- root.info.nonPrivateMember(other.name).alternatives) {
@@ -351,7 +369,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
}
}
- }
+*/
/** Add bridge definitions to a template. This means:
* If there is a concrete member `m' which overrides a member in a base class of the template,
@@ -367,7 +385,19 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
val bridgesScope = new Scope();
val bridgeTarget = new HashMap[Symbol, Symbol];
var bridges: List[Tree] = List();
- for (val bc <- site.baseClasses.tail; val other <- bc.info.members) {
+ val opc = atPhase(phase.prev) { // to avoid DEFERRED flags for interfaces
+ new overridingPairs.Cursor(owner) {
+ override def parents: List[Type] = List(owner.info.parents.head);
+ override def exclude(sym: Symbol): boolean =
+ !sym.isMethod || (sym hasFlag (PRIVATE | BRIDGE)) || super.exclude(sym);
+ }
+ }
+ while (opc.hasNext) {
+ val member = opc.overriding;
+ val other = opc.overridden;
+ if (!(member hasFlag DEFERRED)) {
+/*
+ for (val bc <- site.baseClasses.tail; val other <- bc.info.decls.toList) {
if (other.isMethod && !other.isConstructor) {
for (val member <- site.nonPrivateMember(other.name).alternatives) {
if (member != other &&
@@ -375,6 +405,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
(site.memberType(member) matches site.memberType(other)) &&
!(site.parents exists (p =>
(p.symbol isSubClass member.owner) && (p.symbol isSubClass other.owner)))) {
+*/
val otpe = erasure(other.tpe);
if (!(otpe =:= erasure(member.tpe))) {
var e = bridgesScope.lookupEntry(member.name);
@@ -386,31 +417,43 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
setFlag (member.flags | BRIDGE)
resetFlag ACCESSOR
setInfo otpe;
- if (settings.debug.value)
- log("generating bridge from " + other + ":" + otpe + other.locationString + " to " + member + ":" + erasure(member.tpe) + "=" + bridge + ":" + bridge.tpe);
bridgeTarget(bridge) = member;
bridgesScope enter bridge;
bridges =
atPhase(phase.next) {
atPos(bridge.pos) {
- DefDef(bridge, vparamss =>
- member.tpe match {
- case MethodType(List(), ConstantType(c)) => Literal(c)
- case _ =>
- ((Select(This(owner), member): Tree) /: vparamss)
- ((fun, vparams) => Apply(fun, vparams map Ident))
- })
+ val bridgeDef =
+ DefDef(bridge, vparamss =>
+ member.tpe match {
+ case MethodType(List(), ConstantType(c)) => Literal(c)
+ case _ =>
+ ((Select(This(owner), member): Tree) /: vparamss)
+ ((fun, vparams) => Apply(fun, vparams map Ident))
+ });
+ if (settings.debug.value)
+ log("generating bridge from " + other + ":" + otpe + other.locationString + " to " + member + ":" + erasure(member.tpe) + member.locationString + " =\n " + bridgeDef);
+ bridgeDef
}
} :: bridges;
}
}
- }
+/*
+ }
}
+*/
}
+ opc.next
}
bridges
}
+ def addBridges(stats: List[Tree], base: Symbol): List[Tree] =
+ if (base.isTrait) stats
+ else {
+ val bridges = bridgeDefs(base);
+ if (bridges.isEmpty) stats else stats ::: bridges
+ }
+
/** Transform tree at phase `erasure' before retyping it. This entails the following:
* - Remove all type parameters in class and method definitions.
* - Remove all abstract and alias type definitions.
@@ -438,9 +481,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
// leave type tests/type casts, remove all other type applications
fun
case Template(parents, body) =>
+ assert(!currentOwner.isImplClass);
//System.out.println("checking no dble defs " + tree);//DEBUG
checkNoDoubleDefs(tree.symbol.owner);
- copy.Template(tree, parents, body ::: bridgeDefs(currentOwner));
+ copy.Template(tree, parents, addBridges(body, currentOwner));
case _ =>
tree
}
diff --git a/sources/scala/tools/nsc/transform/ExplicitOuter.scala b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
index 469cabdcb7..5796f1c6f6 100755
--- a/sources/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -19,6 +19,7 @@ abstract class ExplicitOuter extends InfoTransform {
/** the following two members override abstract members in Transform */
val phaseName: String = "explicitouter";
+ override def changesBaseClasses = false;
final val needSuperAccessors = false;
diff --git a/sources/scala/tools/nsc/transform/Flatten.scala b/sources/scala/tools/nsc/transform/Flatten.scala
index 6a66c86c41..0af811cf3f 100755
--- a/sources/scala/tools/nsc/transform/Flatten.scala
+++ b/sources/scala/tools/nsc/transform/Flatten.scala
@@ -13,6 +13,7 @@ import collection.mutable.HashMap;
abstract class Flatten extends InfoTransform {
import global._;
import definitions._;
+ import posAssigner.atPos;
/** the following two members override abstract members in Transform */
val phaseName: String = "flatten";
@@ -45,8 +46,9 @@ abstract class Flatten extends InfoTransform {
atPhase(phase.next)(oldowner.info);
parents1 = List.mapConserve(parents)(this);
for (val sym <- decls.toList) {
- if (sym.isTerm) decls1 enter sym
- else if (sym.isClass) {
+ if (sym.isTerm && !sym.isStaticModule) {
+ decls1 enter sym
+ } else if (sym.isClass) {
liftClass(sym);
if (sym.needsImplClass) liftClass(erasure.implClass(sym))
}
@@ -91,14 +93,22 @@ abstract class Flatten extends InfoTransform {
val mix1 = if (ps.head.symbol.isNestedClass) atPhase(phase.next)(ps.head.symbol.name)
else mix;
copy.Super(tree, qual, mix1)
+ case Select(qual, name) if (sym.isStaticModule && !sym.owner.isPackageClass) =>
+ atPhase(phase.next) {
+ atPos(tree.pos) {
+ gen.mkRef(sym)
+ }
+ }
case _ =>
tree
}
tree1 setType flattened(tree1.tpe);
+/*
if (sym != null && sym.isNestedClass && !(sym hasFlag LIFTED)) {
liftClass(sym);//todo: remove
if (sym.implClass != NoSymbol) liftClass(sym.implClass);
}
+*/
tree1
}
diff --git a/sources/scala/tools/nsc/transform/InfoTransform.scala b/sources/scala/tools/nsc/transform/InfoTransform.scala
index c6d2997c65..5710dc7483 100755
--- a/sources/scala/tools/nsc/transform/InfoTransform.scala
+++ b/sources/scala/tools/nsc/transform/InfoTransform.scala
@@ -15,9 +15,12 @@ abstract class InfoTransform extends Transform {
override def newPhase(prev: scala.tools.nsc.Phase): StdPhase = new Phase(prev);
+ protected def changesBaseClasses = true;
+
class Phase(prev: scala.tools.nsc.Phase) extends super.Phase(prev) {
val infoTransformer = new InfoTransformer {
val phase = Phase.this;
+ val changesBaseClasses = InfoTransform.this.changesBaseClasses;
def transform(sym: Symbol, tpe: Type): Type = transformInfo(sym, tpe);
}
infoTransformers.insert(infoTransformer)
diff --git a/sources/scala/tools/nsc/transform/Mixin.scala b/sources/scala/tools/nsc/transform/Mixin.scala
index 5c627fa2d0..ff56fcfd2b 100755
--- a/sources/scala/tools/nsc/transform/Mixin.scala
+++ b/sources/scala/tools/nsc/transform/Mixin.scala
@@ -52,16 +52,6 @@ abstract class Mixin extends InfoTransform {
decls1 enter member;
member
}
- def addPackageClassMembers = {
- for (val sym <- decls.toList) {
- if (sym.isImplClass) {
- sym setFlag lateMODULE | notABSTRACT;
- addMember(
- clazz.newModule(sym.pos, sym.name.toTermName, sym.asInstanceOf[ClassSymbol])
- setInfo sym.tpe)
- }
- }
- }
def addLateInterfaceMembers = {
def newGetter(field: Symbol): Symbol =
clazz.newMethod(field.pos, nme.getterName(field.name))
@@ -85,7 +75,7 @@ abstract class Mixin extends InfoTransform {
var setter = member.setter(clazz);
if (setter == NoSymbol) setter = addMember(newSetter(member));
}
- } else if ((member hasFlag LIFTED) && !(member hasFlag PRIVATE)) {
+ } else if ((member hasFlag (LIFTED | BRIDGE)) && !(member hasFlag PRIVATE)) {
member.expandName(clazz);
addMember(member.cloneSymbol(clazz));
}
@@ -120,7 +110,7 @@ abstract class Mixin extends InfoTransform {
val member1 = addMember(member.cloneSymbol(clazz)) setFlag MIXEDIN;
assert(member1.alias != NoSymbol, member1);
member1.asInstanceOf[TermSymbol] setAlias rebindSuper(clazz, member.alias, bc);
- } else if (member.isMethod && member.isModule && !(member hasFlag LIFTED)) {
+ } else if (member.isMethod && member.isModule && !(member hasFlag (LIFTED | BRIDGE))) {
addMember(member.cloneSymbol(clazz) setFlag MIXEDIN)
}
}
@@ -128,11 +118,14 @@ abstract class Mixin extends InfoTransform {
}
}
- if (clazz.isPackageClass) {
- addPackageClassMembers
- } else {
+ if (!clazz.isPackageClass) {
atPhase(phase.next)(clazz.owner.info);
if (clazz.isImplClass) {
+ clazz setFlag lateMODULE;
+ clazz.owner.info.decls.enter(
+ clazz.owner.newModule(sym.pos, sym.name.toTermName, sym.asInstanceOf[ClassSymbol])
+ setInfo sym.tpe);
+ assert(clazz.sourceModule != NoSymbol);//debug
parents1 = List();
decls1 = new Scope(decls.toList filter isForwarded)
} else if (!parents.isEmpty) {
@@ -140,15 +133,16 @@ abstract class Mixin extends InfoTransform {
if (!(clazz hasFlag INTERFACE)) addMixedinMembers
else if (clazz hasFlag lateINTERFACE) addLateInterfaceMembers
}
+ if (settings.debug.value) log("new defs of " + clazz + " = " + decls1);
}
- if (settings.debug.value && !clazz.isPackageClass) log("new defs of " + clazz + " = " + decls1);
- decls1 = atPhase(phase.next)(new Scope(decls1.toList));//debug
+ //decls1 = atPhase(phase.next)(new Scope(decls1.toList));//debug
if ((parents1 eq parents) && (decls1 eq decls)) tp
else ClassInfoType(parents1, decls1, clazz);
case MethodType(formals, restp) =>
if (isForwarded(sym)) MethodType(toInterface(sym.owner.typeOfThis) :: formals, restp)
else tp
+
case _ =>
tp
}
@@ -189,8 +183,10 @@ abstract class Mixin extends InfoTransform {
private def staticRef(sym: Symbol) = {
sym.owner.info;
- if (sym.owner.sourceModule == NoSymbol)
+ sym.owner.owner.info;
+ if (sym.owner.sourceModule == NoSymbol) {
assert(false, "" + sym + " in " + sym.owner + " in " + sym.owner.owner + " " + sym.owner.owner.info.decls.toList);//debug
+ }
Select(gen.mkRef(sym.owner.sourceModule), sym);
}
@@ -298,7 +294,7 @@ abstract class Mixin extends InfoTransform {
}
case Select(qual, name) if sym.owner.isImplClass && !isStatic(sym) =>
if (sym.isMethod) {
- assert(sym hasFlag LIFTED, sym);
+ assert(sym hasFlag (LIFTED | BRIDGE), sym);
val sym1 = enclInterface.info.decl(sym.name);
assert(sym1 != NoSymbol && !(sym1 hasFlag OVERLOADED), sym);//debug
tree setSymbol sym1
diff --git a/sources/scala/tools/nsc/transform/OverridingPairs.scala b/sources/scala/tools/nsc/transform/OverridingPairs.scala
new file mode 100755
index 0000000000..2830fed9f5
--- /dev/null
+++ b/sources/scala/tools/nsc/transform/OverridingPairs.scala
@@ -0,0 +1,126 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author
+ */
+// $Id$
+package scala.tools.nsc.transform;
+
+import util.HashSet;
+import collection.mutable.HashMap;
+import symtab.Flags._;
+
+abstract class OverridingPairs {
+
+ val global: Global;
+ import global._;
+
+ class Cursor(base: Symbol) {
+
+ private val self = base.thisType;
+
+ protected def exclude(sym: Symbol): boolean = sym.isConstructor || (sym hasFlag LOCAL);
+
+ protected def parents: List[Type] = base.info.parents;
+
+ protected def matches(sym1: Symbol, sym2: Symbol): boolean =
+ sym1.isType || (self.memberType(sym1) matches self.memberType(sym2));
+
+ private type BitSet = Array[int];
+
+ private def newBitSet(size: int): BitSet = new Array((size + 31) >> 5);
+
+ private def include(bs: BitSet, n: int): unit = {
+ val nshifted = n >> 5;
+ val nmask = 1 << (n & 31);
+ bs(nshifted) = bs(nshifted) | nmask
+ }
+
+ private def intersectionContainsElementLeq(bs1: BitSet, bs2: BitSet, n: int): boolean = {
+ val nshifted = n >> 5;
+ val nmask = 1 << (n & 31);
+ (List.range(0, nshifted) exists (i => (bs1(i) & bs2(i)) != 0)) ||
+ ((bs1(nshifted) & bs2(nshifted) & (nmask | nmask - 1)) != 0)
+ }
+
+ private val decls = new Scope;
+ { def fillDecls(bcs: List[Symbol], deferredflag: int): unit =
+ if (!bcs.isEmpty) {
+ fillDecls(bcs.tail, deferredflag);
+ var e = bcs.head.info.decls.elems;
+ while (e != null) {
+ if (e.sym.getFlag(DEFERRED) == deferredflag && !exclude(e.sym)) decls enter e.sym;
+ e = e.next
+ }
+ }
+ fillDecls(base.info.baseClasses, DEFERRED);
+ fillDecls(base.info.baseClasses, 0);
+ }
+
+ private val size = base.info.baseClasses.length;
+
+ private val index = new HashMap[Symbol, int];
+ { var i = 0;
+ for (val bc <- base.info.baseClasses) {
+ index(bc) = i;
+ i = i + 1
+ }
+ }
+
+ private val subParents = new Array[BitSet](size);
+ { for (val i <- List.range(0, size))
+ subParents(i) = new BitSet(size);
+ for (val p <- parents) {
+ val pIndex = index(p.symbol);
+ for (val bc <- p.baseClasses) include(subParents(index(bc)), pIndex);
+ }
+ }
+
+
+ private def hasCommonParent(sym1: Symbol, sym2: Symbol) = {
+ //assert(index.get(sym1.owner) != None, "" + base + " " + sym1 + " " + sym1.owner);//DEBUG
+ //assert(index.get(sym2.owner) != None, "" + base + " " + sym2 + " " + sym2.owner);//DEBUG
+ val index1 = index(sym1.owner);
+ val index2 = index(sym2.owner);
+ val minindex = if (index1 < index2) index1 else index2;
+ intersectionContainsElementLeq(subParents(index1), subParents(index2), minindex)
+ }
+
+ private val visited = new HashSet[ScopeEntry](256);
+ private var curEntry = decls.elems;
+ private var nextEntry = curEntry;
+
+ var overriding: Symbol = _;
+ var overridden: Symbol = _;
+
+ def hasNext: boolean = curEntry != null;
+
+ def next: unit =
+ if (curEntry != null) {
+ overriding = curEntry.sym;
+ if (nextEntry != null) {
+ do {
+ nextEntry = decls.lookupNextEntry(nextEntry);
+ } while (nextEntry != null &&
+ ((nextEntry.sym hasFlag PRIVATE) ||
+ (overriding.owner == nextEntry.sym.owner) ||
+ (hasCommonParent(overriding, nextEntry.sym)) ||
+ (!matches(overriding, nextEntry.sym)) ||
+ (overriding hasFlag LOCAL)))
+ }
+ if (nextEntry != null) {
+ overridden = nextEntry.sym;
+ //System.out.println("yield: " + overriding + overriding.locationString + " / " + overridden + overridden.locationString);//DEBUG
+ visited addEntry nextEntry
+ } else {
+ do {
+ curEntry = curEntry.next
+ } while (curEntry != null && (visited contains curEntry));
+ nextEntry = curEntry;
+ next
+ }
+ }
+
+ next
+ }
+}
+
diff --git a/sources/scala/tools/nsc/transform/SyntheticMethods.scala b/sources/scala/tools/nsc/transform/SyntheticMethods.scala
deleted file mode 100644
index 5f84f49206..0000000000
--- a/sources/scala/tools/nsc/transform/SyntheticMethods.scala
+++ /dev/null
@@ -1,124 +0,0 @@
-/* NSC -- new scala compiler
- * Copyright 2005 LAMP/EPFL
- * @author
- */
-// $Id$
-package scala.tools.nsc.transform;
-
-import symtab.Flags._;
-import util.ListBuffer;
-
-abstract class SyntheticMethods extends Transform {
- import global._; // the global environment
- import definitions._; // standard classes and methods
- import typer.{typed}; // methods to type trees
-
- val phaseName: String = "syntheticMethods";
- def newTransformer(unit: CompilationUnit): Transformer = new SyntheticMethodTransformer;
-
- class SyntheticMethodTransformer extends Transformer {
-
- private def addSyntheticMethods(templ: Template, clazz: Symbol): Template = {
-
- def hasImplementation(name: Name): boolean = {
- val sym = clazz.info.nonPrivateMember(name);
- sym.isTerm &&
- (sym.owner == clazz ||
- !(ObjectClass isSubClass sym.owner) && !(sym hasFlag DEFERRED));
- }
-
- def syntheticMethod(name: Name, flags: int, tpe: Type) = {
- val method = clazz.newMethod(clazz.pos, name) setFlag (flags | OVERRIDE) setInfo tpe;
- clazz.info.decls.enter(method);
- method
- }
-
- def caseElementMethod: Tree = {
- val method = syntheticMethod(
- nme.caseElement, FINAL, MethodType(List(IntClass.tpe), AnyClass.tpe));
- val caseFields = clazz.caseFieldAccessors map gen.mkRef;
- typed(
- DefDef(method, vparamss =>
- if (caseFields.isEmpty) Literal(Constant(null))
- else {
- var i = caseFields.length;
- var cases = List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(null))));
- for (val field <- caseFields.reverse) {
- i = i - 1; cases = CaseDef(Literal(Constant(i)), EmptyTree, field) :: cases
- }
- Match(Ident(vparamss.head.head), cases)
- }))
- }
-
- def caseArityMethod: Tree = {
- val method = syntheticMethod(nme.caseArity, FINAL, PolyType(List(), IntClass.tpe));
- typed(DefDef(method, vparamss => Literal(Constant(clazz.caseFieldAccessors.length))))
- }
-
- def caseNameMethod: Tree = {
- val method = syntheticMethod(nme.caseName, FINAL, PolyType(List(), StringClass.tpe));
- typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
- }
-
- def moduleToStringMethod: Tree = {
- val method = syntheticMethod(nme.toString_, FINAL, MethodType(List(), StringClass.tpe));
- typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
- }
-
- def tagMethod: Tree = {
- val method = syntheticMethod(nme.tag, FINAL, MethodType(List(), IntClass.tpe));
- typed(DefDef(method, vparamss => Literal(Constant(clazz.tag))))
- }
-
- def forwardingMethod(name: Name): Tree = {
- val target = getMember(ScalaRunTimeModule, "_" + name);
- val method = syntheticMethod(
- name, 0, MethodType(target.tpe.paramTypes.tail, target.tpe.resultType));
- typed(DefDef(method, vparamss =>
- Apply(gen.mkRef(target), This(clazz) :: (vparamss.head map Ident))));
- }
-
- def readResolveMethod: Tree = {
- // !!! the synthetic method "readResolve" should be private,
- // but then it is renamed !!!
- val method = syntheticMethod(nme.readResolve, PROTECTED, MethodType(List(), ObjectClass.tpe));
- typed(DefDef(method, vparamss => gen.mkRef(clazz.sourceModule)))
- }
-
- val ts = new ListBuffer[Tree];
- if (clazz hasFlag CASE) {
- ts += tagMethod;
- if (clazz.isModuleClass) {
- if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod;
- if (clazz.isSubClass(SerializableClass)) {
- // If you serialize a singleton and then deserialize it twice,
- // you will have two instances of your singleton, unless you implement
- // the readResolve() method (see http://www.javaworld.com/javaworld/
- // jw-04-2003/jw-0425-designpatterns_p.html)
- if (!hasImplementation(nme.readResolve)) ts += readResolveMethod;
- }
- } else {
- ts += caseElementMethod;
- ts += caseArityMethod;
- ts += caseNameMethod;
- if (!hasImplementation(nme.equals_)) ts += forwardingMethod(nme.equals_);
- if (!hasImplementation(nme.hashCode_)) ts += forwardingMethod(nme.hashCode_);
- if (!hasImplementation(nme.toString_)) ts += forwardingMethod(nme.toString_);
- }
- }
- val synthetics = ts.toList;
- copy.Template(
- templ, templ.parents, if (synthetics.isEmpty) templ.body else templ.body ::: synthetics)
- }
-
- override def transform(tree: Tree): Tree =
- super.transform {
- tree match {
- case ClassDef(mods, name, tparams, tpe, impl) =>
- copy.ClassDef(tree, mods, name, tparams, tpe, addSyntheticMethods(impl, tree.symbol))
- case _ =>
- tree
- }
- }
- }
-}
diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala
index a252c47d32..05c9be4f54 100755
--- a/sources/scala/tools/nsc/transform/UnCurry.scala
+++ b/sources/scala/tools/nsc/transform/UnCurry.scala
@@ -33,6 +33,7 @@ abstract class UnCurry extends InfoTransform {
val phaseName: String = "uncurry";
def newTransformer(unit: CompilationUnit): Transformer = new UnCurryTransformer(unit);
+ override def changesBaseClasses = false;
private val uncurry = new TypeMap {
def apply(tp: Type): Type = tp match {
diff --git a/sources/scala/tools/nsc/typechecker/Analyzer.scala b/sources/scala/tools/nsc/typechecker/Analyzer.scala
index a0f3f19a8f..267f5ba39c 100644
--- a/sources/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/sources/scala/tools/nsc/typechecker/Analyzer.scala
@@ -14,7 +14,8 @@ abstract class Analyzer
with Typers
with Infer
with Variances
- with EtaExpansion {
+ with EtaExpansion
+ with SyntheticMethods {
val global: Global;
import global._;
diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala
index f78c74c821..a32c7bf0e5 100755
--- a/sources/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala
@@ -43,6 +43,7 @@ abstract class RefChecks extends InfoTransform {
/** the following two members override abstract members in Transform */
val phaseName: String = "refchecks";
def newTransformer(unit: CompilationUnit): Transformer = new RefCheckTransformer(unit);
+ override def changesBaseClasses = false;
def transformInfo(sym: Symbol, tp: Type): Type = {
if (sym.isModule && !sym.isStatic) {
@@ -178,6 +179,14 @@ abstract class RefChecks extends InfoTransform {
}
}
+ val opc = new overridingPairs.Cursor(clazz);
+ while (opc.hasNext) {
+ //System.out.println("overrides " + opc.overriding/* + ":" + opc.overriding.tpe*/ + opc.overriding.locationString + " " + opc.overridden/* + ":" + opc.overridden.tpe*/ + opc.overridden.locationString + opc.overridden.hasFlag(DEFERRED));//DEBUG
+ if (!opc.overridden.isClass) checkOverride(clazz, opc.overriding, opc.overridden);
+
+ opc.next
+ }
+/*
// 1. Check all members for overriding conditions.
for (val bc <- clazz.info.baseClasses.tail; val other <- bc.info.decls.toList)
if (!other.isClass && !(other hasFlag PRIVATE) && !other.isConstructor) {
@@ -195,10 +204,11 @@ abstract class RefChecks extends InfoTransform {
"\n and " + infoString(alt2) +
"\n override " + infoString(other));
} else if (member != NoSymbol && !(member hasFlag LOCAL)) {
+ System.out.println("OVERRIDES " + member + member.locationString + " " + other + other.locationString);//debug
checkOverride(clazz, member, other);
}
}
-
+*/
// 2. Check that only abstract classes have deferred members
if (clazz.isClass && !(clazz hasFlag ABSTRACT)) {
def abstractClassError(msg: String): unit = {
diff --git a/sources/scala/tools/nsc/typechecker/SyntheticMethods.scala b/sources/scala/tools/nsc/typechecker/SyntheticMethods.scala
new file mode 100755
index 0000000000..dafad66d54
--- /dev/null
+++ b/sources/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -0,0 +1,108 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author
+ */
+// $Id$
+package scala.tools.nsc.typechecker;
+
+import symtab.Flags._;
+import util.ListBuffer;
+
+abstract class SyntheticMethods: Analyzer {
+ import global._; // the global environment
+ import definitions._; // standard classes and methods
+ import typer.{typed}; // methods to type trees
+
+ def addSyntheticMethods(templ: Template, clazz: Symbol): Template = {
+
+ def hasImplementation(name: Name): boolean = {
+ val sym = clazz.info.nonPrivateMember(name);
+ sym.isTerm &&
+ (sym.owner == clazz ||
+ !(ObjectClass isSubClass sym.owner) && !(sym hasFlag DEFERRED));
+ }
+
+ def syntheticMethod(name: Name, flags: int, tpe: Type) = {
+ val method = clazz.newMethod(clazz.pos, name) setFlag (flags | OVERRIDE) setInfo tpe;
+ clazz.info.decls.enter(method);
+ method
+ }
+
+ def caseElementMethod: Tree = {
+ val method = syntheticMethod(
+ nme.caseElement, FINAL, MethodType(List(IntClass.tpe), AnyClass.tpe));
+ val caseFields = clazz.caseFieldAccessors map gen.mkRef;
+ typed(
+ DefDef(method, vparamss =>
+ if (caseFields.isEmpty) Literal(Constant(null))
+ else {
+ var i = caseFields.length;
+ var cases = List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(null))));
+ for (val field <- caseFields.reverse) {
+ i = i - 1; cases = CaseDef(Literal(Constant(i)), EmptyTree, field) :: cases
+ }
+ Match(Ident(vparamss.head.head), cases)
+ }))
+ }
+
+ def caseArityMethod: Tree = {
+ val method = syntheticMethod(nme.caseArity, FINAL, PolyType(List(), IntClass.tpe));
+ typed(DefDef(method, vparamss => Literal(Constant(clazz.caseFieldAccessors.length))))
+ }
+
+ def caseNameMethod: Tree = {
+ val method = syntheticMethod(nme.caseName, FINAL, PolyType(List(), StringClass.tpe));
+ typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ }
+
+ def moduleToStringMethod: Tree = {
+ val method = syntheticMethod(nme.toString_, FINAL, MethodType(List(), StringClass.tpe));
+ typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ }
+
+ def tagMethod: Tree = {
+ val method = syntheticMethod(nme.tag, FINAL, MethodType(List(), IntClass.tpe));
+ typed(DefDef(method, vparamss => Literal(Constant(clazz.tag))))
+ }
+
+ def forwardingMethod(name: Name): Tree = {
+ val target = getMember(ScalaRunTimeModule, "_" + name);
+ val method = syntheticMethod(
+ name, 0, MethodType(target.tpe.paramTypes.tail, target.tpe.resultType));
+ typed(DefDef(method, vparamss =>
+ Apply(gen.mkRef(target), This(clazz) :: (vparamss.head map Ident))));
+ }
+
+ def readResolveMethod: Tree = {
+ // !!! the synthetic method "readResolve" should be private,
+ // but then it is renamed !!!
+ val method = syntheticMethod(nme.readResolve, PROTECTED, MethodType(List(), ObjectClass.tpe));
+ typed(DefDef(method, vparamss => gen.mkRef(clazz.sourceModule)))
+ }
+
+ val ts = new ListBuffer[Tree];
+ if (clazz hasFlag CASE) {
+ if (!hasImplementation(nme.tag)) ts += tagMethod;
+ if (clazz.isModuleClass) {
+ if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod;
+ if (clazz.isSubClass(SerializableClass)) {
+ // If you serialize a singleton and then deserialize it twice,
+ // you will have two instances of your singleton, unless you implement
+ // the readResolve() method (see http://www.javaworld.com/javaworld/
+ // jw-04-2003/jw-0425-designpatterns_p.html)
+ if (!hasImplementation(nme.readResolve)) ts += readResolveMethod;
+ }
+ } else {
+ if (!hasImplementation(nme.caseElement)) ts += caseElementMethod;
+ if (!hasImplementation(nme.caseArity)) ts += caseArityMethod;
+ if (!hasImplementation(nme.caseName)) ts += caseNameMethod;
+ if (!hasImplementation(nme.equals_)) ts += forwardingMethod(nme.equals_);
+ if (!hasImplementation(nme.hashCode_)) ts += forwardingMethod(nme.hashCode_);
+ if (!hasImplementation(nme.toString_)) ts += forwardingMethod(nme.toString_);
+ }
+ }
+ val synthetics = ts.toList;
+ copy.Template(
+ templ, templ.parents, if (synthetics.isEmpty) templ.body else templ.body ::: synthetics)
+ }
+}
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index ffef937b0a..5c2ff01376 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -474,7 +474,8 @@ abstract class Typers: Analyzer {
val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(cdef.tpt));
val impl1 = newTyper(context.make(cdef.impl, clazz, new Scope()))
.typedTemplate(cdef.impl);
- copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl1) setType NoType
+ copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, addSyntheticMethods(impl1, clazz))
+ setType NoType
}
def typedModuleDef(mdef: ModuleDef): Tree = {
@@ -907,7 +908,7 @@ abstract class Typers: Analyzer {
val sym =
if (tree.symbol != NoSymbol) {
if (phase.erasedTypes && qual.isInstanceOf[Super]) qual.tpe = tree.symbol.owner.tpe;
- if (settings.debug.value) { // todo: replace by settings.check.value?
+ if (false && settings.debug.value) { // todo: replace by settings.check.value?
val alts = qual.tpe.member(tree.symbol.name).alternatives;
if (!(alts exists (alt =>
alt == tree.symbol || alt.isTerm && (alt.tpe matches tree.symbol.tpe))))