summaryrefslogtreecommitdiff
path: root/test/files/neg
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-11-22 16:28:51 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-11-23 09:36:16 +0100
commit518635385ac1ba14aa230de3e431793331300546 (patch)
tree0f59b8af02591bddf711ecc485623432313510f0 /test/files/neg
parentc243435f113615b2f7407fbd683c93ec16c73749 (diff)
downloadscala-518635385ac1ba14aa230de3e431793331300546.tar.gz
scala-518635385ac1ba14aa230de3e431793331300546.tar.bz2
scala-518635385ac1ba14aa230de3e431793331300546.zip
SI-7872 Plug a variance exploit in refinement types
Refinement types are collapsed to a TypeTree with an original during type checking; this was enough to evade variance validation in refchecks. This commit: - validates the original of `TypeTree`s in refchecks - changes VarianceValidator to recurse into: - the originals of `TypeTree`s - `TypTree` (to cover, e.g. `CompoundTypeTree` / `SelectFromTypeTree`) It also finds an unreported variance violation in an existing test case, variances.scala. This looks to be legitimate.
Diffstat (limited to 'test/files/neg')
-rw-r--r--test/files/neg/t7872.check10
-rw-r--r--test/files/neg/t7872.scala9
-rw-r--r--test/files/neg/t7872b.check7
-rw-r--r--test/files/neg/t7872b.scala23
-rw-r--r--test/files/neg/t7872c.check11
-rw-r--r--test/files/neg/t7872c.scala8
-rw-r--r--test/files/neg/variances.check5
7 files changed, 72 insertions, 1 deletions
diff --git a/test/files/neg/t7872.check b/test/files/neg/t7872.check
new file mode 100644
index 0000000000..57d9772abc
--- /dev/null
+++ b/test/files/neg/t7872.check
@@ -0,0 +1,10 @@
+t7872.scala:6: error: contravariant type a occurs in covariant position in type [-a]Cov[a] of type l
+ type x = {type l[-a] = Cov[a]}
+ ^
+t7872.scala:8: error: covariant type a occurs in contravariant position in type [+a]Inv[a] of type l
+ foo[({type l[+a] = Inv[a]})#l]
+ ^
+t7872.scala:5: error: contravariant type a occurs in covariant position in type [-a]Cov[a] of type l
+ type l[-a] = Cov[a]
+ ^
+three errors found
diff --git a/test/files/neg/t7872.scala b/test/files/neg/t7872.scala
new file mode 100644
index 0000000000..66d22a0715
--- /dev/null
+++ b/test/files/neg/t7872.scala
@@ -0,0 +1,9 @@
+trait Cov[+A]
+trait Inv[-A]
+
+object varianceExploit {
+ type l[-a] = Cov[a]
+ type x = {type l[-a] = Cov[a]}
+ def foo[M[_]] = ()
+ foo[({type l[+a] = Inv[a]})#l]
+}
diff --git a/test/files/neg/t7872b.check b/test/files/neg/t7872b.check
new file mode 100644
index 0000000000..0dc4e76301
--- /dev/null
+++ b/test/files/neg/t7872b.check
@@ -0,0 +1,7 @@
+t7872b.scala:8: error: contravariant type a occurs in covariant position in type [-a]List[a] of type l
+ def oops1 = down[({type l[-a] = List[a]})#l](List('whatever: Object)).head + "oops"
+ ^
+t7872b.scala:19: error: covariant type a occurs in contravariant position in type [+a]coinv.Stringer[a] of type l
+ def oops2 = up[({type l[+a] = Stringer[a]})#l]("printed: " + _)
+ ^
+two errors found
diff --git a/test/files/neg/t7872b.scala b/test/files/neg/t7872b.scala
new file mode 100644
index 0000000000..307a1470c5
--- /dev/null
+++ b/test/files/neg/t7872b.scala
@@ -0,0 +1,23 @@
+object coinv {
+ def up[F[+_]](fa: F[String]): F[Object] = fa
+ def down[F[-_]](fa: F[Object]): F[String] = fa
+
+ up(List("hi"))
+
+ // should not compile; `l' is unsound
+ def oops1 = down[({type l[-a] = List[a]})#l](List('whatever: Object)).head + "oops"
+ // scala> oops1
+ // java.lang.ClassCastException: scala.Symbol cannot be cast to java.lang.String
+ // at com.nocandysw.coinv$.oops1(coinv.scala:12)
+
+ type Stringer[-A] = A => String
+ down[Stringer](_.toString)
+ // [error] type A is contravariant, but type _ is declared covariant
+ // up[Stringer]("printed: " + _)
+
+ // should not compile; `l' is unsound
+ def oops2 = up[({type l[+a] = Stringer[a]})#l]("printed: " + _)
+ // scala> oops2(Some(33))
+ // java.lang.ClassCastException: scala.Some cannot be cast to java.lang.String
+ // at com.nocandysw.coinv$$anonfun$oops2$1.apply(coinv.scala:20)
+}
diff --git a/test/files/neg/t7872c.check b/test/files/neg/t7872c.check
new file mode 100644
index 0000000000..469449dbd5
--- /dev/null
+++ b/test/files/neg/t7872c.check
@@ -0,0 +1,11 @@
+t7872c.scala:7: error: inferred kinds of the type arguments (List) do not conform to the expected kinds of the type parameters (type F).
+List's type parameters do not match type F's expected parameters:
+type A is covariant, but type _ is declared contravariant
+ down(List('whatever: Object))
+ ^
+t7872c.scala:7: error: type mismatch;
+ found : List[Object]
+ required: F[Object]
+ down(List('whatever: Object))
+ ^
+two errors found
diff --git a/test/files/neg/t7872c.scala b/test/files/neg/t7872c.scala
new file mode 100644
index 0000000000..fa12a523b5
--- /dev/null
+++ b/test/files/neg/t7872c.scala
@@ -0,0 +1,8 @@
+object coinv {
+ def up[F[+_]](fa: F[String]): F[Object] = fa
+ def down[F[-_]](fa: F[Object]): F[String] = fa
+
+ up(List("hi"))
+ // [error] type A is covariant, but type _ is declared contravariant
+ down(List('whatever: Object))
+}
diff --git a/test/files/neg/variances.check b/test/files/neg/variances.check
index 7d965e94dc..cb1a60a632 100644
--- a/test/files/neg/variances.check
+++ b/test/files/neg/variances.check
@@ -1,6 +1,9 @@
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]
^
+variances.scala:75: error: covariant type A occurs in contravariant position in type => A => A of value m
+ val m: A => A
+ ^
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
^
@@ -19,4 +22,4 @@ variances.scala:89: error: covariant type T occurs in invariant position in type
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]
^
-7 errors found
+8 errors found