summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-01-04 15:16:08 +0000
committerMartin Odersky <odersky@gmail.com>2006-01-04 15:16:08 +0000
commit776ecad2a3b1d8b253f06eadc1a54c36be873ebf (patch)
treece7a8d8460d123cef1e00e1503a0bc7b6745294c
parent4e176bc3d22fb4457045b5731e0b202dc5924dfa (diff)
downloadscala-776ecad2a3b1d8b253f06eadc1a54c36be873ebf.tar.gz
scala-776ecad2a3b1d8b253f06eadc1a54c36be873ebf.tar.bz2
scala-776ecad2a3b1d8b253f06eadc1a54c36be873ebf.zip
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala5
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala22
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--src/library/scala/List.scala2
13 files changed, 83 insertions, 44 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 4d13548a08..53b1f7da6e 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -91,11 +91,8 @@ abstract class TreePrinters {
def printFlags(flags: long, privateWithin: Name): unit = {
var mask = if (settings.debug.value) -1 else PrintableFlags;
- if (!privateWithin.isEmpty) {
- print("private["+privateWithin+"] ");
- mask = mask & ~PRIVATE
- }
val s = flagsToString(flags & mask);
+ if (!privateWithin.isEmpty) print("private["+privateWithin+"] ");
if (s.length() != 0) print(s + " ")
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 00c8cf99a5..5d548cbf4c 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1077,11 +1077,12 @@ import Tokens._;
case SEALED =>
loop(addMod(mods, Flags.SEALED))
case PRIVATE =>
- val mods1 = addMod(mods, Flags.PRIVATE);
+ var mods1 = addMod(mods, Flags.PRIVATE);
if (in.token == LBRACKET) {
in.nextToken();
privateWithin = ident().toTypeName;
- accept(RBRACKET)
+ accept(RBRACKET);
+ mods1 = mods
}
loop(mods1)
case PROTECTED =>
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 11f0c21c4f..a07da4ad57 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -31,10 +31,12 @@ abstract class SymbolLoaders {
/** The kind of file that's processed by this loader */
protected def kindString: String;
private var ok = false;
+
private def setSource(sym: Symbol): unit = sym match {
case clazz: ClassSymbol => clazz.sourceFile = file;
case _ =>
}
+
override def complete(root: Symbol): unit = {
try {
val start = System.currentTimeMillis();
@@ -45,7 +47,7 @@ abstract class SymbolLoaders {
informTime("loaded " + source, start);
if (root.rawInfo != this) {
ok = true;
- setSource(root.linkedModule);
+ setSource(root.linkedModule.moduleClass);
setSource(root.linkedClass);
} else error(source + " does not define " + root)
} catch {
@@ -94,7 +96,6 @@ abstract class SymbolLoaders {
val name = newTermName(str);
val clazz = owner.newClass(Position.NOPOS, name.toTypeName);
val module = owner.newModule(Position.NOPOS, name);
- clazz.sourceFile = sfile;
clazz.setInfo(completer);
module.setInfo(completer);
module.moduleClass.setInfo(moduleClassLoader);
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 2b1be41917..e8fed63916 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -668,13 +668,9 @@ import Flags._;
def sourceFile: AbstractFile =
(if (isModule) moduleClass else toplevelClass).sourceFile;
-/*
- def referenced: Symbol =
- throw new Error("referenced inapplicable for " + this);
+ def sourceFile_=(f: AbstractFile): unit =
+ throw new Error("sourceFile_= inapplicable for "+this)
- def setReferenced(sym: Symbol): Symbol =
- throw new Error("setReferenced inapplicable for " + this);
-*/
// ToString -------------------------------------------------------------------
/** A tag which (in the ideal case) uniquely identifies class symbols */
@@ -944,7 +940,7 @@ import Flags._;
private var source: AbstractFile = null;
override def sourceFile = source
- def sourceFile_=(f: AbstractFile): unit = { source = f }
+ override def sourceFile_=(f: AbstractFile): unit = { source = f }
private var thissym: Symbol = this;
override def isClass: boolean = true;
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
index 220b4bc6b5..ea88451ef6 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
@@ -45,7 +45,7 @@ object PickleFormat {
* | 34 LITERALnull len_Nat
* | 35 LITERALzero len_Nat
* | 36 ATTRIBUTE sym_Ref type_Ref {constant_Ref} <not yet>
- * SymbolInfo = name_Ref owner_Ref flags_Nat info_Ref
+ * SymbolInfo = name_Ref owner_Ref flags_Nat [privateWithin_Ref] info_Ref
* NameInfo = <character sequence of length len_Nat in Utf8 format>
* NumInfo = <len_Nat-byte signed number in big endian format>
* Ref = Nat
@@ -53,7 +53,7 @@ object PickleFormat {
* len is remaining length after `len'.
*/
val MajorVersion = 2;
- val MinorVersion = 0;
+ val MinorVersion = 1;
final val TERMname = 1;
final val TYPEname = 2;
@@ -94,6 +94,7 @@ object PickleFormat {
final val firstSymTag = NONEsym;
final val lastSymTag = VALsym;
+ final val lastExtSymTag = EXTMODCLASSref;
final val firstTypeTag = NOtpe;
final val lastTypeTag = POLYtpe;
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 5ecd30fcd1..639cb71bf0 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -83,6 +83,7 @@ abstract class Pickler extends SubComponent {
if (isLocal(sym)) {
putEntry(sym.name);
putSymbol(sym.owner);
+ putSymbol(sym.privateWithin);
putType(sym.info);
if (sym.thisSym != sym)
putType(sym.typeOfThis);
@@ -146,6 +147,7 @@ abstract class Pickler extends SubComponent {
writeRef(sym.name);
writeRef(sym.owner);
writeNat((sym.flags & PickledFlags).asInstanceOf[int]);
+ if (sym.privateWithin != NoSymbol) writeRef(sym.privateWithin);
writeRef(sym.info)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 70c50e592b..976704f9ae 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -61,6 +61,12 @@ abstract class UnPickler {
(tag != CLASSsym || !isRefinementSymbolEntry(i)))
}
+ /** Does entry represent an (internal or external) symbol */
+ private def isSymbolRef(i: int): boolean = {
+ val tag = bytes(index(i));
+ (firstSymTag <= tag && tag <= lastExtSymTag)
+ }
+
/** Does entry represent a refinement symbol?
* pre: Entry is a class symbol
*/
@@ -122,7 +128,12 @@ abstract class UnPickler {
val name = readNameRef();
val owner = readSymbolRef();
val flags = readNat();
- val inforef = readNat();
+ var privateWithin: Symbol = NoSymbol;
+ var inforef = readNat();
+ if (isSymbolRef(inforef)) {
+ privateWithin = at(inforef, readSymbol);
+ inforef = readNat()
+ }
tag match {
case TYPEsym =>
sym = owner.newAbstractType(Position.NOPOS, name);
@@ -155,6 +166,7 @@ abstract class UnPickler {
errorBadSignature("bad symbol tag: " + tag);
}
sym.setFlag(flags);
+ sym.privateWithin = privateWithin;
if (readIndex != end) assert(sym hasFlag (SUPERACCESSOR | PARAMACCESSOR));
if (sym hasFlag SUPERACCESSOR) assert(readIndex != end);
sym.setInfo(
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 021e810a43..d0cfa6f3a1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -221,15 +221,20 @@ import scala.tools.nsc.util.Position;
c != NoContext;
}
- (pre == NoPrefix
- ||
- (!sym.hasFlag(PRIVATE | PROTECTED))
- ||
- accessWithin(sym.owner) && (!sym.hasFlag(LOCAL) || pre =:= sym.owner.thisType)
- ||
- (!sym.hasFlag(PRIVATE) &&
- (superAccess ||
- (pre.widen.symbol.isSubClass(sym.owner) && isSubClassOfEnclosing(pre.widen.symbol)))))
+ ( pre == NoPrefix
+ ||
+ (!sym.hasFlag(PRIVATE | PROTECTED))
+ ||
+ accessWithin(sym.owner) && (!sym.hasFlag(LOCAL) || pre =:= sym.owner.thisType)
+ ||
+ (!sym.hasFlag(PRIVATE) &&
+ (superAccess ||
+ (pre.widen.symbol.isSubClass(sym.owner) && isSubClassOfEnclosing(pre.widen.symbol))))
+ ) && (
+ sym.privateWithin == NoSymbol
+ ||
+ accessWithin(sym.privateWithin)
+ )
}
def pushTypeBounds(sym: Symbol): unit = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index ce53aa40c2..739cb4935a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -42,7 +42,7 @@ trait Namers: Analyzer {
val typer = newTyper(context);
- def setPrivate(sym: Symbol, mods: Modifiers): Symbol = {
+ def setPrivateWithin(sym: Symbol, mods: Modifiers): Symbol = {
if (!mods.privateWithin.isEmpty)
sym.privateWithin = typer.qualifyingClassContext(EmptyTree, mods.privateWithin).owner;
sym
@@ -119,7 +119,7 @@ trait Namers: Analyzer {
}
if (c.owner.isPackageClass) {
currentRun.symSource(c) = context.unit.source.getFile();
- c.asInstanceOf[ClassSymbol].sourceFile = context.unit.source.getFile();
+ c.sourceFile = context.unit.source.getFile();
}
c
}
@@ -134,6 +134,7 @@ trait Namers: Analyzer {
m = context.owner.newModule(pos, name);
m.setFlag(flags);
m.moduleClass.setFlag(flags | inConstructorFlag);
+ m.moduleClass.sourceFile = context.unit.source.getFile();
enterInScope(m)
}
if (m.owner.isPackageClass) currentRun.symSource(m) = context.unit.source.getFile();
@@ -203,15 +204,15 @@ trait Namers: Analyzer {
tree.symbol = enterCaseFactorySymbol(
tree.pos, mods.flags & AccessFlags | METHOD | CASE, name.toTermName)
.setInfo(innerNamer.caseFactoryCompleter(tree));
- setPrivate(tree.symbol, mods);
+ setPrivateWithin(tree.symbol, mods);
}
tree.symbol = enterClassSymbol(tree.pos, mods.flags, name);
- setPrivate(tree.symbol, mods);
+ setPrivateWithin(tree.symbol, mods);
finishWith(tparams);
case ModuleDef(mods, name, _) =>
tree.symbol = enterModuleSymbol(tree.pos, mods.flags | MODULE | FINAL, name);
- setPrivate(tree.symbol, mods);
- setPrivate(tree.symbol.moduleClass, mods);
+ setPrivateWithin(tree.symbol, mods);
+ setPrivateWithin(tree.symbol.moduleClass, mods);
tree.symbol.moduleClass.setInfo(innerNamer.typeCompleter(tree));
finish
case ValDef(mods, name, tp, rhs) =>
@@ -222,13 +223,13 @@ trait Namers: Analyzer {
val getter = owner.newMethod(tree.pos, name)
.setFlag(accflags)
.setInfo(innerNamer.getterTypeCompleter(tree));
- setPrivate(getter, mods);
+ setPrivateWithin(getter, mods);
enterInScope(getter);
if ((mods.flags & MUTABLE) != 0) {
val setter = owner.newMethod(tree.pos, nme.getterToSetter(name))
.setFlag(accflags & ~STABLE & ~CASEACCESSOR)
.setInfo(innerNamer.setterTypeCompleter(tree));
- setPrivate(setter, mods);
+ setPrivateWithin(setter, mods);
enterInScope(setter)
}
tree.symbol =
@@ -245,22 +246,22 @@ trait Namers: Analyzer {
case DefDef(mods, nme.CONSTRUCTOR, tparams, vparams, tp, rhs) =>
tree.symbol = enterInScope(owner.newConstructor(tree.pos))
.setFlag(mods.flags | owner.getFlag(ConstrFlags));
- setPrivate(tree.symbol, mods);
+ setPrivateWithin(tree.symbol, mods);
finishWith(tparams);
case DefDef(mods, name, tparams, _, _, _) =>
tree.symbol = enterInScope(owner.newMethod(tree.pos, name))
.setFlag(mods.flags);
- setPrivate(tree.symbol, mods);
+ setPrivateWithin(tree.symbol, mods);
finishWith(tparams);
case AbsTypeDef(mods, name, _, _) =>
tree.symbol = enterInScope(owner.newAbstractType(tree.pos, name))
.setFlag(mods.flags);
- setPrivate(tree.symbol, mods);
+ setPrivateWithin(tree.symbol, mods);
finish
case AliasTypeDef(mods, name, tparams, _) =>
tree.symbol = enterInScope(owner.newAliasType(tree.pos, name))
.setFlag(mods.flags);
- setPrivate(tree.symbol, mods);
+ setPrivateWithin(tree.symbol, mods);
finishWith(tparams)
case Attributed(attr, defn) =>
enterSym(defn);
@@ -333,7 +334,7 @@ trait Namers: Analyzer {
param.symbol = owner.newValueParameter(param.pos, param.name)
.setInfo(typeCompleter(param))
.setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT));
- setPrivate(param.symbol, param.mods);
+ setPrivateWithin(param.symbol, param.mods);
context.scope enter param.symbol;
param.symbol
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index d69b6d540c..7057638749 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -164,6 +164,9 @@ abstract class RefChecks extends InfoTransform {
if (member hasFlag PRIVATE) { // (1.1)
overrideError("has weaker access privileges; it should not be private");
+ } else if (member.privateWithin != NoSymbol &&
+ !other.privateWithin.ownerChain.contains(member.privateWithin)) {
+ overrideError("has weaker access privileges; it should at least be private["+other.privateWithin.name+"]");
} else if ((member hasFlag PROTECTED) && !(other hasFlag PROTECTED)) { // 1
overrideError("has weaker access privileges; it should not be protected");
} else if (other hasFlag FINAL) { // (1.2)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 005a81d031..ae4cdb2b58 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -6,6 +6,7 @@
package scala.tools.nsc.typechecker;
import symtab.Flags._;
+import util.FreshNameCreator;
import scala.collection.mutable.ListBuffer;
/**
@@ -22,7 +23,7 @@ import scala.collection.mutable.ListBuffer;
import definitions._; // standard classes and methods
import typer.{typed}; // methods to type trees
- def addSyntheticMethods(templ: Template, clazz: Symbol): Template = {
+ def addSyntheticMethods(templ: Template, clazz: Symbol, unit: CompilationUnit): Template = {
def hasImplementation(name: Name): boolean = {
val sym = clazz.info.nonPrivateMember(name);
@@ -102,11 +103,30 @@ import scala.collection.mutable.ListBuffer;
typed(DefDef(method, vparamss => gen.mkRef(clazz.sourceModule)))
}
+ def newAccessorMethod(tree: Tree): Tree = tree match {
+ case DefDef(_, _, _, _, _, rhs) =>
+ val newAcc = tree.symbol.cloneSymbol;
+ newAcc.name = unit.fresh.newName(""+tree.symbol.name+"$");
+ newAcc.setFlag(SYNTHETIC).resetFlag(ACCESSOR | PARAMACCESSOR);
+ newAcc.owner.info.decls enter newAcc;
+ val result = typed(DefDef(newAcc, vparamss => rhs.duplicate));
+ System.out.println("new acc method " + result)
+ result
+ }
+
val ts = new ListBuffer[Tree];
if ((clazz hasFlag CASE) && !phase.erasedTypes) {
// case classes are implicitly declared serializable
clazz.attributes = Pair(SerializableAttr, List()) :: clazz.attributes;
+ for (val stat <- templ.body) {
+ if (stat.isDef && stat.symbol.isMethod && stat.symbol.hasFlag(CASEACCESSOR) &&
+ (stat.symbol.hasFlag(PRIVATE | PROTECTED) || stat.symbol.privateWithin != NoSymbol)) {
+ ts += newAccessorMethod(stat);
+ stat.symbol.resetFlag(CASEACCESSOR)
+ }
+ }
+
ts += tagMethod;
if (clazz.isModuleClass) {
if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod;
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 551fb0bd6c..4179674f94 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -573,7 +573,7 @@ import scala.collection.mutable.{HashMap, ListBuffer}
val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(cdef.tpt))
val impl1 = newTyper(context.make(cdef.impl, clazz, new Scope()))
.typedTemplate(cdef.impl, parentTypes(cdef.impl))
- val impl2 = addSyntheticMethods(impl1, clazz)
+ val impl2 = addSyntheticMethods(impl1, clazz, context.unit)
val ret = copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl2)
.setType(NoType)
ret
@@ -583,7 +583,7 @@ import scala.collection.mutable.{HashMap, ListBuffer}
val clazz = mdef.symbol.moduleClass
val impl1 = newTyper(context.make(mdef.impl, clazz, new Scope()))
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
- val impl2 = addSyntheticMethods(impl1, clazz)
+ val impl2 = addSyntheticMethods(impl1, clazz, context.unit)
copy.ModuleDef(mdef, mdef.mods, mdef.name, impl2) setType NoType
}
diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala
index 19f4bf789d..7921ec6e4f 100644
--- a/src/library/scala/List.scala
+++ b/src/library/scala/List.scala
@@ -1098,7 +1098,7 @@ case object Nil extends List[All] {
* @version 1.0, 15/07/2003
*/
[SerialVersionUID(0L - 8476791151983527571L)]
-final case class ::[b](hd: b, var tl: List[b]) extends List[b] {
+final case class ::[b](hd: b, /*private[scala]*/ var tl: List[b]) extends List[b] {
def head = hd;
def tail = tl;
def isEmpty: boolean = false;