diff options
author | Miles Sabin <miles@milessabin.com> | 2016-05-20 12:49:25 +0100 |
---|---|---|
committer | Miles Sabin <miles@milessabin.com> | 2016-05-24 08:46:40 +0100 |
commit | 892a6d6878accb67e3fe68aefaa256396db05a90 (patch) | |
tree | 89024c06147fddf825904bc5891e1ee2cbf4c2d1 /test | |
parent | 207e32df30fd733e4dd1cb28fb8cb5c3153c21a6 (diff) | |
download | scala-892a6d6878accb67e3fe68aefaa256396db05a90.tar.gz scala-892a6d6878accb67e3fe68aefaa256396db05a90.tar.bz2 scala-892a6d6878accb67e3fe68aefaa256396db05a90.zip |
SI-2712 Add support for higher order unification
Diffstat (limited to 'test')
29 files changed, 466 insertions, 0 deletions
diff --git a/test/files/neg/t2712-1.check b/test/files/neg/t2712-1.check new file mode 100644 index 0000000000..61e4b6b149 --- /dev/null +++ b/test/files/neg/t2712-1.check @@ -0,0 +1,13 @@ +t2712-1.scala:7: error: no type parameters for method foo: (m: M[A])Unit exist so that it can be applied to arguments (test.Two[Int,String]) + --- because --- +argument expression's type is not compatible with formal parameter type; + found : test.Two[Int,String] + required: ?M[?A] + def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled* + ^ +t2712-1.scala:7: error: type mismatch; + found : test.Two[Int,String] + required: M[A] + def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled* + ^ +two errors found diff --git a/test/files/neg/t2712-1.scala b/test/files/neg/t2712-1.scala new file mode 100644 index 0000000000..f7967d71b6 --- /dev/null +++ b/test/files/neg/t2712-1.scala @@ -0,0 +1,8 @@ +package test + +trait Two[A, B] + +object Test { + def foo[M[_], A](m: M[A]) = () + def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled* +} diff --git a/test/files/neg/t2712-2.check b/test/files/neg/t2712-2.check new file mode 100644 index 0000000000..ea19e33e2c --- /dev/null +++ b/test/files/neg/t2712-2.check @@ -0,0 +1,13 @@ +t2712-2.scala:16: error: type mismatch; + found : test.Foo + required: test.Two[test.X1,Object] +Note: test.X2 <: Object (and test.Foo <: test.Two[test.X1,test.X2]), but trait Two is invariant in type B. +You may wish to define B as +B instead. (SLS 4.5) + test1(foo): One[X3] // fails with -Ypartial-unification enabled + ^ +t2712-2.scala:16: error: type mismatch; + found : test.Two[test.X1,Object] + required: test.One[test.X3] + test1(foo): One[X3] // fails with -Ypartial-unification enabled + ^ +two errors found diff --git a/test/files/neg/t2712-2.flags b/test/files/neg/t2712-2.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/neg/t2712-2.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/neg/t2712-2.scala b/test/files/neg/t2712-2.scala new file mode 100644 index 0000000000..85ed523489 --- /dev/null +++ b/test/files/neg/t2712-2.scala @@ -0,0 +1,18 @@ +package test + +class X1 +class X2 +class X3 + +trait One[A] +trait Two[A, B] + +class Foo extends Two[X1, X2] with One[X3] +object Test { + def test1[M[_], A](x: M[A]): M[A] = x + + val foo = new Foo + + test1(foo): One[X3] // fails with -Ypartial-unification enabled + test1(foo): Two[X1, X2] // fails without -Ypartial-unification +} diff --git a/test/files/neg/t2712-3.check b/test/files/neg/t2712-3.check new file mode 100644 index 0000000000..a84d96bf09 --- /dev/null +++ b/test/files/neg/t2712-3.check @@ -0,0 +1,6 @@ +t2712-3.scala:17: error: type mismatch; + found : test.One[test.X3] + required: test.Two[test.X1,test.X2] + test1(foo): Two[X1, X2] // fails without -Ypartial-unification + ^ +one error found diff --git a/test/files/neg/t2712-3.scala b/test/files/neg/t2712-3.scala new file mode 100644 index 0000000000..85ed523489 --- /dev/null +++ b/test/files/neg/t2712-3.scala @@ -0,0 +1,18 @@ +package test + +class X1 +class X2 +class X3 + +trait One[A] +trait Two[A, B] + +class Foo extends Two[X1, X2] with One[X3] +object Test { + def test1[M[_], A](x: M[A]): M[A] = x + + val foo = new Foo + + test1(foo): One[X3] // fails with -Ypartial-unification enabled + test1(foo): Two[X1, X2] // fails without -Ypartial-unification +} diff --git a/test/files/neg/t2712.flags b/test/files/neg/t2712.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/neg/t2712.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-1.flags b/test/files/pos/t2712-1.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/pos/t2712-1.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-1.scala b/test/files/pos/t2712-1.scala new file mode 100644 index 0000000000..4f84c9df5e --- /dev/null +++ b/test/files/pos/t2712-1.scala @@ -0,0 +1,9 @@ +package test + +// Original test case from, +// +// https://issues.scala-lang.org/browse/SI-2712 +object Test { + def meh[M[_], A](x: M[A]): M[A] = x + meh{(x: Int) => x} // solves ?M = [X] Int => X and ?A = Int ... +} diff --git a/test/files/pos/t2712-2.flags b/test/files/pos/t2712-2.flags new file mode 100644 index 0000000000..7d49efbb8e --- /dev/null +++ b/test/files/pos/t2712-2.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t2712-2.scala b/test/files/pos/t2712-2.scala new file mode 100644 index 0000000000..39f22dd92a --- /dev/null +++ b/test/files/pos/t2712-2.scala @@ -0,0 +1,25 @@ +package test + +// See: https://github.com/milessabin/si2712fix-demo/issues/3 +object Test { + trait A[T1, T2] { } + trait B[T1, T2] { } + class C[T] extends A[T, Long] with B[T, Double] + class CB extends A[Boolean, Long] with B[Boolean, Double] + + trait A2[T] + trait B2[T] + class C2[T] extends A2[T] with B2[T] + class CB2 extends A2[Boolean] with B2[Boolean] + + def meh[M[_], A](x: M[A]): M[A] = x + + val m0 = meh(new C[Boolean]) + m0: C[Boolean] + val m1 = meh(new CB) + m1: A[Boolean, Long] + val m2 = meh(new C2[Boolean]) + m2: C2[Boolean] + val m3 = meh(new CB2) + m3: A2[Boolean] +} diff --git a/test/files/pos/t2712-3.flags b/test/files/pos/t2712-3.flags new file mode 100644 index 0000000000..7d49efbb8e --- /dev/null +++ b/test/files/pos/t2712-3.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t2712-3.scala b/test/files/pos/t2712-3.scala new file mode 100644 index 0000000000..46445f9289 --- /dev/null +++ b/test/files/pos/t2712-3.scala @@ -0,0 +1,24 @@ +package test + +object Test1 { + class Foo[T, F[_]] + def meh[M[_[_]], F[_]](x: M[F]): M[F] = x + meh(new Foo[Int, List]) // solves ?M = [X[_]]Foo[Int, X[_]] ?A = List ... +} + +object Test2 { + trait TC[T] + class Foo[F[_], G[_]] + def meh[G[_[_]]](g: G[TC]) = ??? + meh(new Foo[TC, TC]) // solves ?G = [X[_]]Foo[TC, X] +} + +object Test3 { + trait TC[F[_]] + trait TC2[F[_]] + class Foo[F[_[_]], G[_[_]]] + new Foo[TC, TC2] + + def meh[G[_[_[_]]]](g: G[TC2]) = ??? + meh(new Foo[TC, TC2]) // solves ?G = [X[_[_]]]Foo[TC, X] +} diff --git a/test/files/pos/t2712-4.flags b/test/files/pos/t2712-4.flags new file mode 100644 index 0000000000..7d49efbb8e --- /dev/null +++ b/test/files/pos/t2712-4.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t2712-4.scala b/test/files/pos/t2712-4.scala new file mode 100644 index 0000000000..3e2e5cddae --- /dev/null +++ b/test/files/pos/t2712-4.scala @@ -0,0 +1,17 @@ +package test + +object Test1 { + trait X + trait Y extends X + class Foo[T, U <: X] + def meh[M[_ <: A], A](x: M[A]): M[A] = x + meh(new Foo[Int, Y]) +} + +object Test2 { + trait X + trait Y extends X + class Foo[T, U >: Y] + def meh[M[_ >: A], A](x: M[A]): M[A] = x + meh(new Foo[Int, X]) +} diff --git a/test/files/pos/t2712-5.flags b/test/files/pos/t2712-5.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/pos/t2712-5.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-5.scala b/test/files/pos/t2712-5.scala new file mode 100644 index 0000000000..ed96d4c06f --- /dev/null +++ b/test/files/pos/t2712-5.scala @@ -0,0 +1,29 @@ +package test + +import scala.language.higherKinds + +trait Functor[F[_]] { + def map[A, B](f: A => B, fa: F[A]): F[B] +} + +object Functor { + implicit def function[A]: Functor[({ type l[B] = A => B })#l] = + new Functor[({ type l[B] = A => B })#l] { + def map[C, B](cb: C => B, ac: A => C): A => B = cb compose ac + } +} + +object FunctorSyntax { + implicit class FunctorOps[F[_], A](fa: F[A])(implicit F: Functor[F]) { + def map[B](f: A => B): F[B] = F.map(f, fa) + } +} + +object Test { + + val f: Int => String = _.toString + + import FunctorSyntax._ + + f.map((s: String) => s.reverse) +} diff --git a/test/files/pos/t2712-6.flags b/test/files/pos/t2712-6.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/pos/t2712-6.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-6.scala b/test/files/pos/t2712-6.scala new file mode 100644 index 0000000000..eefe769ad6 --- /dev/null +++ b/test/files/pos/t2712-6.scala @@ -0,0 +1,12 @@ +package test + +object Tags { + type Tagged[A, T] = {type Tag = T; type Self = A} + + type @@[T, Tag] = Tagged[T, Tag] + + trait Disjunction + + def meh[M[_], A](ma: M[A]): M[A] = ma + meh(null.asInstanceOf[Int @@ Disjunction]) +} diff --git a/test/files/pos/t2712-7.flags b/test/files/pos/t2712-7.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/pos/t2712-7.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-7.scala b/test/files/pos/t2712-7.scala new file mode 100644 index 0000000000..d9c5243f13 --- /dev/null +++ b/test/files/pos/t2712-7.scala @@ -0,0 +1,15 @@ +package test + +// Cats Xor, Scalaz \/, scala.util.Either +sealed abstract class Xor[+A, +B] extends Product with Serializable +object Xor { + final case class Left[+A](a: A) extends (A Xor Nothing) + final case class Right[+B](b: B) extends (Nothing Xor B) +} + +object TestXor { + import Xor._ + def meh[F[_], A, B](fa: F[A])(f: A => B): F[B] = ??? + meh(new Right(23): Xor[Boolean, Int])(_ < 13) + meh(new Left(true): Xor[Boolean, Int])(_ < 13) +} diff --git a/test/files/pos/t5683.flags b/test/files/pos/t5683.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/pos/t5683.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t5683.scala b/test/files/pos/t5683.scala new file mode 100644 index 0000000000..05ab035792 --- /dev/null +++ b/test/files/pos/t5683.scala @@ -0,0 +1,23 @@ +object Test { + trait NT[X] + trait W[W, A] extends NT[Int] + type StringW[T] = W[String, T] + trait K[M[_], A, B] + + def k[M[_], B](f: Int => M[B]): K[M, Int, B] = null + + val okay1: K[StringW,Int,Int] = k{ (y: Int) => null: StringW[Int] } + val okay2 = k[StringW,Int]{ (y: Int) => null: W[String, Int] } + + val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] } + + // remove `extends NT[Int]`, and the last line gives an inference error + // rather than a crash. + // test/files/pos/t5683.scala:12: error: no type parameters for method k: (f: Int => M[B])Test.K[M,Int,B] exist so that it can be applied to arguments (Int => Test.W[String,Int]) + // --- because --- + // argument expression's type is not compatible with formal parameter type; + // found : Int => Test.W[String,Int] + // required: Int => ?M[?B] + // val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] } + // ^ +} diff --git a/test/files/pos/t6895b.flags b/test/files/pos/t6895b.flags new file mode 100644 index 0000000000..7d49efbb8e --- /dev/null +++ b/test/files/pos/t6895b.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t6895b.scala b/test/files/pos/t6895b.scala new file mode 100644 index 0000000000..c465065011 --- /dev/null +++ b/test/files/pos/t6895b.scala @@ -0,0 +1,39 @@ +trait Foo[F[_]] +trait Bar[F[_], A] + +trait Or[A, B] + +class Test { + implicit def orFoo[A]: Foo[({type L[X] = Or[A, X]})#L] = ??? + implicit def barFoo[F[_]](implicit f: Foo[F]): Foo[({type L[X] = Bar[F, X]})#L] = ??? + + // Now we can define a couple of type aliases: + type StringOr[X] = Or[String, X] + type BarStringOr[X] = Bar[StringOr, X] + + // ok + implicitly[Foo[BarStringOr]] + barFoo[StringOr](null) : Foo[BarStringOr] + barFoo(null) : Foo[BarStringOr] + + // nok + implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]] + // Let's write the application explicitly, and then + // compile with just this line enabled and -explaintypes. + barFoo(null) : Foo[({type L[X] = Bar[StringOr, X]})#L] + + // Foo[[X]Bar[F,X]] <: Foo[[X]Bar[[X]Or[String,X],X]]? + // Bar[[X]Or[String,X],X] <: Bar[F,X]? + // F[_] <: Or[String,_]? + // false + // false + // false + + // Note that the type annotation above is typechecked as + // Foo[[X]Bar[[X]Or[String,X],X]], ie the type alias `L` + // is eta expanded. + // + // This is done so that it does not escape its defining scope. + // However, one this is done, higher kinded inference + // no longer is able to unify F with `StringOr` (SI-2712) +} diff --git a/test/files/run/inferred-type-constructors-hou.check b/test/files/run/inferred-type-constructors-hou.check new file mode 100644 index 0000000000..6b09823341 --- /dev/null +++ b/test/files/run/inferred-type-constructors-hou.check @@ -0,0 +1,56 @@ +warning: there were two feature warnings; re-run with -feature for details + p.Iterable[Int] + p.Set[Int] + p.Seq[Int] + p.m.Set[Int] + p.m.Seq[Int] + private[m] p.m.ASet[Int] + p.i.Seq[Int] + private[i] p.i.ASet[Int] + private[i] p.i.ASeq[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.m.Set[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + private[p] p.ASet[Int] + private[p] p.AIterable[Int] + p.Iterable[Int] + p.i.Seq[Int] + private[p] p.AIterable[Int] + List[Nothing] + scala.collection.immutable.Vector[Nothing] + scala.collection.immutable.Map[Int,Int] + scala.collection.immutable.Set[Int] + Seq[Int] + Array[Int] + scala.collection.AbstractSet[Int] + Comparable[java.lang.String] + scala.collection.immutable.LinearSeq[Int] + Iterable[Int] diff --git a/test/files/run/inferred-type-constructors-hou.flags b/test/files/run/inferred-type-constructors-hou.flags new file mode 100644 index 0000000000..41565c7e32 --- /dev/null +++ b/test/files/run/inferred-type-constructors-hou.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/run/inferred-type-constructors-hou.scala b/test/files/run/inferred-type-constructors-hou.scala new file mode 100644 index 0000000000..79a8653f68 --- /dev/null +++ b/test/files/run/inferred-type-constructors-hou.scala @@ -0,0 +1,125 @@ +package p { + trait TCon[+CC[X]] { + def fPublic: CC[Int] = ??? + private[p] def fPackagePrivate: CC[Int] = ??? + protected[p] def fPackageProtected: CC[Int] = ??? + } + trait Iterable[+A] extends TCon[Iterable] + trait Set[A] extends Iterable[A] with TCon[Set] + trait Seq[+A] extends Iterable[A] with TCon[Seq] + + private[p] abstract class AIterable[+A] extends Iterable[A] + private[p] abstract class ASeq[+A] extends AIterable[A] with Seq[A] + private[p] abstract class ASet[A] extends AIterable[A] with Set[A] + + package m { + private[m] abstract class ASeq[A] extends p.ASeq[A] with Seq[A] + private[m] abstract class ASet[A] extends p.ASet[A] with Set[A] + trait Set[A] extends p.Set[A] with TCon[Set] + trait Seq[A] extends p.Seq[A] with TCon[Seq] + trait BitSet extends ASet[Int] + trait IntSeq extends ASeq[Int] + } + + package i { + private[i] abstract class ASeq[+A] extends p.ASeq[A] with Seq[A] + private[i] abstract class ASet[A] extends p.ASet[A] with Set[A] + trait Set[A] extends p.Set[A] with TCon[Set] + trait Seq[+A] extends p.Seq[A] with TCon[Seq] + trait BitSet extends ASet[Int] + trait IntSeq extends ASeq[Int] + } +} + +object Test { + import scala.reflect.runtime.universe._ + // Complicated by the absence of usable type constructor type tags. + def extract[A, CC[X]](xs: CC[A]): CC[A] = xs + def whatis[T: TypeTag](x: T): Unit = { + val tpe = typeOf[T] + val access = tpe.typeSymbol.asInstanceOf[scala.reflect.internal.HasFlags].accessString.replaceAllLiterally("package ", "") + println(f"$access%15s $tpe") + } + + trait IntIterable extends p.Iterable[Int] + trait IntSet extends p.Set[Int] + trait IntSeq extends p.Seq[Int] + + trait MutableIntSet extends p.m.Set[Int] + trait MutableIntSeq extends p.m.Seq[Int] + + trait ImmutableIntSet extends p.i.Set[Int] + trait ImmutableIntSeq extends p.i.Seq[Int] + + def f1: IntIterable = null + def f2: IntSet = null + def f3: IntSeq = null + + def g1: MutableIntSet = null + def g2: MutableIntSeq = null + def g3: p.m.BitSet = null + + def h1: ImmutableIntSeq = null + def h2: p.i.BitSet = null + def h3: p.i.IntSeq = null + + def main(args: Array[String]): Unit = { + whatis(extract(f1)) + whatis(extract(f2)) + whatis(extract(f3)) + whatis(extract(g1)) + whatis(extract(g2)) + whatis(extract(g3)) + whatis(extract(h1)) + whatis(extract(h2)) + whatis(extract(h3)) + + whatis(extract(if (true) f1 else f2)) + whatis(extract(if (true) f1 else f3)) + whatis(extract(if (true) f1 else g1)) + whatis(extract(if (true) f1 else g2)) + whatis(extract(if (true) f1 else g3)) + whatis(extract(if (true) f1 else h1)) + whatis(extract(if (true) f1 else h2)) + whatis(extract(if (true) f1 else h3)) + whatis(extract(if (true) f2 else f3)) + whatis(extract(if (true) f2 else g1)) + whatis(extract(if (true) f2 else g2)) + whatis(extract(if (true) f2 else g3)) + whatis(extract(if (true) f2 else h1)) + whatis(extract(if (true) f2 else h2)) + whatis(extract(if (true) f2 else h3)) + whatis(extract(if (true) f3 else g1)) + whatis(extract(if (true) f3 else g2)) + whatis(extract(if (true) f3 else g3)) + whatis(extract(if (true) f3 else h1)) + whatis(extract(if (true) f3 else h2)) + whatis(extract(if (true) f3 else h3)) + whatis(extract(if (true) g1 else g2)) + whatis(extract(if (true) g1 else g3)) + whatis(extract(if (true) g1 else h1)) + whatis(extract(if (true) g1 else h2)) + whatis(extract(if (true) g1 else h3)) + whatis(extract(if (true) g2 else g3)) + whatis(extract(if (true) g2 else h1)) + whatis(extract(if (true) g2 else h2)) + whatis(extract(if (true) g2 else h3)) + whatis(extract(if (true) g3 else h1)) + whatis(extract(if (true) g3 else h2)) + whatis(extract(if (true) g3 else h3)) + whatis(extract(if (true) h1 else h2)) + whatis(extract(if (true) h1 else h3)) + whatis(extract(if (true) h2 else h3)) + + whatis(extract(Nil)) + whatis(extract(Vector())) + whatis(extract(Map[Int,Int]())) + whatis(extract(Set[Int]())) + whatis(extract(Seq[Int]())) + whatis(extract(Array[Int]())) + whatis(extract(scala.collection.immutable.BitSet(1))) + whatis(extract("abc")) + whatis(extract(if (true) Stream(1) else List(1))) + whatis(extract(if (true) Seq(1) else Set(1))) + } +} |