From 518635385ac1ba14aa230de3e431793331300546 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 22 Nov 2013 16:28:51 +0100 Subject: 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. --- test/files/neg/t7872.check | 10 ++++++++++ test/files/neg/t7872.scala | 9 +++++++++ test/files/neg/t7872b.check | 7 +++++++ test/files/neg/t7872b.scala | 23 +++++++++++++++++++++++ test/files/neg/t7872c.check | 11 +++++++++++ test/files/neg/t7872c.scala | 8 ++++++++ test/files/neg/variances.check | 5 ++++- 7 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t7872.check create mode 100644 test/files/neg/t7872.scala create mode 100644 test/files/neg/t7872b.check create mode 100644 test/files/neg/t7872b.scala create mode 100644 test/files/neg/t7872c.check create mode 100644 test/files/neg/t7872c.scala (limited to 'test/files') 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 -- cgit v1.2.3