summaryrefslogtreecommitdiff
path: root/test/files/pos/t8223.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2014-02-10 16:16:37 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2014-02-12 17:49:48 -0800
commitd5a1ea61871ad695c67a2165d0e569f304e63662 (patch)
tree4e3af4441ef920bd697b4faa4511486018e9de4d /test/files/pos/t8223.scala
parent9c4a6e3ed7624892f46948c1c0fb57d7d5b3346e (diff)
downloadscala-d5a1ea61871ad695c67a2165d0e569f304e63662.tar.gz
scala-d5a1ea61871ad695c67a2165d0e569f304e63662.tar.bz2
scala-d5a1ea61871ad695c67a2165d0e569f304e63662.zip
SI-7753 InstantiateDependentMap narrows type of unstable args
[Most of this comment and the initial fix were implemented by Jason Zaugg. I just cleaned it up a bit.] After a soundness fix in SI-3873, instantiation of dependent method type results behaved differently depending on whether the argument from which we were propagating information had a stable type or not. This is particular to substitution into singleton types over the parameter in question. If the argument was stable, it was substituted into singleton types, such as the one below in the prefix in `a.type#B` (which is the longhand version of `a.B`) scala> class A { type B >: Null <: AnyRef } defined class A scala> object AA extends A { type B = String } defined object AA scala> def foo(a: A): a.B = null foo: (a: A)a.B scala> foo(AA) res0: AA.B = null But what if it isn't stable? scala> foo({def a = AA; a: A { type B <: String}}) res1: a.B = null This commit changes that to: scala> foo({def a = AA; a: A { type B <: String}}) res1: A{type B <: String}#B = null
Diffstat (limited to 'test/files/pos/t8223.scala')
-rw-r--r--test/files/pos/t8223.scala29
1 files changed, 29 insertions, 0 deletions
diff --git a/test/files/pos/t8223.scala b/test/files/pos/t8223.scala
new file mode 100644
index 0000000000..52d6b0098e
--- /dev/null
+++ b/test/files/pos/t8223.scala
@@ -0,0 +1,29 @@
+package p {
+ class ViewEnv[AIn] {
+ type A = AIn
+ class SubView { def has(x: A): Boolean = ??? }
+ def get: SubView = new SubView
+ }
+
+ trait HasA { type A }
+ trait Indexable[R] extends HasA
+ class ArrayTC[AIn] extends Indexable[Array[AIn]] { type A = AIn }
+}
+
+package object p {
+ implicit def arrayTypeClass[A] : ArrayTC[A] = new ArrayTC[A]
+ object intArrayTC extends ArrayTC[Int]
+
+ type EnvAlias[W <: HasA] = ViewEnv[W#A]
+ type SubAlias[W <: HasA] = ViewEnv[W#A]#SubView
+
+ def f0[R](xs: R)(implicit tc: Indexable[R]): ViewEnv[tc.A]#SubView = new ViewEnv[tc.A]() get
+ def f1[R](xs: R)(implicit tc: Indexable[R]): EnvAlias[tc.type]#SubView = new ViewEnv[tc.A]() get
+ def f2[R](xs: R)(implicit tc: Indexable[R]): SubAlias[tc.type] = new ViewEnv[tc.A]() get
+
+ def g0 = f0(Array(1)) has 2 // ok
+ def g1 = f1(Array(1)) has 2 // ok
+ def g2 = f2(Array(1)) has 2 // "found: Int(2), required: tc.A"
+ def g3 = f2(Array(1))(new ArrayTC[Int]) has 2 // "found: Int(2), required: tc.A"
+ def g4 = f2(Array(1))(intArrayTC) has 2 // ok
+}