diff options
author | Paul Phillips <paulp@improving.org> | 2013-09-30 12:11:49 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-10-01 20:26:54 -0700 |
commit | 95d5554b9a263e3eb060c181463234f3e79864ab (patch) | |
tree | ab5d0185f0096d723403c14209fe638d337463ec /test/files | |
parent | bef9e52d7337dafcc1f507ff1d93241f12f7c6d9 (diff) | |
download | scala-95d5554b9a263e3eb060c181463234f3e79864ab.tar.gz scala-95d5554b9a263e3eb060c181463234f3e79864ab.tar.bz2 scala-95d5554b9a263e3eb060c181463234f3e79864ab.zip |
SI-7886 unsoundness in pattern matcher.
I tracked down what was behind the issue described here:
// TODO: fix the illegal type bound in pos/t602 -- type inference
// messes up before we get here:
/*override def equals(x$1: Any): Boolean = ...
// Span[Any] --> Any is not a legal type argument for Span!
val o5: Option[com.mosol.sl.Span[Any]] =
*/
...which led straight to the unsoundness seen in neg/t7886.
It is dangerous to have an expected type of "Any" because
the type system will blithely ignore kind errors, since "Any"
can absorb anything. The consequence in this instance was
that inferring the case constructor for a type like
Foo[T <: Bound]
if done with expected type Any, this would come up with Foo[Any].
I altered it to use expected type Foo[T], which lets the dummy
type parameter survive to carry the bound forward and restores
sense to the inference. The before/after output for -Xprint:patmat
on pos/t602.scala is:
15c15
< if (x1.isInstanceOf[com.mosol.sl.Span[Any]])
---
> if (x1.isInstanceOf[com.mosol.sl.Span[K]])
17c17
< <synthetic> val x2: com.mosol.sl.Span[Any] = \
(x1.asInstanceOf[com.mosol.sl.Span[Any]]: com.mosol.sl.Span[Any]);
---
> <synthetic> val x2: com.mosol.sl.Span[K] = \
(x1.asInstanceOf[com.mosol.sl.Span[K]]: com.mosol.sl.Span[K]);
19,20c19,20
< val low$0: Option[Any] = x2.low;
< val high$0: Option[Any] = x2.high;
---
> val low$0: Option[K] = x2.low;
> val high$0: Option[K] = x2.high;
A file in the library depended (needlessly) on the unsoundness.
It was easy to fix but reminds us this may affect existing code.
Diffstat (limited to 'test/files')
-rw-r--r-- | test/files/neg/t4818.check | 2 | ||||
-rw-r--r-- | test/files/neg/t5189.check | 4 | ||||
-rw-r--r-- | test/files/neg/t6829.check | 4 | ||||
-rw-r--r-- | test/files/neg/t7886.check | 6 | ||||
-rw-r--r-- | test/files/neg/t7886.scala | 22 |
5 files changed, 33 insertions, 5 deletions
diff --git a/test/files/neg/t4818.check b/test/files/neg/t4818.check index a5e15e456b..8a2c024b30 100644 --- a/test/files/neg/t4818.check +++ b/test/files/neg/t4818.check @@ -1,6 +1,6 @@ t4818.scala:4: error: type mismatch; found : Int(5) - required: Nothing + required: A def f(x: Any) = x match { case Fn(f) => f(5) } ^ one error found diff --git a/test/files/neg/t5189.check b/test/files/neg/t5189.check index 7762f465dc..aecc1d11c4 100644 --- a/test/files/neg/t5189.check +++ b/test/files/neg/t5189.check @@ -1,6 +1,6 @@ t5189.scala:3: error: type mismatch; - found : Nothing => Any + found : T => U required: Any => Any def f(x: Any): Any => Any = x match { case Foo(bar) => bar } ^ -one error found
\ No newline at end of file +one error found diff --git a/test/files/neg/t6829.check b/test/files/neg/t6829.check index 7c3c66e0f2..c7c641844e 100644 --- a/test/files/neg/t6829.check +++ b/test/files/neg/t6829.check @@ -16,12 +16,12 @@ t6829.scala:49: error: not found: value nextState val (s,a,s2) = (state,actions(agent),nextState) ^ t6829.scala:50: error: type mismatch; - found : s.type (with underlying type Any) + found : s.type (with underlying type T1) required: _53.State where val _53: G val r = rewards(agent).r(s,a,s2) ^ t6829.scala:51: error: type mismatch; - found : s.type (with underlying type Any) + found : s.type (with underlying type T1) required: _50.State agent.learn(s,a,s2,r): G#Agent ^ diff --git a/test/files/neg/t7886.check b/test/files/neg/t7886.check new file mode 100644 index 0000000000..338eee9708 --- /dev/null +++ b/test/files/neg/t7886.check @@ -0,0 +1,6 @@ +t7886.scala:10: error: type mismatch; + found : Contra[A] + required: Contra[Any] + case Unravel(m, msg) => g(m) + ^ +one error found diff --git a/test/files/neg/t7886.scala b/test/files/neg/t7886.scala new file mode 100644 index 0000000000..55d80a0a43 --- /dev/null +++ b/test/files/neg/t7886.scala @@ -0,0 +1,22 @@ +trait Covariant[+A] +trait Contra[-A] { def accept(p: A): Unit } +trait Invariant[A] extends Covariant[A] with Contra[A] + +case class Unravel[A](m: Contra[A], msg: A) + +object Test extends Covariant[Any] { + def g(m: Contra[Any]): Unit = m accept 5 + def f(x: Any): Unit = x match { + case Unravel(m, msg) => g(m) + case _ => + } + def main(args: Array[String]) { + f(Unravel[String](new Contra[String] { def accept(x: String) = x.length }, "")) + } +} +// java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String +// at Test$$anon$1.accept(a.scala:18) +// at Test$.g(a.scala:13) +// at Test$.f(a.scala:15) +// at Test$.main(a.scala:18) +// at Test.main(a.scala) |