summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-04-02 08:23:57 -0700
committerPaul Phillips <paulp@improving.org>2012-04-02 09:23:25 -0700
commit03f32bd22f85bf3a6f8824dbe4a7a989e717c071 (patch)
tree4befb2ee97185754d9db670494698c035aeea445
parentf7535f72903f083b2444fb1d0b73363efa5482e9 (diff)
downloadscala-03f32bd22f85bf3a6f8824dbe4a7a989e717c071.tar.gz
scala-03f32bd22f85bf3a6f8824dbe4a7a989e717c071.tar.bz2
scala-03f32bd22f85bf3a6f8824dbe4a7a989e717c071.zip
Fix for SI-3272.
"References to the type parameters in object-private or object-protected values, variables, or methods (ยง5.2) of the class are not checked for their variance position." Review by @odersky.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala15
-rw-r--r--test/files/neg/variances.check19
-rw-r--r--test/files/neg/variances.scala29
-rw-r--r--test/files/pos/t3272.scala8
4 files changed, 48 insertions, 23 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 045614e773..54b711cebc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -951,17 +951,20 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
override def traverse(tree: Tree) {
tree match {
- case ClassDef(_, _, _, _) |
- TypeDef(_, _, _, _) =>
+ case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) =>
validateVariance(tree.symbol)
super.traverse(tree)
// ModuleDefs need not be considered because they have been eliminated already
case ValDef(_, _, _, _) =>
- validateVariance(tree.symbol)
+ if (!tree.symbol.hasLocalFlag)
+ validateVariance(tree.symbol)
case DefDef(_, _, tparams, vparamss, _, _) =>
- validateVariance(tree.symbol)
- traverseTrees(tparams)
- traverseTreess(vparamss)
+ // No variance check for object-private/protected methods/values.
+ if (!tree.symbol.hasLocalFlag) {
+ validateVariance(tree.symbol)
+ traverseTrees(tparams)
+ traverseTreess(vparamss)
+ }
case Template(_, _, _) =>
super.traverse(tree)
case _ =>
diff --git a/test/files/neg/variances.check b/test/files/neg/variances.check
index dc72b05e1e..0643e533b7 100644
--- a/test/files/neg/variances.check
+++ b/test/files/neg/variances.check
@@ -1,16 +1,19 @@
variances.scala:4: error: covariant type A occurs in contravariant position in type test.Vector[A] of value x
- def append(x: Vector[A]): Vector[A]
+ def append(x: Vector[A]): Vector[A]
^
-variances.scala:14: error: covariant type A occurs in contravariant position in type A of value a
- private[this] def setA(a : A) = this.a = a
- ^
-variances.scala:16: error: covariant type A occurs in invariant position in supertype test.C[A] of object Baz
+variances.scala:18: error: covariant type A occurs in contravariant position in type A of value a
+ private def setA3(a : A) = this.a = a
+ ^
+variances.scala:19: error: covariant type A occurs in contravariant position in type A of value a
+ protected def setA4(a : A) = this.a = a
+ ^
+variances.scala:21: error: covariant type A occurs in invariant position in supertype test.C[A] of object Baz
object Baz extends C[A]
^
-variances.scala:63: error: covariant type A occurs in contravariant position in type => test.Covariant.T[A]{val m: A => A} of value x
+variances.scala:74: error: covariant type A occurs in contravariant position in type => test.Covariant.T[A]{val m: A => A} of value x
val x: T[A] {
^
-variances.scala:79: error: covariant type T occurs in contravariant position in type => test.TestAlias.B[C.this.A] of method foo
+variances.scala:90: error: covariant type T occurs in contravariant position in type => test.TestAlias.B[C.this.A] of method foo
def foo: B[A]
^
-5 errors found
+6 errors found
diff --git a/test/files/neg/variances.scala b/test/files/neg/variances.scala
index 726bc35270..10ca111cd0 100644
--- a/test/files/neg/variances.scala
+++ b/test/files/neg/variances.scala
@@ -1,7 +1,7 @@
package test
trait Vector[+A] {
- def append(x: Vector[A]): Vector[A]
+ def append(x: Vector[A]): Vector[A]
private[this] def append3(x: Vector[A]): Vector[A] = append(x)
}
@@ -11,19 +11,27 @@ object Covariant {
class Foo[+A] {
private[this] var a : A = _
def getA : A = a
- private[this] def setA(a : A) = this.a = a
-
+ // allowed
+ private[this] def setA1(a : A) = this.a = a
+ protected[this] def setA2(a : A) = this.a = a
+ // forbidden
+ private def setA3(a : A) = this.a = a
+ protected def setA4(a : A) = this.a = a
+
object Baz extends C[A]
trait Convert[B] {
def b2a(b : B) : A
- def doit(b : B) = setA(b2a(b))
+ def doit1(b : B) = setA1(b2a(b))
+ def doit2(b : B) = setA2(b2a(b))
+ def doit3(b : B) = setA3(b2a(b))
+ def doit4(b : B) = setA4(b2a(b))
}
}
class Foo2[+A] {
private[this] var a : A = _
def getA : A = a
- private[this] def setA(a : A) = this.a = a
-
+ private[this] def setA(a : A) = this.a = a
+
{
trait Convert[B] {
def b2a(b : B) : A
@@ -35,8 +43,8 @@ object Covariant {
class Foo3[+A] {
private[this] var a : A = _
def getA : A = a
- private[this] def setA(a : A) = this.a = a
-
+ private[this] def setA(a : A) = this.a = a
+
private[this] trait Convert[B] {
def b2a(b : B) : A
def doit(b : B) = setA(b2a(b))
@@ -54,7 +62,10 @@ object Covariant {
}
def main(args : Array[String]) {
val test = new Test
- test.c.doit(test.b)
+ test.c.doit1(test.b)
+ test.c.doit2(test.b)
+ test.c.doit3(test.b)
+ test.c.doit4(test.b)
val x : java.lang.Character = test.a.getA
Console.println("XXX " + x)
}
diff --git a/test/files/pos/t3272.scala b/test/files/pos/t3272.scala
new file mode 100644
index 0000000000..8efd5ded2c
--- /dev/null
+++ b/test/files/pos/t3272.scala
@@ -0,0 +1,8 @@
+trait A {
+ trait C[+T] {
+ protected[this] def f(t: T) {}
+ }
+ trait D[T] extends C[T] {
+ def g(t: T) { f(t) }
+ }
+}