diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-10 16:16:37 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-12 17:49:48 -0800 |
commit | d5a1ea61871ad695c67a2165d0e569f304e63662 (patch) | |
tree | 4e3af4441ef920bd697b4faa4511486018e9de4d /test/files/pos/t7753.scala | |
parent | 9c4a6e3ed7624892f46948c1c0fb57d7d5b3346e (diff) | |
download | scala-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/t7753.scala')
-rw-r--r-- | test/files/pos/t7753.scala | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/test/files/pos/t7753.scala b/test/files/pos/t7753.scala new file mode 100644 index 0000000000..93ad23f114 --- /dev/null +++ b/test/files/pos/t7753.scala @@ -0,0 +1,36 @@ +import scala.language.{ higherKinds, implicitConversions } + +trait Foo { type Out } + +trait SI { + val instance: Foo + type Out +} + +object Test { + def test { + def indirect(si: SI)(v: si.instance.Out) = v + + val foo: Foo { type Out = Int } = ??? + def conv(i: Foo): SI { type Out = i.Out; val instance: i.type } = ??? + + val converted = conv(foo) + + val v1: Int = indirect(converted)(23) // Okay (after refining the return type `instance` in the return type of `conv`) + /* + indirect(converted){(v: converted.instance.Out)converted.instance.Out}( + 23{Int(23)} + ){converted.instance.Out}; + */ + + val v2: Int = indirect(conv(foo))(23) // Used to fail as follows: + /* + indirect( + conv(foo){si.SI{type Out = foo.Out; val instance: si.Test.<refinement>.type}} + ){(v: si.instance.Out)si.instance.Out}( + 23{<error>} + ){<error>}; + */ + + } +} |