From 33fc68171105bb8d884219381c220076c5651316 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 13 Feb 2014 12:28:06 -0800 Subject: SI-8177 specializeSym must use memberInfo on high side When determining whether member `symLo` of `tpLo` has a stronger type than member `symHi` of `tpHi`, should we use memberType or memberInfo? Well, memberType transforms (using `asSeenFrom`) `sym.tpe`, whereas memberInfo performs the same transform on `sym.info`. For term symbols, this ends up being the same thing (`sym.tpe == sym.info`). For type symbols, however, the `.info` of an abstract type member is defined by its bounds, whereas its `.tpe` is a `TypeRef` to that type symbol, so that `sym.tpe <:< sym.info`, but not the other way around. Thus, for the strongest (correct) result, we should use `memberType` on the low side. On the high side, we should use the result appropriate for the right side of the `<:<` above (`memberInfo`). I also optimized the method a little bit by avoiding calling memberType if the symbol on the high side isn't eligble (e.g., it's a class). PS: I had to add a workaround to reifyType, because we now dealias a little less eagerly, which means a type selection on refinement class symbols makes it to reify this broke the t8104 tests. I also had to update the run/t6992 test, which should now test the right thing. Tests should be commented and/or use sensible names. What is it testing? What is the expected outcome? We should not be left guessing. --- test/files/neg/t0764b.scala | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 test/files/neg/t0764b.scala (limited to 'test/files/neg/t0764b.scala') diff --git a/test/files/neg/t0764b.scala b/test/files/neg/t0764b.scala new file mode 100644 index 0000000000..14c623c67a --- /dev/null +++ b/test/files/neg/t0764b.scala @@ -0,0 +1,63 @@ +// see neg/t0764 why this should probably be a pos/ test -- alas something's wrong with existential subtyping (?) + +// In all cases when calling "prepend" the receiver 'v' +// has static type NodeAlias[A] or (equivalently) Node { type T = A }. +// Since prepend explicitly returns the singleton type of the receiver, +// the return type of prepend in all cases is "v.type", and so the call +// to "new Main" can be parameterized with any of the following, in order +// of decreasing specificity with a tie for second place: +// +// new Main[v.type](v.prepend) +// new Main[NodeAlias[A]](v.prepend) +// new Main[Node { type T = A }](v.prepend) +// new Main(v.prepend) + +// the `fail` comments below denote what didn't compile before SI-8177 fixed all of them + +package p1 { + object t0764 { + type NodeAlias[A] = Node { type T = A } + trait Node { outer => + type T <: Node + def prepend: Node { type T = outer.type } = ??? + } + + class Main1[A <: Node](v: NodeAlias[A]) { + private[this] def f1 = new Main1(v.prepend) // fail + private[this] def f2 = new Main1[NodeAlias[A]](v.prepend) // fail + private[this] def f3 = new Main1[Node { type T = A }](v.prepend) // fail + private[this] def f4 = new Main1[v.type](v.prepend) // ok + } + + class Main2[A <: Node](v: Node { type T = A }) { + private[this] def f1 = new Main2(v.prepend) // fail + private[this] def f2 = new Main2[NodeAlias[A]](v.prepend) // fail + private[this] def f3 = new Main2[Node { type T = A }](v.prepend) // fail + private[this] def f4 = new Main2[v.type](v.prepend) // ok + } + } +} + +package p2 { + object t0764 { + type NodeAlias[A] = Node { type T = A } + trait Node { outer => + type T <: Node + def prepend: NodeAlias[outer.type] = ??? + } + + class Main1[A <: Node](v: NodeAlias[A]) { + private[this] def f1 = new Main1(v.prepend) // ok! <<========== WOT + private[this] def f2 = new Main1[NodeAlias[A]](v.prepend) // fail + private[this] def f3 = new Main1[Node { type T = A }](v.prepend) // fail + private[this] def f4 = new Main1[v.type](v.prepend) // ok + } + + class Main2[A <: Node](v: Node { type T = A }) { + private[this] def f1 = new Main2(v.prepend) // fail + private[this] def f2 = new Main2[NodeAlias[A]](v.prepend) // fail + private[this] def f3 = new Main2[Node { type T = A }](v.prepend) // fail + private[this] def f4 = new Main2[v.type](v.prepend) // ok + } + } +} -- cgit v1.2.3