summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-09-03 14:32:12 +0000
committerMartin Odersky <odersky@gmail.com>2006-09-03 14:32:12 +0000
commit132637e42e4b45dd73b907ea5f63273876d2e99f (patch)
treef28d76dd4628637a55bc5749ef45481a83169139 /src
parentbacd5d56f4ba1dc311cc68625535c270db93cb17 (diff)
downloadscala-132637e42e4b45dd73b907ea5f63273876d2e99f.tar.gz
scala-132637e42e4b45dd73b907ea5f63273876d2e99f.tar.bz2
scala-132637e42e4b45dd73b907ea5f63273876d2e99f.zip
fixed bug 722
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala11
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala19
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala56
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala16
6 files changed, 82 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 76bf0793c7..96110f8dc1 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -37,7 +37,7 @@ abstract class TreeGen {
if (sym.isRoot) {
mkAttributedThis(sym)
} else if (sym.isModuleClass) {
- val qual = mkAttributedSelect(mkAttributedQualifier(pre), sym.sourceModule);
+ val qual = mkAttributedRef(pre, sym.sourceModule);
qual.tpe match {
case MethodType(List(), restpe) =>
Apply(qual, List()) setType restpe
@@ -45,7 +45,7 @@ abstract class TreeGen {
qual
}
} else {
- assert(phase.erasedTypes, ""+sym+sym.isModuleClass)
+ assert(phase.erasedTypes)
mkAttributedThis(sym)
}
case _ =>
@@ -55,8 +55,11 @@ abstract class TreeGen {
/** Builds a reference to given symbol with given stable prefix. */
def mkAttributedRef(pre: Type, sym: Symbol): Tree = {
val qual = mkAttributedQualifier(pre)
- if (qual == EmptyTree) mkAttributedIdent(sym)
- else mkAttributedSelect(qual, sym)
+ qual match {
+ case EmptyTree => mkAttributedIdent(sym)
+ case This(clazz) if (qual.symbol.isRoot || qual.symbol.isEmptyPackageClass) => mkAttributedIdent(sym)
+ case _ => mkAttributedSelect(qual, sym)
+ }
}
/** Builds a reference to given symbol. */
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 1a41659a61..d2214148b6 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -127,6 +127,9 @@ trait StdNames requires SymbolTable {
def implClassName(name: Name): Name =
newTypeName(name.toString() + IMPL_CLASS_SUFFIX)
+ def interfaceName(implname: Name): Name =
+ implname.subName(0, implname.length - IMPL_CLASS_SUFFIX.length)
+
def moduleVarName(name: Name): Name =
newTermName(name.toString() + MODULE_SUFFIX)
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index ffca6fc765..c4c61d4b46 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -197,7 +197,7 @@ trait Symbols requires 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 isRootPackage = isPackage && name == nme.ROOTPKG
final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME
final def isEmptyPackageClass = isPackageClass && name == nme.EMPTY_PACKAGE_NAME.toTypeName
@@ -640,8 +640,15 @@ trait Symbols requires SymbolTable {
final def toInterface: Symbol =
if (isImplClass) {
- assert(!tpe.parents.isEmpty, this)
- tpe.parents.last.symbol
+ val result =
+ if (phase.erasedTypes) {
+ assert(!tpe.parents.isEmpty, this)
+ tpe.parents.last.symbol
+ } else {
+ owner.info.decl(nme.interfaceName(name))
+ }
+ assert(result != NoSymbol, this)
+ result
} else this
/** The module corresponding to this module class (note that this
@@ -885,6 +892,12 @@ trait Symbols requires SymbolTable {
privateWithin = NoSymbol
+ override def owner: Symbol = {
+ if (name == nme.MIXIN_CONSTRUCTOR && !phase.erasedTypes && super.owner.isImplClass)
+ super.owner.toInterface
+ else rawowner
+ }
+
protected var referenced: Symbol = NoSymbol
def cloneSymbolImpl(owner: Symbol): Symbol = {
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 14dd16f316..94d47a4209 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1057,6 +1057,8 @@ trait Types requires SymbolTable {
sym.tpe.resultType
else if (checkMalformedSwitch && !pre.isStable && !pre.isError)
throw new MalformedType(pre, sym.name.toString())
+ else if (sym.isRootPackage)
+ ThisType(RootClass)
else {
var sym1 = rebind(pre, sym)
val pre1 = removeSuper(pre, sym1)
@@ -1511,7 +1513,7 @@ trait Types requires SymbolTable {
def corresponds(sym1: Symbol, sym2: Symbol): boolean =
sym1.name == sym2.name && (sym1.isPackageClass || corresponds(sym1.owner, sym2.owner))
assert(sym != NoSymbol)
- if (rebind0 == NoSymbol) assert(false, ""+pre+"."+sym+"does no longer exist!")
+ if (rebind0 == NoSymbol) assert(false, ""+pre+"."+sym+" does no longer exist, phase = "+phase)
if (!corresponds(sym.owner, rebind0.owner)) {
if (settings.debug.value) Console.println("ADAPT1 pre = "+pre+", sym = "+sym+sym.locationString+", rebind = "+rebind0+rebind0.locationString)
val bcs = pre.baseClasses.dropWhile(bc => !corresponds(bc, sym.owner));
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 24bf59a7fe..19319079e0 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -15,13 +15,22 @@ abstract class AddInterfaces extends InfoTransform {
import definitions._ // standard classes and methods
import posAssigner.atPos // for filling in tree positions
+ /** The phase sets lateINTERFACE for non-interface traits that now become interfaces
+ * It sets lateDEFERRED for formerly concrete methods in such traits
+ */
override def phaseNewFlags: long = lateDEFERRED | lateINTERFACE
-// Type transformation
-
+ /** Type reference after erasure; to be defined in subclass Erasure */
def erasedTypeRef(sym: Symbol): Type
+ /** A lazily constructed map that associates every non-interface trait with
+ * its implementation class */
private val implClassMap = new HashMap[Symbol, Symbol]
+
+ /** A lazily constructed map that associates every concrete method in a non-interface
+ * trait that's currently compiled with its corresponding method in the trait's
+ * implementation class.
+ */
private val implMethodMap = new HashMap[Symbol, Symbol]
override def newPhase(prev: scala.tools.nsc.Phase): StdPhase = {
@@ -30,11 +39,8 @@ abstract class AddInterfaces extends InfoTransform {
super.newPhase(prev)
}
- private def needsImplMethod(sym: Symbol): boolean = (
- sym.isMethod && isInterfaceMember(sym) &&
- (!(sym hasFlag (DEFERRED | SUPERACCESSOR)) || (sym hasFlag lateDEFERRED))
- )
-
+ /** Is given trait member symbol a member of the trait's interface
+ * after this transform is performed? */
private def isInterfaceMember(sym: Symbol): boolean = {
sym.info; // to set lateMETHOD flag if necessary
(sym.isType ||
@@ -42,6 +48,12 @@ abstract class AddInterfaces extends InfoTransform {
!sym.isConstructor && !sym.isImplOnly)
}
+ /** Does symbol need an implementation method? */
+ private def needsImplMethod(sym: Symbol): boolean =
+ sym.isMethod && isInterfaceMember(sym) &&
+ (!(sym hasFlag (DEFERRED | SUPERACCESSOR)) || (sym hasFlag lateDEFERRED))
+
+ /** Return the implementation class of a trait; create a new one of one does not yet exist */
def implClass(iface: Symbol): Symbol = implClassMap.get(iface) match {
case Some(c) => c
case None =>
@@ -51,7 +63,18 @@ abstract class AddInterfaces extends InfoTransform {
if (impl == NoSymbol) {
impl = iface.cloneSymbolImpl(iface.owner)
impl.name = implName
- if (iface.owner.isClass) iface.owner.info.decls enter impl
+ if (iface.owner.isClass) {
+ atPhase(phase.next) {
+ val decls = iface.owner.info.decls
+ val e = decls.lookupEntry(impl.name)
+ if (e == null) {
+ decls enter impl
+ } else if (true || currentRun.compiles(iface)) {
+ decls.unlink(e)
+ decls enter impl
+ }
+ }
+ }
}
if (currentRun.compiles(iface)) currentRun.symSource(impl) = iface.sourceFile
impl setPos iface.pos
@@ -63,8 +86,12 @@ abstract class AddInterfaces extends InfoTransform {
}
}
+ /** A lazy type to set the info of an implementation class */
private class LazyImplClassType(iface: Symbol) extends LazyType {
+ /** Compute the decls of implementation class `implClass',
+ * given the decls `ifaceDecls' of its interface
+ */
def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {
val decls = newScope
for (val sym <- ifaceDecls.elements) {
@@ -77,6 +104,9 @@ abstract class AddInterfaces extends InfoTransform {
}
} else {
sym.owner = implClass
+ // note: OK to destructively modify the owner here,
+ // because symbol will not be accessible from outside the sourcefile.
+ // mixin constructors are corrected separately; see TermSymbol.owner
decls enter sym
}
}
@@ -88,7 +118,7 @@ abstract class AddInterfaces extends InfoTransform {
case ClassInfoType(parents, decls, _) =>
//ClassInfoType(mixinToImplClass(parents) ::: List(iface.tpe), implDecls(sym, decls), sym)
ClassInfoType(
- ObjectClass.tpe :: (parents.tail map mixinToImplClass) ::: List(iface.tpe),
+ ObjectClass.tpe :: (parents.tail map mixinToImplClass) ::: List(iface.tpe), //!!!
implDecls(sym, decls),
sym)
case PolyType(tparams, restpe) =>
@@ -100,6 +130,9 @@ abstract class AddInterfaces extends InfoTransform {
override def load(clazz: Symbol): unit = complete(clazz)
}
+ /** If `tp' refers to a non-interface trait, return a reference to its implementation class.
+ * Otherwise return `tp' itself.
+ */
private def mixinToImplClass(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) if (sym.needsImplClass) =>
typeRef(pre, implClass(sym), args)
@@ -126,8 +159,9 @@ abstract class AddInterfaces extends InfoTransform {
else (!sym.isType || sym.isClass))
//if (!clazz.isPackageClass) System.out.println("Decls of "+clazz+" after explicitOuter = " + decls1);//DEBUG
- if ((parents1 eq parents) && (decls1 eq decls)) tp
- else ClassInfoType(parents1, decls1, clazz)
+ //if ((parents1 eq parents) && (decls1 eq decls)) tp
+ //else
+ ClassInfoType(parents1, decls1, clazz)
case _ =>
tp
}
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index ef1f066648..063da42900 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -363,14 +363,14 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
/** A replacement for the standard typer's `typed1' method */
override protected def typed1(tree: Tree, mode: int, pt: Type): Tree = {
-// var tree1 = try { //debug
- var tree1 = super.typed1(adaptMember(tree), mode, pt);
-// } catch {
-// case ex: Throwable =>
-// if (settings.debug.value)
-// System.out.println("exception when typing " + tree);
-// throw ex
-// }
+ var tree1 = try {
+ super.typed1(adaptMember(tree), mode, pt);
+ } catch {
+ case ex: Throwable =>
+ if (settings.debug.value)
+ System.out.println("exception when typing " + tree);
+ throw ex
+ }
def adaptCase(cdef: CaseDef): CaseDef = {
val body1 = adaptToType(cdef.body, tree1.tpe)
copy.CaseDef(cdef, cdef.pat, cdef.guard, body1) setType body1.tpe