From c956a27c3278b99d45676c268955a9e58a1ed15c Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 12 Feb 2014 14:41:36 +0100 Subject: SI-5900 Fix pattern inference regression This commit does not close SI-5900. It only addresses a regression in 2.11 prereleases caused by SI-7886. The fix for SI-7886 was incomplete (as shown by the last commit) and incorrect (as shown by the regression in pos/t5900a.scala and the fact it ended up inferring type parameters.) I believe that the key to fixing this problem will be unifying the inference of case class constructor patterns and extractor patterns. I've explored that idea: https://gist.github.com/retronym/7704153 https://github.com/retronym/scala/compare/ticket/5900 But didn't quite get there. --- .../tools/nsc/typechecker/PatternTypers.scala | 8 +++--- test/files/neg/t4818.check | 2 +- test/files/neg/t5189.check | 2 +- test/files/neg/t6680a.flags | 1 + test/files/neg/t6829.check | 12 ++++----- test/files/neg/t7886.check | 6 ----- test/files/neg/t7886.scala | 22 ---------------- test/files/pos/pattern-typing.scala | 29 ---------------------- test/files/pos/t5900a.scala | 9 +++++++ test/pending/neg/t7886.scala | 22 ++++++++++++++++ test/pending/pos/pattern-typing.scala | 29 ++++++++++++++++++++++ 11 files changed, 74 insertions(+), 68 deletions(-) create mode 100644 test/files/neg/t6680a.flags delete mode 100644 test/files/neg/t7886.check delete mode 100644 test/files/neg/t7886.scala delete mode 100644 test/files/pos/pattern-typing.scala create mode 100644 test/files/pos/t5900a.scala create mode 100644 test/pending/neg/t7886.scala create mode 100644 test/pending/pos/pattern-typing.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala index 41c656f8ce..cf3f265f0c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala @@ -221,10 +221,12 @@ trait PatternTypers { * see test/files/../t5189*.scala */ private def convertToCaseConstructor(tree: Tree, caseClass: Symbol, ptIn: Type): Tree = { - def untrustworthyPt = ( + // TODO SI-7886 / SI-5900 This is well intentioned but doesn't quite hit the nail on the head. + // For now, I've put it completely behind -Xstrict-inference. + val untrustworthyPt = settings.strictInference && ( ptIn =:= AnyTpe || ptIn =:= NothingTpe - || settings.strictInference && ptIn.typeSymbol != caseClass + || ptIn.typeSymbol != caseClass ) val variantToSkolem = new VariantToSkolemMap val caseClassType = tree.tpe.prefix memberType caseClass @@ -371,4 +373,4 @@ trait PatternTypers { } } } -} \ No newline at end of file +} diff --git a/test/files/neg/t4818.check b/test/files/neg/t4818.check index 8a2c024b30..a5e15e456b 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: A + required: Nothing 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 aecc1d11c4..4885de99cd 100644 --- a/test/files/neg/t5189.check +++ b/test/files/neg/t5189.check @@ -1,5 +1,5 @@ t5189.scala:3: error: type mismatch; - found : T => U + found : Nothing => Any required: Any => Any def f(x: Any): Any => Any = x match { case Foo(bar) => bar } ^ diff --git a/test/files/neg/t6680a.flags b/test/files/neg/t6680a.flags new file mode 100644 index 0000000000..19243266d1 --- /dev/null +++ b/test/files/neg/t6680a.flags @@ -0,0 +1 @@ +-Xstrict-inference \ No newline at end of file diff --git a/test/files/neg/t6829.check b/test/files/neg/t6829.check index a0b43e3b52..914a1c9260 100644 --- a/test/files/neg/t6829.check +++ b/test/files/neg/t6829.check @@ -16,32 +16,32 @@ 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 T1) + found : s.type (with underlying type Any) required: _53.State where val _53: G val r = rewards(agent).r(s,a,s2) ^ t6829.scala:50: error: type mismatch; - found : a.type (with underlying type T2) + found : a.type (with underlying type Any) required: _53.Action where val _53: G val r = rewards(agent).r(s,a,s2) ^ t6829.scala:50: error: type mismatch; - found : s2.type (with underlying type T3) + found : s2.type (with underlying type Any) 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 T1) + found : s.type (with underlying type Any) required: _50.State agent.learn(s,a,s2,r): G#Agent ^ t6829.scala:51: error: type mismatch; - found : a.type (with underlying type T2) + found : a.type (with underlying type Any) required: _50.Action agent.learn(s,a,s2,r): G#Agent ^ t6829.scala:51: error: type mismatch; - found : s2.type (with underlying type T3) + found : s2.type (with underlying type Any) 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 deleted file mode 100644 index 338eee9708..0000000000 --- a/test/files/neg/t7886.check +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 55d80a0a43..0000000000 --- a/test/files/neg/t7886.scala +++ /dev/null @@ -1,22 +0,0 @@ -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) diff --git a/test/files/pos/pattern-typing.scala b/test/files/pos/pattern-typing.scala deleted file mode 100644 index 7286cc38af..0000000000 --- a/test/files/pos/pattern-typing.scala +++ /dev/null @@ -1,29 +0,0 @@ -import scala.language.higherKinds - -trait Bound[B] - -package p1 { - case class Sub[B <: Bound[B]](p: B) - object Test { - def g[A](x: Bound[A]) = () - def f(x: Any) = x match { case Sub(p) => g(p) } - } -} - -package p2 { - trait Traversable[+A] { def head: A = ??? } - trait Seq[+A] extends Traversable[A] { def length: Int = ??? } - - case class SubHK[B <: Bound[B], CC[X] <: Traversable[X]](xs: CC[B]) - class MyBound extends Bound[MyBound] - class MySeq extends Seq[MyBound] - - object Test { - def g[B](x: Bound[B]) = () - - def f1(x: Any) = x match { case SubHK(xs) => xs } - def f2[B <: Bound[B], CC[X] <: Traversable[X]](sub: SubHK[B, CC]): CC[B] = sub match { case SubHK(xs) => xs } - def f3 = g(f1(SubHK(new MySeq)).head) - def f4 = g(f2(SubHK(new MySeq)).head) - } -} diff --git a/test/files/pos/t5900a.scala b/test/files/pos/t5900a.scala new file mode 100644 index 0000000000..cb02f67fb2 --- /dev/null +++ b/test/files/pos/t5900a.scala @@ -0,0 +1,9 @@ +case class Transition[S](x: S) + +object C + +object Test { + (??? : Any) match { + case Transition(C) => + } +} diff --git a/test/pending/neg/t7886.scala b/test/pending/neg/t7886.scala new file mode 100644 index 0000000000..55d80a0a43 --- /dev/null +++ b/test/pending/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) diff --git a/test/pending/pos/pattern-typing.scala b/test/pending/pos/pattern-typing.scala new file mode 100644 index 0000000000..7286cc38af --- /dev/null +++ b/test/pending/pos/pattern-typing.scala @@ -0,0 +1,29 @@ +import scala.language.higherKinds + +trait Bound[B] + +package p1 { + case class Sub[B <: Bound[B]](p: B) + object Test { + def g[A](x: Bound[A]) = () + def f(x: Any) = x match { case Sub(p) => g(p) } + } +} + +package p2 { + trait Traversable[+A] { def head: A = ??? } + trait Seq[+A] extends Traversable[A] { def length: Int = ??? } + + case class SubHK[B <: Bound[B], CC[X] <: Traversable[X]](xs: CC[B]) + class MyBound extends Bound[MyBound] + class MySeq extends Seq[MyBound] + + object Test { + def g[B](x: Bound[B]) = () + + def f1(x: Any) = x match { case SubHK(xs) => xs } + def f2[B <: Bound[B], CC[X] <: Traversable[X]](sub: SubHK[B, CC]): CC[B] = sub match { case SubHK(xs) => xs } + def f3 = g(f1(SubHK(new MySeq)).head) + def f4 = g(f2(SubHK(new MySeq)).head) + } +} -- cgit v1.2.3