summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala60
-rw-r--r--test/files/jvm/protectedacc.check10
-rw-r--r--test/files/jvm/protectedacc.scala51
3 files changed, 85 insertions, 36 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 1e7244e8d2..e41da55549 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -172,6 +172,13 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
val Select(qual, name) = tree
val sym = tree.symbol
val clazz = hostForAccessorOf(sym, currentOwner.enclClass)
+
+ /** Return a list of list of types of all value parameter sections. */
+ def allParamTypes(tpe: Type): List[List[Type]] = tpe match {
+ case MethodType(pts, res) => pts :: allParamTypes(res)
+ case _ => Nil
+ }
+
assert(clazz != NoSymbol, sym)
if (settings.debug.value)
log("Decided for host class: " + clazz)
@@ -179,29 +186,19 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
var protAcc = clazz.info.decl(accName)
val hasArgs = sym.tpe.paramTypes != Nil
if (protAcc == NoSymbol) {
- val resTpe = tree.tpe
- val argTypes =
- if (hasArgs)
- MethodType(
- sym.tpe.paramTypes map {t =>
-// Console.print("Transforming " + t + "(sym=" + t.symbol +") to ")
-// Console.println("" + clazz.typeOfThis + ".memberType = " + clazz.typeOfThis.memberType(t.symbol))
-
- if (!t.symbol.isAbstractType || t.symbol.isTypeParameter)
- clazz.typeOfThis.memberType(t.symbol)
- else
- t
- },
- resTpe.resultType /*sym.tpe.resultType*/)
- else
- resTpe.resultType /*sym.tpe.resultType*/
+ val argTypes = tree.tpe // transform(sym.tpe)
protAcc = clazz.newMethod(tree.pos, nme.protName(sym.originalName))
.setInfo(MethodType(List(clazz.typeOfThis),argTypes))
clazz.info.decls.enter(protAcc);
- val code = DefDef(protAcc, vparamss =>
- vparamss.tail.foldRight(Select(gen.mkAttributedRef(vparamss.head.head), sym): Tree) (
- (vparams, fun) => Apply(fun, (vparams map { v => makeArg(v, vparamss.head.head) } ))))
+ val code = DefDef(protAcc, vparamss => {
+ val obj = vparamss.head.head
+ 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)
@@ -212,16 +209,27 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (hasArgs) typer.typedOperator(res) else typer.typed(res)
}
- private def makeArg(v: Symbol, obj: Symbol): Tree = {
-// Console.println("" + v + ".tpe = " + v.tpe + " .symbol = "
-// + v.tpe.symbol + " isAbstractType = " + v.tpe.symbol.isAbstractType);
+ /** Adapt the given argument in call to protected member.
+ * Adaptation means adding a cast to a path-dependent type, for instance
+ *
+ * def prot$m(obj: Outer)(x: Inner) = obj.m(x.asInstanceOf[obj.Inner]).
+ *
+ * such a cast might be necessary when m expects an Outer.this.Inner (the
+ * outer of 'obj' and 'x' have to be the same). This restriction can't be
+ * expressed in the type system (but is implicit when defining method m).
+ */
+ private def makeArg(v: Symbol, obj: Symbol, expectedTpe: Type): Tree = {
val res = Ident(v)
+ val sym = v.tpe.symbol
- if (v.tpe.symbol.isAbstractType && !v.tpe.symbol.isTypeParameter) {
+ val isDependentType = expectedTpe match {
+ case TypeRef(ThisType(outerSym), _, _) if (obj.isSubClass(outerSym)) => true
+ case _ => false
+ }
+ if (isDependentType) {
val preciseTpe = typeRef(singleType(NoPrefix, obj), v.tpe.symbol, List())
- Console.println("precise tpe: " + preciseTpe)
- TypeApply(Select(res, definitions.Any_asInstanceOf),
- List(TypeTree(preciseTpe)))
+ TypeApply(Select(res, definitions.Any_asInstanceOf),
+ List(TypeTree(preciseTpe)))
}
else
res
diff --git a/test/files/jvm/protectedacc.check b/test/files/jvm/protectedacc.check
index ae0f39b997..2479af69c0 100644
--- a/test/files/jvm/protectedacc.check
+++ b/test/files/jvm/protectedacc.check
@@ -1,12 +1,12 @@
10
meth1(1) = 2
-meth2(1)(1) = 2
-meth2(1)(1) = 2
+meth2(1)(1) = prefix: 0
+meth2(1)(1) = prefix: 0
meth3 = class [I
-10++ = 11
+100 = 100
count before: 3
count after: 4
10
meth1(1) = 2
-meth2(1)(1) = 2
-10++ = 11
+meth2(1)(1) = 10
+100 = 100
diff --git a/test/files/jvm/protectedacc.scala b/test/files/jvm/protectedacc.scala
index a6bc8984c4..0fda40babe 100644
--- a/test/files/jvm/protectedacc.scala
+++ b/test/files/jvm/protectedacc.scala
@@ -29,11 +29,30 @@ package p {
protected val x = 10;
protected def meth1(x: Int) = x + 1;
- protected def meth2(x: Int)(y: Int) = x + y;
+ protected def meth2(x: Int)(y: String) = y + (x - 1);
protected def meth3 = Array(1, 2)
def getA: this.type = this;
}
+
+ /** Test type members */
+ trait HighlighterXXX {
+ type Node;
+ protected def highlight(node : Node) : Unit;
+ }
+
+ /** Test type parameters */
+ abstract class PolyA[a] {
+ protected def m(x: a): Unit;
+
+ class B {
+
+ trait Node {
+ def s: String = "";
+ }
+ protected def tie(x: Node): Unit = { x.s; () }
+ }
+ }
}
package b {
@@ -47,12 +66,12 @@ package p {
Console.println("meth1(1) = " + meth1(1));
// test accesses from closures
for (val x <- 1 until 3)
- Console.println("meth2(1)(1) = " + meth2(1)(1));
+ Console.println("meth2(1)(1) = " + meth2(1)("prefix: "));
Console.println("meth3 = " + meth3.getClass);
val inc = &meth2(1);
- Console.println("10++ = " + inc(10));
+ Console.println("100 = " + inc("10"));
getA.x;
}
@@ -76,14 +95,36 @@ package p {
def m = {
Console.println(x);
Console.println("meth1(1) = " + meth1(1));
- Console.println("meth2(1)(1) = " + meth2(1)(1));
+ Console.println("meth2(1)(1) = " + meth2(1)("1"));
val inc = &meth2(1);
- Console.println("10++ = " + inc(10));
+ Console.println("100 = " + inc("10"));
getA.x;
}
}
}
+
+ trait ScalaAutoEditXXX extends HighlighterXXX {
+ trait NodeImpl {
+ def self : Node;
+ highlight(self);
+ }
+ }
+
+ abstract class X[T] extends PolyA[T] {
+
+ trait Inner extends B {
+ def self: T;
+ def self2: Node;
+ def getB: Inner;
+
+ m(self)
+
+ trait InnerInner {
+ getB.tie(self2)
+ }
+ }
+ }
}
}