summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala58
-rw-r--r--test/files/jvm/protectedacc.check3
-rw-r--r--test/files/jvm/protectedacc.scala7
-rw-r--r--test/files/pos/protected-t1010.scala27
-rw-r--r--test/pending/pos/t010/Presentations.scala10
-rw-r--r--test/pending/pos/t010/PresentationsX.scala8
6 files changed, 80 insertions, 33 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index bf847b3a58..a501c22896 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -113,6 +113,14 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
accDefs = accDefs.tail;
copy.Template(tree, parents, self, ownAccDefs.toList ::: body1);
+ case TypeApply(sel @ Select(This(_), name), args) =>
+ val sym = tree.symbol
+ if (needsProtectedAccessor(sym, tree.pos)) {
+ if (settings.debug.value) log("Adding protected accessor for " + tree);
+ transform(makeAccessor(sel.asInstanceOf[Select], args))
+ } else
+ tree
+
case Select(qual @ This(_), name) =>
val sym = tree.symbol
if ((sym hasFlag PARAMACCESSOR) && (sym.alias != NoSymbol)) {
@@ -127,7 +135,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
} else {
if (needsProtectedAccessor(sym, tree.pos)) {
if (settings.debug.value) log("Adding protected accessor for " + tree);
- transform(makeAccessor(tree.asInstanceOf[Select]))
+ transform(makeAccessor(tree.asInstanceOf[Select], List(EmptyTree)))
} else
tree
}
@@ -166,11 +174,19 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
} else tree
+ case TypeApply(sel @ Select(qual, name), args) =>
+ val sym = tree.symbol
+ if (needsProtectedAccessor(sym, tree.pos)) {
+ if (settings.debug.value) log("Adding protected accessor for tree: " + tree);
+ transform(makeAccessor(sel.asInstanceOf[Select], args))
+ } else
+ super.transform(tree)
+
case Select(qual, name) =>
val sym = tree.symbol
if (needsProtectedAccessor(sym, tree.pos)) {
if (settings.debug.value) log("Adding protected accessor for tree: " + tree);
- transform(makeAccessor(tree.asInstanceOf[Select]))
+ transform(makeAccessor(tree.asInstanceOf[Select], List(EmptyTree)))
} else
super.transform(tree)
@@ -220,7 +236,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
* the accessor and returns the the same member. The result is already
* typed.
*/
- private def makeAccessor(tree: Select): Tree = {
+ private def makeAccessor(tree: Select, targs: List[Tree]): Tree = {
val Select(qual, name) = tree
val sym = tree.symbol
val clazz = hostForAccessorOf(sym, currentOwner.enclClass)
@@ -233,22 +249,29 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
assert(clazz != NoSymbol, sym)
- if (settings.debug.value)
- log("Decided for host class: " + clazz)
+ if (settings.debug.value) log("Decided for host class: " + clazz)
+
val accName = nme.protName(sym.originalName)
- var protAcc = clazz.info.decl(accName)
val hasArgs = sym.tpe.paramTypes != Nil
- if (protAcc == NoSymbol) {
- val argTypes = tree.tpe // transform(sym.tpe)
- // 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(argTypes.finalResultType)) clazz.thisType else clazz.typeOfThis
+ 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 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) =>
+ PolyType(tparams, MethodType(List(objType), restpe.asSeenFrom(qual.tpe, sym.owner)))
+ case _ =>
+ MethodType(List(objType), memberType.asSeenFrom(qual.tpe, sym.owner))
+ }
+ if (settings.debug.value) log("accType: " + accType)
- protAcc = clazz.newMethod(tree.pos, nme.protName(sym.originalName))
- .setInfo(MethodType(List(objType),argTypes))
+ var protAcc = clazz.info.decl(accName).suchThat(_.tpe == accType)
+ if (protAcc == NoSymbol) {
+ protAcc = clazz.newMethod(tree.pos, nme.protName(sym.originalName)).setInfo(accType)
clazz.info.decls.enter(protAcc);
val code = DefDef(protAcc, vparamss => {
- val obj = vparamss.head.head
+ 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) } ))
@@ -259,7 +282,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
log(code)
accDefBuf(clazz) += typers(clazz).typed(code)
}
- var res: Tree = atPos(tree.pos) { Apply(Select(This(clazz), protAcc), List(qual)) }
+ var res: Tree = atPos(tree.pos) {
+ if (targs.head == EmptyTree)
+ Apply(Select(This(clazz), protAcc), List(qual))
+ else
+ Apply(TypeApply(Select(This(clazz), protAcc), targs), List(qual))
+ }
if (settings.debug.value)
log("Replaced " + tree + " with " + res)
if (hasArgs) typer.typedOperator(res) else typer.typed(res)
diff --git a/test/files/jvm/protectedacc.check b/test/files/jvm/protectedacc.check
index 2479af69c0..aaac0d613e 100644
--- a/test/files/jvm/protectedacc.check
+++ b/test/files/jvm/protectedacc.check
@@ -1,9 +1,12 @@
10
meth1(1) = 2
+meth1(1.0) = 2.0
meth2(1)(1) = prefix: 0
meth2(1)(1) = prefix: 0
meth3 = class [I
100 = 100
+id(1) = 1
+id('a') = a
count before: 3
count after: 4
10
diff --git a/test/files/jvm/protectedacc.scala b/test/files/jvm/protectedacc.scala
index fc6d5336d4..f5d05e21b4 100644
--- a/test/files/jvm/protectedacc.scala
+++ b/test/files/jvm/protectedacc.scala
@@ -29,9 +29,12 @@ package p {
protected val x = 10;
protected def meth1(x: Int) = x + 1;
+ protected def meth1(x: Double) = x + 1
protected def meth2(x: Int)(y: String) = y + (x - 1);
protected def meth3 = Array(1, 2)
+ protected def f[a](x: a) = x
+
def getA: this.type = this;
}
@@ -78,6 +81,7 @@ package p {
def m = {
Console.println(x);
Console.println("meth1(1) = " + meth1(1));
+ Console.println("meth1(1.0) = " + meth1(1.0));
// test accesses from closures
for (val x <- 1 until 3)
Console.println("meth2(1)(1) = " + meth2(1)("prefix: "));
@@ -87,6 +91,9 @@ package p {
val inc = meth2(1)_;
Console.println("100 = " + inc("10"));
+ Console.println("id(1) = " + f(1))
+ Console.println("id('a') = " + f("a"))
+
getA.x;
}
}
diff --git a/test/files/pos/protected-t1010.scala b/test/files/pos/protected-t1010.scala
new file mode 100644
index 0000000000..8575ddaaf7
--- /dev/null
+++ b/test/files/pos/protected-t1010.scala
@@ -0,0 +1,27 @@
+/** Check protected accessors involving polymorphic methods. */
+
+package pkg2 {
+
+trait PresentationsX extends pkg1.Presentations {
+ trait ProjectImpl extends super.ProjectImpl {
+ trait FileImpl extends super.FileImpl {
+ lockTyper(Console.println)
+ }
+ }
+}
+
+} // pkg2
+
+package pkg1 {
+
+trait Presentations {
+ trait ProjectImpl {
+ trait FileImpl
+ protected def lockTyper[T](f : => T) = {
+ if (this == null) None
+ else Some(f)
+ }
+ }
+}
+
+} // pkg1
diff --git a/test/pending/pos/t010/Presentations.scala b/test/pending/pos/t010/Presentations.scala
deleted file mode 100644
index ee2d94162f..0000000000
--- a/test/pending/pos/t010/Presentations.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package pkg1
-trait Presentations {
- trait ProjectImpl {
- trait FileImpl
- protected def lockTyper[T](f : => T) = {
- if (this == null) None
- else Some(f)
- }
- }
-}
diff --git a/test/pending/pos/t010/PresentationsX.scala b/test/pending/pos/t010/PresentationsX.scala
deleted file mode 100644
index 6d6c5bf504..0000000000
--- a/test/pending/pos/t010/PresentationsX.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package pkg2
-trait PresentationsX extends pkg1.Presentations {
- trait ProjectImpl extends super.ProjectImpl {
- trait FileImpl extends super.FileImpl {
- lockTyper(Console.println)
- }
- }
-}