summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-08-29 13:36:15 +1000
committerGitHub <noreply@github.com>2016-08-29 13:36:15 +1000
commit90bced5b659e174b01a44999ef7ce4b810c73c4a (patch)
tree011dea592e85b973f87f00bc0fe5d4003911bcba /test
parent18b75748dfb3e790b4c4be67155e2f1682fc85e2 (diff)
parente9e8618070d17ab167249d8197cb9c6e72891ad2 (diff)
downloadscala-90bced5b659e174b01a44999ef7ce4b810c73c4a.tar.gz
scala-90bced5b659e174b01a44999ef7ce4b810c73c4a.tar.bz2
scala-90bced5b659e174b01a44999ef7ce4b810c73c4a.zip
Merge pull request #5263 from retronym/review/5041
SI-5294 SI-6161 Hard graft in asSeenFrom, refinements, and existentials [ci: last-only]
Diffstat (limited to 'test')
-rw-r--r--test/files/neg/lub-from-hell-2.check7
-rw-r--r--test/files/neg/lub-from-hell-2.scala13
-rw-r--r--test/files/pos/lub-from-hell.scala6
-rw-r--r--test/files/pos/t5294b.scala36
-rw-r--r--test/files/pos/t5294c.scala30
-rw-r--r--test/files/pos/t6161b.scala (renamed from test/pending/pos/t6161.scala)0
-rw-r--r--test/files/pos/typevar-in-prefix.scala9
-rw-r--r--test/files/presentation/callcc-interpreter/Runner.scala5
-rw-r--r--test/files/run/t5294.scala22
-rw-r--r--test/files/run/t7747-repl.scala4
-rw-r--r--test/junit/scala/reflect/internal/TypesTest.scala81
11 files changed, 206 insertions, 7 deletions
diff --git a/test/files/neg/lub-from-hell-2.check b/test/files/neg/lub-from-hell-2.check
new file mode 100644
index 0000000000..3ef935f93b
--- /dev/null
+++ b/test/files/neg/lub-from-hell-2.check
@@ -0,0 +1,7 @@
+lub-from-hell-2.scala:3: error: type arguments [Any,Iterable[Any] with Int => Any with scala.collection.generic.Subtractable[Any,Iterable[Any] with Int => Any with scala.collection.generic.Subtractable[Any,Iterable[Any] with Int => Any]{def seq: Iterable[Any] with Int => Any}]{def seq: Iterable[Any] with Int => Any{def seq: Iterable[Any] with Int => Any}}] do not conform to trait Subtractable's type parameter bounds [A,+Repr <: scala.collection.generic.Subtractable[A,Repr]]
+ def foo(a: Boolean, b: collection.mutable.Set[Any], c: collection.mutable.ListBuffer[Any]) = if (a) b else c
+ ^
+lub-from-hell-2.scala:4: error: type arguments [Any,scala.collection.mutable.Iterable[Any] with scala.collection.mutable.Cloneable[scala.collection.mutable.Iterable[Any] with scala.collection.mutable.Cloneable[scala.collection.mutable.Iterable[Any] with Cloneable with Int => Any] with Int => Any{def seq: scala.collection.mutable.Iterable[Any] with Cloneable with Int => Any}] with scala.collection.generic.Growable[Any] with Int => Any with scala.collection.generic.Shrinkable[Any] with scala.collection.generic.Subtractable[Any,Iterable[Any] with Int => Any with scala.collection.generic.Subtractable[Any,Iterable[Any] with Int => Any]{def seq: Iterable[Any] with Int => Any}] with scala.collection.script.Scriptable[Any]] do not conform to trait Subtractable's type parameter bounds [A,+Repr <: scala.collection.generic.Subtractable[A,Repr]]
+ def bar(a: Boolean, b: scala.collection.mutable.SetLike[Any,scala.collection.mutable.Set[Any]], c: scala.collection.mutable.Buffer[Any]) = if (a) b else c
+ ^
+two errors found
diff --git a/test/files/neg/lub-from-hell-2.scala b/test/files/neg/lub-from-hell-2.scala
new file mode 100644
index 0000000000..18c99dfada
--- /dev/null
+++ b/test/files/neg/lub-from-hell-2.scala
@@ -0,0 +1,13 @@
+class Test {
+ trait Tree
+ def foo(a: Boolean, b: collection.mutable.Set[Any], c: collection.mutable.ListBuffer[Any]) = if (a) b else c
+ def bar(a: Boolean, b: scala.collection.mutable.SetLike[Any,scala.collection.mutable.Set[Any]], c: scala.collection.mutable.Buffer[Any]) = if (a) b else c
+ // bar produces an ill-bounded LUB in 2.11.8. After this commit, which fixes a bug in existential+refinement lubs, foo also fails.
+}
+// This test case minimizes a case that stated to fail compile after my fixes in SI-5294.
+// `foo` used to compile for the wrong reason, `mergePrefixAndArgs` failed to transpose a
+// ragged matrix and skipped to the next level of the base type sequences to find a common type symbol.
+//
+// My changes fixed the root cause of the ragged matrix, which uncovered the latent bug.
+// For comparison, `bar` failed to compile before _and_ after my changes for the same reason:
+// f-bounded types involved in LUBs can sometimes produce an ill-bounded LUB.
diff --git a/test/files/pos/lub-from-hell.scala b/test/files/pos/lub-from-hell.scala
new file mode 100644
index 0000000000..cb4b1733c7
--- /dev/null
+++ b/test/files/pos/lub-from-hell.scala
@@ -0,0 +1,6 @@
+class Test {
+ trait Tree
+ def foo(b: Boolean, buf: collection.mutable.ArrayBuffer[Any], acc: StringBuilder) = if (b) buf else acc
+}
+// This test case minimizes a case that failed to compile due to a bug in my work on
+// SI-5294. After refining my patches, it compiles again, as expected. \ No newline at end of file
diff --git a/test/files/pos/t5294b.scala b/test/files/pos/t5294b.scala
new file mode 100644
index 0000000000..038d2ff806
--- /dev/null
+++ b/test/files/pos/t5294b.scala
@@ -0,0 +1,36 @@
+class Test {
+ def test = {
+
+ val l1 = null: Int #: String #: Boolean #: String #: HNil.type
+
+ type _2 = Succ[Succ[Zero.type]]
+
+ val t1: Boolean = null.asInstanceOf[ l1.type#Drop[_2]#Head ]
+
+ val t2: Boolean = null.asInstanceOf[ l1.type#Apply[_2] ]
+ }
+}
+
+
+sealed trait Nat {
+ type Fold[U, F[_ <: U] <: U, Z <: U] <: U
+}
+
+final object Zero extends Nat {
+ type Fold[U, F[_ <: U] <: U, Z <: U] = Z
+}
+
+final class Succ[N <: Nat] extends Nat {
+ type Fold[U, F[_ <: U] <: U, Z <: U] = F[N#Fold[U, F, Z]]
+}
+
+trait HList {
+ type Head
+ type Tail <: HList
+ type Drop[N <: Nat] = N#Fold[HList, ({ type L[X <: HList] = X#Tail })#L, this.type]
+ type Apply[N <: Nat] = Drop[N]#Head
+}
+
+class #: [H, T <: HList] extends HList { type Head = H; type Tail = T }
+
+object HNil extends HList { type Head = Nothing; type Tail = Nothing }
diff --git a/test/files/pos/t5294c.scala b/test/files/pos/t5294c.scala
new file mode 100644
index 0000000000..2709098988
--- /dev/null
+++ b/test/files/pos/t5294c.scala
@@ -0,0 +1,30 @@
+sealed trait Nat {
+ type IsZero[U, A <: U, B <: U] <: U
+}
+
+final object Zero extends Nat {
+ type IsZero[U, T <: U, F <: U] = T
+}
+
+final class Succ[N <: Nat] extends Nat {
+ type IsZero[U, T <: U, F <: U] = F
+}
+
+trait HList {
+ type Head
+ type Tail <: HList
+ type Drop[N <: Nat] = N#IsZero[HList, this.type, Tail]
+ type Apply[N <: Nat] = Drop[N]#Head // typechecks as HList.this.Head
+}
+
+object Test {
+ type ::[H, T <: HList] = HList { type Head = H; type Tail = T}
+ type HNil <: HList
+ type T = Int :: String :: HNil
+
+ type U = T#Drop[Succ[Zero.type]]#Head
+ type V = T#Apply[Succ[Zero.type]]
+ var u: U = ???
+ var v: V = ???
+ u = v
+}
diff --git a/test/pending/pos/t6161.scala b/test/files/pos/t6161b.scala
index 5783cc85f2..5783cc85f2 100644
--- a/test/pending/pos/t6161.scala
+++ b/test/files/pos/t6161b.scala
diff --git a/test/files/pos/typevar-in-prefix.scala b/test/files/pos/typevar-in-prefix.scala
new file mode 100644
index 0000000000..929648b789
--- /dev/null
+++ b/test/files/pos/typevar-in-prefix.scala
@@ -0,0 +1,9 @@
+trait Test1 {
+ abstract class Setting
+ def Bool: Setting
+
+ class C[T <: Setting](val s: T)
+ val setting1 = null.asInstanceOf[_1.s.type forSome { val _1: C[Setting] }]
+ // the derived accessor for this val was not using an inferred type, as was
+ // the intention of the implementation in MethodSynthesis.
+}
diff --git a/test/files/presentation/callcc-interpreter/Runner.scala b/test/files/presentation/callcc-interpreter/Runner.scala
index a5698be5c2..1c03e3d5ba 100644
--- a/test/files/presentation/callcc-interpreter/Runner.scala
+++ b/test/files/presentation/callcc-interpreter/Runner.scala
@@ -1,6 +1,3 @@
import scala.tools.nsc.interactive.tests._
-object Test extends InteractiveTest {
- // Normalize ordering of LUB
- override def normalize(s: String) = s.replace("Serializable with Product", "Product with Serializable")
-}
+object Test extends InteractiveTest
diff --git a/test/files/run/t5294.scala b/test/files/run/t5294.scala
new file mode 100644
index 0000000000..2551ae89a6
--- /dev/null
+++ b/test/files/run/t5294.scala
@@ -0,0 +1,22 @@
+import scala.language.higherKinds
+
+package p {
+ trait T[+A, +CC] {
+ def t: CC
+ }
+ class C {
+ def test[CC[X] <: T[X,String] with T[X,Int]](from: CC[_]): Unit = ()
+ }
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val symtab = reflect.runtime.universe.asInstanceOf[reflect.internal.SymbolTable]
+ val CTpe = reflect.runtime.universe.typeOf[p.C].asInstanceOf[symtab.Type]
+ val TClass = reflect.runtime.universe.symbolOf[p.T[_, _]].asInstanceOf[symtab.Symbol]
+ import symtab._
+ val from = CTpe.member(TermName("test")).paramss.head.head
+ assert(from.baseClasses contains TClass)
+ assert(from.info.baseTypeIndex(TClass) != -1) // was failing!
+ }
+}
diff --git a/test/files/run/t7747-repl.scala b/test/files/run/t7747-repl.scala
index 0094d3ba98..8203f4c802 100644
--- a/test/files/run/t7747-repl.scala
+++ b/test/files/run/t7747-repl.scala
@@ -10,9 +10,7 @@ object Test extends ReplTest {
override def normalize(s: String) = {
// replace indylambda function names by <function0>
- val s2 = """\$Lambda.*""".r.replaceAllIn(s, "<function0>")
- // Normalize ordering of LUB
- s2.replace("Serializable with Product", "Product with Serializable")
+ """\$Lambda.*""".r.replaceAllIn(s, "<function0>")
}
def code = """
diff --git a/test/junit/scala/reflect/internal/TypesTest.scala b/test/junit/scala/reflect/internal/TypesTest.scala
index 05a77cfb47..585493280b 100644
--- a/test/junit/scala/reflect/internal/TypesTest.scala
+++ b/test/junit/scala/reflect/internal/TypesTest.scala
@@ -58,4 +58,85 @@ class TypesTest {
Assert.fail(xs.mkString("\n"))
}
}
+
+ @Test
+ def testRefinementContains(): Unit = {
+ val refinement = typeOf[{def foo: Int}]
+ assert(refinement.isInstanceOf[RefinedType])
+ assert(refinement.contains(IntClass))
+ val elem0 = refinement.baseTypeSeq(0)
+ assert(elem0.isInstanceOf[RefinementTypeRef])
+ assert(elem0.contains(IntClass))
+ }
+
+ @Test
+ def testRefinedLubs(): Unit = {
+ // https://github.com/scala/scala-dev/issues/168
+ assertEquals(typeOf[Option[AnyVal]], lub(typeOf[Option[Int] with Option[Char]] :: typeOf[Option[Boolean] with Option[Short]] :: Nil))
+ assertEquals(typeOf[Option[AnyVal]], lub(typeOf[Option[Int] with Option[Char]] :: typeOf[Option[Boolean]] :: Nil))
+ assertEquals(typeOf[Option[AnyVal]], lub((typeOf[Option[Int] with Option[Char]] :: typeOf[Option[Boolean] with Option[Short]] :: Nil).reverse))
+ assertEquals(typeOf[Option[AnyVal]], lub((typeOf[Option[Int] with Option[Char]] :: typeOf[Option[Boolean]] :: Nil).reverse))
+ }
+
+ @Test
+ def testExistentialRefinement(): Unit = {
+ import rootMirror.EmptyPackageClass
+
+ // class M[A]
+ val MClass = EmptyPackageClass.newClass("M")
+ val A = MClass.newTypeParameter("A").setInfo(TypeBounds.empty)
+ MClass.setInfo(PolyType(A :: Nil, ClassInfoType(ObjectClass.tpeHK :: Nil, newScopeWith(), MClass)))
+
+ // (M[Int] with M[X] { def m: Any }) forSome { type X }
+ val X = NoSymbol.newExistential("X").setInfo(TypeBounds.empty)
+ val T: Type = {
+ val decls = newScopeWith(MClass.newMethod("m").setInfo(NullaryMethodType(AnyClass.tpeHK)))
+ val refined = refinedType(appliedType(MClass, IntClass.tpeHK) :: appliedType(MClass, X.tpeHK) :: Nil, NoSymbol, decls, NoPosition)
+ newExistentialType(X :: Nil, refined)
+ }
+
+ val RefinementClass = T.underlying.typeSymbol
+ assertTrue(RefinementClass.isRefinementClass)
+ TypeRef(NoPrefix, RefinementClass, Nil) match {
+ case rtr : RefinementTypeRef =>
+ // ContainsCollector needs to look inside the info of symbols of RefinementTypeRefs
+ assert(rtr.contains(X))
+ }
+
+ val underlying = T.underlying
+ val baseTypeSeqIndices = T.baseTypeSeq.toList.indices
+ for (i <- baseTypeSeqIndices) {
+ // Elements of the existential type should have the same type symbol as underlying
+ assertEquals(T.baseTypeSeq.typeSymbol(i), underlying.baseTypeSeq.typeSymbol(i))
+ }
+
+ // Type symbols should be distinct
+ def checkDistinctTypeSyms(bts: BaseTypeSeq): Unit = {
+ val syms = baseTypeSeqIndices.map(T.baseTypeSeq.typeSymbol)
+ assertEquals(syms, syms.distinct)
+ }
+ checkDistinctTypeSyms(T.baseTypeSeq)
+ checkDistinctTypeSyms(T.underlying.baseTypeSeq)
+
+ // This is the entry for the refinement class
+ assertTrue(T.baseTypeSeq.typeSymbol(0).isRefinementClass)
+ assertEquals("M[Int] with M[X]{def m: Any} forSome { type X }", T.baseTypeSeq.rawElem(0).toString)
+
+ // This is the entry for M. The raw entry is an existential over a RefinedType which encodes a lazily computed base type
+ assertEquals(T.baseTypeSeq.typeSymbol(1), MClass)
+ assertEquals("M[X] with M[Int] forSome { type X }", T.baseTypeSeq.rawElem(1).toString)
+ // calling `apply` merges the prefix/args of the elements ot the RefinedType and rewraps in the existential
+ assertEquals("M[_1] forSome { type X; type _1 >: X with Int }", T.baseTypeSeq.apply(1).toString)
+ }
+
+ @Test
+ def testExistentialMerge(): Unit = {
+ val ts = typeOf[Set[Any]] :: typeOf[Set[X] forSome { type X <: Y; type Y <: Int}] :: Nil
+ def merge(ts: List[Type]) = mergePrefixAndArgs(ts, Variance.Contravariant, lubDepth(ts))
+ val merged1 = merge(ts)
+ val merged2 = merge(ts.reverse)
+ assert(ts.forall(_ <:< merged1)) // use to fail before fix to mergePrefixAndArgs for existentials
+ assert(ts.forall(_ <:< merged2))
+ assert(merged1 =:= merged2)
+ }
}