summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2010-08-13 16:21:44 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2010-08-13 16:21:44 +0000
commitd0f20624930e529f327ebc83cf2c042056cabb7f (patch)
tree5fedaeaeb8f412f894c60c24c182921191e9f85e /src
parent9550c2077cc69434a460171ddd021a1de7ca1da4 (diff)
downloadscala-d0f20624930e529f327ebc83cf2c042056cabb7f.tar.gz
scala-d0f20624930e529f327ebc83cf2c042056cabb7f.tar.bz2
scala-d0f20624930e529f327ebc83cf2c042056cabb7f.zip
closes #3663.
namers wasn't setting privateWithin on java-defined variables (btw, ) shouldn't clone carry over privateWithin? better treatment of linked ) class access boundary (only check for access within linked class if it ) actually exists ) would have liked more control for the test case: only javac should compile the java file, then scalac should compile the scala file and fail review by odersky
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala48
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala9
3 files changed, 40 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 96b065ae61..c7d198b638 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1074,6 +1074,7 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
/** A clone of this symbol, but with given owner */
final def cloneSymbol(owner: Symbol): Symbol = {
val newSym = cloneSymbolImpl(owner)
+ // newSym.privateWithin = privateWithin // ?
newSym.setInfo(info.cloneInfo(newSym))
.setFlag(this.rawflags).setAnnotations(this.annotations)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 7469388a08..42c1329edf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -8,6 +8,7 @@ package typechecker
import symtab.Flags._
import scala.collection.mutable.ListBuffer
+import annotation.tailrec
/** This trait ...
*
@@ -349,9 +350,26 @@ trait Contexts { self: Analyzer =>
* @return ...
*/
def isAccessible(sym: Symbol, pre: Type, superAccess: Boolean): Boolean = {
+ @inline def accessWithinLinked(ab: Symbol) = {
+ val linked = ab.linkedClassOfClass
+ // don't have access if there is no linked class
+ // (before adding the `ne NoSymbol` check, this was a no-op when linked eq NoSymbol,
+ // since `accessWithin(NoSymbol) == true` whatever the symbol)
+ (linked ne NoSymbol) && accessWithin(linked)
+ }
+
+ /** Are we inside definition of `ab'? */
+ def accessWithin(ab: Symbol) = {
+ // #3663: we must disregard package nesting if sym isJavaDefined
+ if(sym.isJavaDefined) {
+ // is `o` or one of its transitive owners equal to `ab`?
+ // stops at first package, since further owners can only be surrounding packages
+ @tailrec def abEnclosesStopAtPkg(o: Symbol): Boolean =
+ (o eq ab) || (!o.isPackageClass && (o ne NoSymbol) && abEnclosesStopAtPkg(o.owner))
+ abEnclosesStopAtPkg(owner)
+ } else (owner hasTransOwner ab)
+ }
- /** Are we inside definition of `sym'? */
- def accessWithin(sym: Symbol): Boolean = this.owner.ownersIterator contains sym
/*
var c = this
while (c != NoContext && c.owner != owner) {
@@ -373,18 +391,20 @@ trait Contexts { self: Analyzer =>
(pre == NoPrefix) || {
val ab = sym.accessBoundary(sym.owner)
- ((ab.isTerm || ab == definitions.RootClass)
- ||
- (accessWithin(ab) || accessWithin(ab.linkedClassOfClass)) &&
- (!sym.hasFlag(LOCAL) ||
- sym.owner.isImplClass || // allow private local accesses to impl classes
- (sym hasFlag PROTECTED) && isSubThisType(pre, sym.owner) ||
- pre =:= sym.owner.thisType)
- ||
- (sym hasFlag PROTECTED) &&
- (superAccess || sym.isConstructor ||
- (pre.widen.typeSymbol.isNonBottomSubClass(sym.owner) &&
- (isSubClassOfEnclosing(pre.widen.typeSymbol) || phase.erasedTypes))))
+ ( (ab.isTerm || ab == definitions.RootClass)
+ || (accessWithin(ab) || accessWithinLinked(ab)) &&
+ ( !sym.hasFlag(LOCAL)
+ || sym.owner.isImplClass // allow private local accesses to impl classes
+ || (sym hasFlag PROTECTED) && isSubThisType(pre, sym.owner)
+ || pre =:= sym.owner.thisType
+ )
+ || (sym hasFlag PROTECTED) &&
+ ( superAccess
+ || sym.isConstructor
+ || (pre.widen.typeSymbol.isNonBottomSubClass(sym.owner) &&
+ (isSubClassOfEnclosing(pre.widen.typeSymbol) || phase.erasedTypes))
+ )
+ )
// note: phase.erasedTypes disables last test, because after addinterfaces
// implementation classes are not in the superclass chain. If we enable the
// test, bug780 fails.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index b3ea178aaa..91d7b1d12c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -374,8 +374,9 @@ trait Namers { self: Analyzer =>
name.endsWith(nme.OUTER, nme.OUTER.length) ||
context.unit.isJava) &&
!mods.isLazy) {
- tree.symbol = enterInScope(owner.newValue(tree.pos, name)
- .setFlag(mods.flags))
+ val vsym = owner.newValue(tree.pos, name).setFlag(mods.flags);
+ if(context.unit.isJava) setPrivateWithin(tree, vsym, mods) // #3663
+ tree.symbol = enterInScope(vsym)
finish
} else {
val mods1 =
@@ -418,7 +419,7 @@ trait Namers { self: Analyzer =>
addBeanGetterSetter(vd, getter)
}
case DefDef(mods, nme.CONSTRUCTOR, tparams, _, _, _) =>
- var sym = owner.newConstructor(tree.pos).setFlag(mods.flags | owner.getFlag(ConstrFlags))
+ val sym = owner.newConstructor(tree.pos).setFlag(mods.flags | owner.getFlag(ConstrFlags))
setPrivateWithin(tree, sym, mods)
tree.symbol = enterInScope(sym)
finishWith(tparams)
@@ -428,7 +429,7 @@ trait Namers { self: Analyzer =>
case TypeDef(mods, name, tparams, _) =>
var flags: Long = mods.flags
if ((flags & PARAM) != 0L) flags |= DEFERRED
- var sym = new TypeSymbol(owner, tree.pos, name).setFlag(flags)
+ val sym = new TypeSymbol(owner, tree.pos, name).setFlag(flags)
setPrivateWithin(tree, sym, mods)
tree.symbol = enterInScope(sym)
finishWith(tparams)