diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-08-13 16:21:44 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-08-13 16:21:44 +0000 |
commit | d0f20624930e529f327ebc83cf2c042056cabb7f (patch) | |
tree | 5fedaeaeb8f412f894c60c24c182921191e9f85e /src/compiler | |
parent | 9550c2077cc69434a460171ddd021a1de7ca1da4 (diff) | |
download | scala-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/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 48 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 9 |
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) |