summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala55
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala41
-rw-r--r--test/files/jvm/protectedacc.check1
-rw-r--r--test/files/jvm/protectedacc.scala16
6 files changed, 27 insertions, 93 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index 21023ec72c..fae47dd0f3 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -61,7 +61,6 @@ object Flags extends Enumeration {
final val MODULEVAR = 0x40000000 // for variables: is the variable caching a module value
final val SYNTHETICMETH = 0x40000000 // for methods: synthetic method, but without SYNTHETIC flag
final val MONOMORPHIC = 0x40000000 // for type symbols: does not have type parameters
- final val PROTACCESSOR = 0x40000000 // for methods: a protected accessor
final val LAZY = 0x80000000L // symbol is a lazy val. can't have MUTABLE unless transformed by typer
final val IS_ERROR = 0x100000000L // symbol is an error symbol
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index d7ce3f22ac..258e109243 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -306,7 +306,7 @@ trait Symbols {
final def isImplOnly: Boolean =
hasFlag(PRIVATE) ||
(owner.isImplClass || owner.isTrait) &&
- ((hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | PROTACCESSOR | MODULE) || isConstructor) ||
+ ((hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE) || isConstructor) ||
(hasFlag(LIFTED) && isModule && isMethod))
/** Is this symbol a module variable ? */
@@ -1296,14 +1296,14 @@ trait Symbols {
}
override def alias: Symbol =
- if (hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN | PROTACCESSOR)) initialize.referenced
+ if (hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN)) initialize.referenced
else NoSymbol
def setAlias(alias: Symbol): TermSymbol = {
assert(alias != NoSymbol, this)
assert(!(alias hasFlag OVERLOADED), alias)
- assert(hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN | PROTACCESSOR), this)
+ assert(hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN), this)
referenced = alias
this
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index e4b60e4b3a..a0b66a6644 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -44,7 +44,7 @@ abstract class Mixin extends InfoTransform {
private def isImplementedStatically(sym: Symbol) =
sym.owner.isImplClass && sym.isMethod &&
(!sym.isModule || sym.hasFlag(PRIVATE | LIFTED)) &&
- (!(sym hasFlag (ACCESSOR | SUPERACCESSOR | PROTACCESSOR)) || sym.hasFlag(LAZY))
+ (!(sym hasFlag (ACCESSOR | SUPERACCESSOR)) || sym.hasFlag(LAZY))
/** A member of a trait is static only if it belongs only to the
* implementation class, not the interface, and it is implemented
@@ -266,8 +266,7 @@ abstract class Mixin extends InfoTransform {
assert(member1.alias != NoSymbol, member1)
val alias1 = rebindSuper(clazz, member.alias, mixinClass)
member1.asInstanceOf[TermSymbol] setAlias alias1
- } else if (member hasFlag PROTACCESSOR) {
- addMember(clazz, member.cloneSymbol(clazz)) setPos clazz.pos
+
} else if (member.isMethod && member.isModule && !(member hasFlag (LIFTED | BRIDGE))) {
// mixin objects: todo what happens with abstract objects?
addMember(clazz, member.cloneSymbol(clazz))
@@ -525,49 +524,6 @@ abstract class Mixin extends InfoTransform {
stat
}
- /**
- * Complete the given abstract method to be a protected accessor. It
- * assumes the accessed symbol is in the 'alias' field of the method's
- * symbol.
- *
- * If the accessed symbol comes from Java, and the access happens
- * in a trait method, it ignores the receiver parameter and uses 'this' instead.
- * This is because of the rules for protected access in Java, which prevent an
- * access from a subclass if the static type of the receiver is not a subtype
- * of the class where the access happens. For traits, the access always happens
- * in a class that cannot fulfill this requirement (an error for this case is
- * issued in 'SuperAccessors', so we are safe assuming 'this' here).
- */
- def completeProtectedAccessor(stat: Tree) = stat match {
- case DefDef(mods, name, tparams, List(vparams), tpt, EmptyTree)
- if stat.symbol.hasFlag(PROTACCESSOR) =>
- val sym = stat.symbol
- assert(sym.alias != NoSymbol, sym)
- log("Adding protected accessor for " + sym)
- sym.resetFlag(lateDEFERRED)
-
- val obj = vparams.head.symbol // receiver
- val receiver = if (sym.alias.hasFlag(JAVA) && sym.hasFlag(MIXEDIN)) This(clazz) else Ident(obj)
- val selection = Select(receiver, sym.alias)
- val rhs0 =
- if (sym.alias.isMethod)
- Apply(selection, vparams.tail.map(v => Ident(v.symbol)))
- else
- selection // a Java field
- val rhs1 = localTyper.typed(atPos(stat.pos)(rhs0), stat.symbol.tpe.resultType)
- val rhs2 = atPhase(currentRun.mixinPhase)(transform(rhs1))
- copy.DefDef(stat, mods, name, tparams, List(vparams), tpt, rhs2)
- case _ =>
- stat
- }
-
- /** Complete either a super accessor or a protected accessor. */
- def completeAbstractAccessors(stat: Tree) =
- if (stat.symbol.hasFlag(SUPERACCESSOR))
- completeSuperAccessor(stat)
- else
- completeProtectedAccessor(stat)
-
import lazyVals._
/** return a 'lazified' version of rhs.
@@ -700,8 +656,8 @@ abstract class Mixin extends InfoTransform {
} else if (!sym.isMethod) {
// add fields
addDef(position(sym), ValDef(sym))
- } else if (sym hasFlag (SUPERACCESSOR | PROTACCESSOR)) {
- // add superaccessors/protected accessors
+ } else if (sym hasFlag SUPERACCESSOR) {
+ // add superaccessors
addDefDef(sym, vparams => EmptyTree)
} else {
// add forwarders
@@ -713,8 +669,7 @@ abstract class Mixin extends InfoTransform {
}
}
stats1 = add(stats1, newDefs.toList)
- if (!clazz.isTrait)
- stats1 = stats1 map completeAbstractAccessors
+ if (!clazz.isTrait) stats1 = stats1 map completeSuperAccessor
stats1
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index c613790e6c..fd19bcd8b8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -199,13 +199,6 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Select(qual, name) =>
val sym = tree.symbol
if (needsProtectedAccessor(sym, tree.pos)) {
- if (currentOwner.enclClass.isTrait
- && sym.hasFlag(JAVA)
- && !qual.isInstanceOf[This])
- unit.error(tree.pos,
- "Implementation restriction: Cannot access Java protected member inside a trait,"
- + " when the qualifier is not 'this'.")
-
if (settings.debug.value) log("Adding protected accessor for tree: " + tree);
transform(makeAccessor(tree.asInstanceOf[Select], List(EmptyTree)))
} else
@@ -276,8 +269,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
val hasArgs = sym.tpe.paramTypes != Nil
val memberType = sym.tpe // transform(sym.tpe)
- // if the result type depends on the 'this' type of an enclosing class, the accessor
- // has to take a singleton type, otherwise it takes the type of this
+ // if the result type depends on the this type of an enclosing class, the accessor
+ // has to take an object of exactly this type, otherwise it's more general
val objType = if (isThisType(memberType.finalResultType)) clazz.thisType else clazz.typeOfThis
val accType = memberType match {
case PolyType(tparams, restpe) =>
@@ -289,12 +282,19 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
var protAcc = clazz.info.decl(accName).suchThat(_.tpe == accType)
if (protAcc == NoSymbol) {
- protAcc = clazz.newMethod(tree.pos, accName)
- .setInfo(accType)
- .setFlag(SYNTHETIC | PROTACCESSOR | lateDEFERRED)
- .setAlias(sym)
+ protAcc = clazz.newMethod(tree.pos, nme.protName(sym.originalName)).setInfo(accType)
clazz.info.decls.enter(protAcc);
- accDefBuf(clazz) += typers(clazz).typed(DefDef(protAcc, vparamss => EmptyTree))
+ val code = DefDef(protAcc, vparamss => {
+ val obj = vparamss.head.head // receiver
+ vparamss.tail.zip(allParamTypes(sym.tpe)).foldLeft(Select(Ident(obj), sym): Tree) (
+ (fun, pvparams) => {
+ Apply(fun, (List.map2(pvparams._1, pvparams._2) { (v, origTpe) => makeArg(v, obj, origTpe) } ))
+ })
+ })
+
+ if (settings.debug.value)
+ log(code)
+ accDefBuf(clazz) += typers(clazz).typed(code)
}
var res: Tree = atPos(tree.pos) {
if (targs.head == EmptyTree)
@@ -304,7 +304,6 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
if (settings.debug.value)
log("Replaced " + tree + " with " + res)
-
if (hasArgs) typer.typedOperator(res) else typer.typed(res)
}
@@ -389,23 +388,21 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
* classes, this has to be signaled as error.
*/
private def needsProtectedAccessor(sym: Symbol, pos: Position): Boolean = {
- val accNeeded = /* settings.debug.value && */
+ val res = /* settings.debug.value && */
((sym hasFlag PROTECTED)
- && (!validCurrentOwner
- || !(currentOwner.enclClass.thisSym isSubClass sym.owner)
- || currentOwner.enclClass.isTrait)
+ && (!validCurrentOwner || !(currentOwner.enclClass.thisSym isSubClass sym.owner))
&& (enclPackage(sym.owner) != enclPackage(currentOwner))
&& (enclPackage(sym.owner) == enclPackage(sym.accessBoundary(sym.owner))))
- if (accNeeded) {
+ if (res) {
val host = hostForAccessorOf(sym, currentOwner.enclClass)
if (host.thisSym != host) {
if (host.thisSym.tpe.typeSymbol.hasFlag(JAVA))
unit.error(pos, "Implementation restriction: " + currentOwner.enclClass + " accesses protected "
+ sym + " from self type " + host.thisSym.tpe)
false
- } else accNeeded
- } else accNeeded
+ } else res
+ } else res
}
/** Return the enclosing package of the given symbol. */
diff --git a/test/files/jvm/protectedacc.check b/test/files/jvm/protectedacc.check
index d36d85fef8..aaac0d613e 100644
--- a/test/files/jvm/protectedacc.check
+++ b/test/files/jvm/protectedacc.check
@@ -13,4 +13,3 @@ count after: 4
meth1(1) = 2
meth2(1)(1) = 10
100 = 100
-Foo
diff --git a/test/files/jvm/protectedacc.scala b/test/files/jvm/protectedacc.scala
index 59869c63ae..f5d05e21b4 100644
--- a/test/files/jvm/protectedacc.scala
+++ b/test/files/jvm/protectedacc.scala
@@ -19,25 +19,9 @@ object Test {
(new ji.Inner).m;
(new p.b.OuterObj.Inner).m
- cloneable.MainClone.run
}
}
-package cloneable {
-object MainClone {
- trait Foo extends Cloneable {
- def copy : Foo = clone.asInstanceOf[Foo]
- override def toString = "Foo"
- }
- def run : Unit = {
- val foo = new Foo {}
- Console.println(foo.copy)
- }
-}
-
-}
-
-
package p {
package a {