From 95d5554b9a263e3eb060c181463234f3e79864ab Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 30 Sep 2013 12:11:49 -0700 Subject: 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 < val x2: com.mosol.sl.Span[Any] = \ (x1.asInstanceOf[com.mosol.sl.Span[Any]]: com.mosol.sl.Span[Any]); --- > 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. --- test/files/neg/t4818.check | 2 +- test/files/neg/t5189.check | 4 ++-- test/files/neg/t6829.check | 4 ++-- test/files/neg/t7886.check | 6 ++++++ test/files/neg/t7886.scala | 22 ++++++++++++++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 test/files/neg/t7886.check create mode 100644 test/files/neg/t7886.scala (limited to 'test/files/neg') 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) -- cgit v1.2.3 From 5708e9d73ba01c286d7155606b72caeab914face Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 1 Oct 2013 20:28:48 -0700 Subject: SI-6680 unsoundness in gadt typing. Introduces -Xstrict-inference to deal with the significant gap between soundness and what presently compiles. I'm hopeful that it's TOO strict, because it finds e.g. 75 errors compiling immutable/IntMap.scala, but it might be that bad. --- .../scala/tools/nsc/settings/ScalaSettings.scala | 1 + .../tools/nsc/typechecker/PatternTypers.scala | 43 ++++++++++++---------- src/library/scala/util/control/TailCalls.scala | 2 +- test/files/neg/gadts2-strict.check | 6 +++ test/files/neg/gadts2-strict.flags | 1 + test/files/neg/gadts2-strict.scala | 26 +++++++++++++ test/files/neg/gadts2.check | 6 +++ test/files/neg/gadts2.flags | 1 + test/files/neg/gadts2.scala | 12 ++++++ test/files/neg/run-gadts-strict.check | 21 +++++++++++ test/files/neg/run-gadts-strict.flags | 1 + test/files/neg/run-gadts-strict.scala | 18 +++++++++ test/files/neg/t6680a.check | 11 ++++++ test/files/neg/t6680a.scala | 18 +++++++++ test/files/neg/t6680b.flags | 1 + test/files/neg/t6680c.check | 6 +++ test/files/neg/t6680c.flags | 1 + test/files/pos/gadts2.scala | 2 +- test/files/pos/pattern-typing.scala | 29 +++++++++++++++ test/files/run/patmatnew.scala | 2 +- test/pending/neg/t6680a.scala | 13 ------- test/pending/neg/t6680b.check | 6 --- test/pending/neg/t6680b.scala | 10 ----- test/pending/neg/t6680c.scala | 17 --------- 24 files changed, 185 insertions(+), 69 deletions(-) create mode 100644 test/files/neg/gadts2-strict.check create mode 100644 test/files/neg/gadts2-strict.flags create mode 100644 test/files/neg/gadts2-strict.scala create mode 100644 test/files/neg/gadts2.check create mode 100644 test/files/neg/gadts2.flags create mode 100644 test/files/neg/gadts2.scala create mode 100644 test/files/neg/run-gadts-strict.check create mode 100644 test/files/neg/run-gadts-strict.flags create mode 100644 test/files/neg/run-gadts-strict.scala create mode 100644 test/files/neg/t6680a.check create mode 100644 test/files/neg/t6680a.scala create mode 100644 test/files/neg/t6680b.flags create mode 100644 test/files/neg/t6680c.check create mode 100644 test/files/neg/t6680c.flags create mode 100644 test/files/pos/pattern-typing.scala delete mode 100644 test/pending/neg/t6680a.scala delete mode 100644 test/pending/neg/t6680b.check delete mode 100644 test/pending/neg/t6680b.scala delete mode 100644 test/pending/neg/t6680c.scala (limited to 'test/files/neg') diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 96c93a838b..b6819066a6 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -111,6 +111,7 @@ trait ScalaSettings extends AbsScalaSettings val Xshowobj = StringSetting ("-Xshow-object", "object", "Show internal representation of object.", "") val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases.") val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "") + val strictInference = BooleanSetting ("-Xstrict-inference", "Don't infer known-unsound types") val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala index df4dd3d777..c2e7f32d62 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala @@ -74,7 +74,7 @@ trait PatternTypers { case tp => tp } - def typedConstructorPattern(fun0: Tree, pt: Type) = { + def typedConstructorPattern(fun0: Tree, pt: Type): Tree = { // Do some ad-hoc overloading resolution and update the tree's symbol and type // do not update the symbol if the tree's symbol's type does not define an unapply member // (e.g. since it's some method that returns an object with an unapply member) @@ -85,7 +85,7 @@ trait PatternTypers { // A case class with 23+ params has no unapply method. // A case class constructor be overloaded with unapply methods in the companion. if (caseClass.isCase && !unapplyMember(fun.tpe).isOverloaded) - convertToCaseConstructor(fun, caseClass, pt) + logResult(s"convertToCaseConstructor($fun, $caseClass, pt=$pt)")(convertToCaseConstructor(fun, caseClass, pt)) else if (hasUnapplyMember(fun)) fun else @@ -275,26 +275,30 @@ trait PatternTypers { private class VariantToSkolemMap extends TypeMap(trackVariance = true) { private val skolemBuffer = mutable.ListBuffer[TypeSymbol]() + // !!! FIXME - skipping this when variance.isInvariant allows unsoundness, see SI-5189 + // Test case which presently requires the exclusion is run/gadts.scala. + def eligible(tparam: Symbol) = ( + tparam.isTypeParameterOrSkolem + && tparam.owner.isTerm + && (settings.strictInference || !variance.isInvariant) + ) + def skolems = try skolemBuffer.toList finally skolemBuffer.clear() def apply(tp: Type): Type = mapOver(tp) match { - // !!! FIXME - skipping this when variance.isInvariant allows unsoundness, see SI-5189 - case tp @ TypeRef(NoPrefix, tpSym, Nil) if tpSym.isTypeParameterOrSkolem && tpSym.owner.isTerm => - if (variance.isInvariant) { - // if (variance.isInvariant) tpSym.tpeHK.bounds - devWarning(s"variantToSkolem skipping rewrite of $tpSym due to invariance") - return tp - } + case tp @ TypeRef(NoPrefix, tpSym, Nil) if eligible(tpSym) => val bounds = ( - if (variance.isPositive) TypeBounds.upper(tpSym.tpeHK) + if (variance.isInvariant) tpSym.tpeHK.bounds + else if (variance.isPositive) TypeBounds.upper(tpSym.tpeHK) else TypeBounds.lower(tpSym.tpeHK) ) // origin must be the type param so we can deskolemize val skolem = context.owner.newGADTSkolem(unit.freshTypeName("?"+tpSym.name), tpSym, bounds) skolemBuffer += skolem - skolem.tpe_* + logResult(s"Created gadt skolem $skolem: ${skolem.tpe_*} to stand in for $tpSym")(skolem.tpe_*) case tp1 => tp1 } } + /* * To deal with the type slack between actual (run-time) types and statically known types, for each abstract type T, * reflect its variance as a skolem that is upper-bounded by T (covariant position), or lower-bounded by T (contravariant). @@ -323,25 +327,24 @@ trait PatternTypers { * see test/files/../t5189*.scala */ private def convertToCaseConstructor(tree: Tree, caseClass: Symbol, ptIn: Type): Tree = { - // Unsoundness looms for those who infer type parameters with pt=Any. See SI-7886. - val pt = ( - if (ptIn =:= AnyTpe && caseClass.typeParams.nonEmpty) - devWarningResult(s"Evading kind-polymorphic expected type for case constructor of $caseClass")(caseClass.tpe_*) - else ptIn + def untrustworthyPt = ( + ptIn =:= AnyTpe + || ptIn =:= NothingTpe + || settings.strictInference && ptIn.typeSymbol != caseClass ) val variantToSkolem = new VariantToSkolemMap - val caseConstructorType = tree.tpe.prefix memberType caseClass memberType caseClass.primaryConstructor + val caseClassType = tree.tpe.prefix memberType caseClass + val caseConstructorType = caseClassType memberType caseClass.primaryConstructor val tree1 = TypeTree(caseConstructorType) setOriginal tree + val pt = if (untrustworthyPt) caseClassType else ptIn // have to open up the existential and put the skolems in scope // can't simply package up pt in an ExistentialType, because that takes us back to square one (List[_ <: T] == List[T] due to covariance) - val ptSafe = variantToSkolem(pt) // TODO: pt.skolemizeExistential(context.owner, tree) ? + val ptSafe = logResult(s"case constructor from (${tree.summaryString}, $caseClassType, $pt)")(variantToSkolem(pt)) val freeVars = variantToSkolem.skolems // use "tree" for the context, not context.tree: don't make another CaseDef context, // as instantiateTypeVar's bounds would end up there - log(s"convert ${tree.summaryString}: ${tree.tpe} to case constructor, pt=$ptSafe") - val ctorContext = context.makeNewScope(tree, context.owner) freeVars foreach ctorContext.scope.enter newTyper(ctorContext).infer.inferConstructorInstance(tree1, caseClass.typeParams, ptSafe) diff --git a/src/library/scala/util/control/TailCalls.scala b/src/library/scala/util/control/TailCalls.scala index c3e7d98073..953d5b407e 100644 --- a/src/library/scala/util/control/TailCalls.scala +++ b/src/library/scala/util/control/TailCalls.scala @@ -55,7 +55,7 @@ object TailCalls { case Done(a) => Call(() => f(a)) case c@Call(_) => Cont(c, f) // Take advantage of the monad associative law to optimize the size of the required stack - case Cont(s, g) => Cont(s, (x:Any) => g(x).flatMap(f)) + case c: Cont[a1, b1] => Cont(c.a, (x: a1) => c f x flatMap f) } /** Returns either the next step of the tailcalling computation, diff --git a/test/files/neg/gadts2-strict.check b/test/files/neg/gadts2-strict.check new file mode 100644 index 0000000000..960b35ed2f --- /dev/null +++ b/test/files/neg/gadts2-strict.check @@ -0,0 +1,6 @@ +gadts2-strict.scala:14: error: type mismatch; + found : Test.MyDouble + required: a + case NumTerm(n) => c.x = MyDouble(1.0) + ^ +one error found diff --git a/test/files/neg/gadts2-strict.flags b/test/files/neg/gadts2-strict.flags new file mode 100644 index 0000000000..19243266d1 --- /dev/null +++ b/test/files/neg/gadts2-strict.flags @@ -0,0 +1 @@ +-Xstrict-inference \ No newline at end of file diff --git a/test/files/neg/gadts2-strict.scala b/test/files/neg/gadts2-strict.scala new file mode 100644 index 0000000000..54978b7712 --- /dev/null +++ b/test/files/neg/gadts2-strict.scala @@ -0,0 +1,26 @@ +// A copy of pos/gadts2, which must fail under -Xstrict-inference. +object Test { + + abstract class Number + case class MyInt(n: Int) extends Number + case class MyDouble(d: Double) extends Number + + trait Term[a] + case class Cell[a](var x: a) extends Term[a] + final case class NumTerm(val n: Number) extends Term[Number] + + def f[a](t: Term[a], c: Cell[a]) { + t match { + case NumTerm(n) => c.x = MyDouble(1.0) + } + } + + val x: Term[Number] = NumTerm(MyInt(5)) + + def main(args: Array[String]) { + val cell = Cell[Number](MyInt(6)) + Console.println(cell) + f[Number](new NumTerm(MyInt(5)), cell) + Console.println(cell) + } +} diff --git a/test/files/neg/gadts2.check b/test/files/neg/gadts2.check new file mode 100644 index 0000000000..dc21f3f52c --- /dev/null +++ b/test/files/neg/gadts2.check @@ -0,0 +1,6 @@ +gadts2.scala:7: error: type mismatch; + found : String("abc") + required: B + (s1: Super[Any]) match { case Sub(f) => f("abc") } + ^ +one error found diff --git a/test/files/neg/gadts2.flags b/test/files/neg/gadts2.flags new file mode 100644 index 0000000000..19243266d1 --- /dev/null +++ b/test/files/neg/gadts2.flags @@ -0,0 +1 @@ +-Xstrict-inference \ No newline at end of file diff --git a/test/files/neg/gadts2.scala b/test/files/neg/gadts2.scala new file mode 100644 index 0000000000..156944b8d9 --- /dev/null +++ b/test/files/neg/gadts2.scala @@ -0,0 +1,12 @@ +trait Super[+A] +case class Sub[B](f: B => B) extends Super[B] + +object Test extends App { + val s1 = Sub((x: Int) => x) + + (s1: Super[Any]) match { case Sub(f) => f("abc") } +} +// java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer +// at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105) +// at Test$$anonfun$1.apply(a.scala:5) +// at Test$.delayedEndpoint$Test$1(a.scala:7) diff --git a/test/files/neg/run-gadts-strict.check b/test/files/neg/run-gadts-strict.check new file mode 100644 index 0000000000..b4d36c4629 --- /dev/null +++ b/test/files/neg/run-gadts-strict.check @@ -0,0 +1,21 @@ +run-gadts-strict.scala:12: error: type mismatch; + found : n.type (with underlying type Int) + required: T + case Lit(n) => n + ^ +run-gadts-strict.scala:13: error: type mismatch; + found : Int + required: T + case Succ(u) => eval(u) + 1 + ^ +run-gadts-strict.scala:14: error: type mismatch; + found : Boolean + required: T + case IsZero(u) => eval(u) == 0 + ^ +run-gadts-strict.scala:15: error: type mismatch; + found : T(in class If) + required: T(in method eval) + case If(c, u1, u2) => eval(if (eval(c)) u1 else u2) + ^ +four errors found diff --git a/test/files/neg/run-gadts-strict.flags b/test/files/neg/run-gadts-strict.flags new file mode 100644 index 0000000000..19243266d1 --- /dev/null +++ b/test/files/neg/run-gadts-strict.flags @@ -0,0 +1 @@ +-Xstrict-inference \ No newline at end of file diff --git a/test/files/neg/run-gadts-strict.scala b/test/files/neg/run-gadts-strict.scala new file mode 100644 index 0000000000..041d10d4bd --- /dev/null +++ b/test/files/neg/run-gadts-strict.scala @@ -0,0 +1,18 @@ +// A copy of run/gadts.scala, which must fail under -Xstrict-inference. +abstract class Term[T] +case class Lit(x: Int) extends Term[Int] +case class Succ(t: Term[Int]) extends Term[Int] +case class IsZero(t: Term[Int]) extends Term[Boolean] +case class If[T](c: Term[Boolean], + t1: Term[T], + t2: Term[T]) extends Term[T] + +object Test extends App { + def eval[T](t: Term[T]): T = t match { + case Lit(n) => n + case Succ(u) => eval(u) + 1 + case IsZero(u) => eval(u) == 0 + case If(c, u1, u2) => eval(if (eval(c)) u1 else u2) + } + println(eval(If(IsZero(Lit(1)), Lit(41), Succ(Lit(41))))) +} diff --git a/test/files/neg/t6680a.check b/test/files/neg/t6680a.check new file mode 100644 index 0000000000..03e4df10c1 --- /dev/null +++ b/test/files/neg/t6680a.check @@ -0,0 +1,11 @@ +t6680a.scala:10: error: type mismatch; + found : String("abc") + required: A + y.x = "abc" + ^ +t6680a.scala:17: error: type mismatch; + found : String("") + required: A + case class C[A](f:A=>A);def f(x:Any)=x match { case C(f)=>f("") };f(C[Int](x=>x)) + ^ +two errors found diff --git a/test/files/neg/t6680a.scala b/test/files/neg/t6680a.scala new file mode 100644 index 0000000000..93b796438f --- /dev/null +++ b/test/files/neg/t6680a.scala @@ -0,0 +1,18 @@ +case class Cell[A](var x: A) +object Test { + def f1(x: Any) = x match { case y @ Cell(_) => y } // Inferred type is Cell[Any] + def f2(x: Cell[_]) = x match { case y @ Cell(_) => y } // Inferred type is Cell[_] + def f3[A](x: Cell[A]) = x match { case y @ Cell(_) => y } // Inferred type is Cell[A] + + def main(args: Array[String]): Unit = { + val x = new Cell(1) + val y = f1(x) + y.x = "abc" + println(x.x + 1) + } +} + +// The tweetable variation +object Tweet { + case class C[A](f:A=>A);def f(x:Any)=x match { case C(f)=>f("") };f(C[Int](x=>x)) +} diff --git a/test/files/neg/t6680b.flags b/test/files/neg/t6680b.flags new file mode 100644 index 0000000000..a02d83efad --- /dev/null +++ b/test/files/neg/t6680b.flags @@ -0,0 +1 @@ +-Xstrict-inference diff --git a/test/files/neg/t6680c.check b/test/files/neg/t6680c.check new file mode 100644 index 0000000000..7a749de1f2 --- /dev/null +++ b/test/files/neg/t6680c.check @@ -0,0 +1,6 @@ +t6680c.scala:15: error: type mismatch; + found : String("a string!") + required: S + res match { case Unfold(s, f) => f("a string!") } + ^ +one error found diff --git a/test/files/neg/t6680c.flags b/test/files/neg/t6680c.flags new file mode 100644 index 0000000000..a02d83efad --- /dev/null +++ b/test/files/neg/t6680c.flags @@ -0,0 +1 @@ +-Xstrict-inference diff --git a/test/files/pos/gadts2.scala b/test/files/pos/gadts2.scala index fc2a7e4333..d77c8a7ba4 100644 --- a/test/files/pos/gadts2.scala +++ b/test/files/pos/gadts2.scala @@ -4,7 +4,7 @@ object Test { case class MyInt(n: Int) extends Number case class MyDouble(d: Double) extends Number - trait Term[+a] + trait Term[a] case class Cell[a](var x: a) extends Term[a] final case class NumTerm(val n: Number) extends Term[Number] diff --git a/test/files/pos/pattern-typing.scala b/test/files/pos/pattern-typing.scala new file mode 100644 index 0000000000..7286cc38af --- /dev/null +++ b/test/files/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) + } +} diff --git a/test/files/run/patmatnew.scala b/test/files/run/patmatnew.scala index 35b733d080..b212e10f8d 100644 --- a/test/files/run/patmatnew.scala +++ b/test/files/run/patmatnew.scala @@ -114,7 +114,7 @@ object Test { val foo2 = new Foo(2) def run() { val res = (foo1.Bar(2): Any) match { - case foo2.Bar(2) => false + case foo1.Bar(2) => true } assert(res) diff --git a/test/pending/neg/t6680a.scala b/test/pending/neg/t6680a.scala deleted file mode 100644 index 745334b1cd..0000000000 --- a/test/pending/neg/t6680a.scala +++ /dev/null @@ -1,13 +0,0 @@ -case class Cell[A](var x: A) -object Test { - def f1(x: Any) = x match { case y @ Cell(_) => y } // Inferred type is Cell[Any] - // def f2(x: Cell[_]) = x match { case y @ Cell(_) => y } // Inferred type is Cell[_] - // def f3[A](x: Cell[A]) = x match { case y @ Cell(_) => y } // Inferred type is Cell[A] - - def main(args: Array[String]): Unit = { - // val x = new Cell(1) - // val y = f1(x) - // y.x = "abc" - // println(x.x + 1) - } -} \ No newline at end of file diff --git a/test/pending/neg/t6680b.check b/test/pending/neg/t6680b.check deleted file mode 100644 index a16812d91d..0000000000 --- a/test/pending/neg/t6680b.check +++ /dev/null @@ -1,6 +0,0 @@ -t6680b.scala:8: error: type mismatch; - found : String("not what you\'d expect") - required: ?Hidden1 where type ?Hidden1 (this is a GADT skolem) - case Concrete(f) => f("not what you'd expect") - ^ -one error found diff --git a/test/pending/neg/t6680b.scala b/test/pending/neg/t6680b.scala deleted file mode 100644 index e9f6468315..0000000000 --- a/test/pending/neg/t6680b.scala +++ /dev/null @@ -1,10 +0,0 @@ -trait Super[+A] -// `Hidden` must occur in both variance positions (covariant/contravariant) for the sneakiness to work -// this way type inference will infer Any for `Hidden` and `A` in the pattern below -case class Concrete[Hidden, +A](havoc: Hidden => Hidden) extends Super[A] - -object Test extends App { - (Concrete((x: Int) => x): Super[Any]) match { - case Concrete(f) => f("not what you'd expect") - } -} \ No newline at end of file diff --git a/test/pending/neg/t6680c.scala b/test/pending/neg/t6680c.scala deleted file mode 100644 index f69663a71b..0000000000 --- a/test/pending/neg/t6680c.scala +++ /dev/null @@ -1,17 +0,0 @@ -package s - -trait Stream[+A] -case class Unfold[S,+A](s: S, f: S => Option[(A,S)]) extends Stream[A] - -object Stream { - def fromList[A](a: List[A]): Stream[A] = - Unfold(a, (l:List[A]) => l.headOption.map((_,l.tail))) -} - -object Test { - def main(args: Array[String]): Unit = { - val res = Stream.fromList(List(1,2,3,4)) - - res match { case Unfold(s, f) => f("a string!") } - } -} -- cgit v1.2.3