summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala25
-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/run/t5294.scala22
5 files changed, 108 insertions, 5 deletions
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 24f83c0b99..df61d2e418 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -610,11 +610,26 @@ private[internal] trait TypeMaps {
}
// Does the candidate symbol match the given prefix and class?
- // Since pre may be something like ThisType(A) where trait A { self: B => },
- // we have to test the typeSymbol of the widened type, not pre.typeSymbol, or
- // B will not be considered.
- private def matchesPrefixAndClass(pre: Type, clazz: Symbol)(candidate: Symbol) =
- (clazz == candidate) && (pre.widen.typeSymbol isSubClass clazz)
+ private def matchesPrefixAndClass(pre: Type, clazz: Symbol)(candidate: Symbol) = (clazz == candidate) && {
+ val pre1 = pre match {
+ case tv: TypeVar =>
+ // Needed with existentials in prefixes, e.g. test/files/pos/typevar-in-prefix.scala
+ // Perhaps the base type sequence of a type var should include it bounds?
+ tv.origin
+ case _ => pre
+ }
+ // widen needed (at least) because of https://github.com/scala/scala-dev/issues/166
+ (clazz == candidate) && (
+ if (clazz.isRefinementClass)
+ // base type seqs of aliases over refinement types have copied refinement types based on beta reduction
+ // for reliable lookup we need to consult the base type of the type symbol. (example: pos/t8177b.scala)
+ pre1.widen.typeSymbol isSubClass clazz
+ else
+ // In the general case, we look at the base type sequence of the prefix itself,
+ // which can have more concrete base classes than `.typeSymbol.baseClasses` (example: t5294, t6161)
+ pre1.widen.baseTypeIndex(clazz) != -1
+ )
+ }
// Whether the annotation tree currently being mapped over has had a This(_) node rewritten.
private[this] var wroteAnnotation = false
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/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!
+ }
+}