summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/scala/reflect/internal/tpe/TypeMaps.scala')
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala18
1 files changed, 14 insertions, 4 deletions
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 28a7fb37a6..af5128163b 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -1001,10 +1001,20 @@ private[internal] trait TypeMaps {
class ContainsCollector(sym: Symbol) extends TypeCollector(false) {
def traverse(tp: Type) {
if (!result) {
- tp.normalize match {
- case TypeRef(_, sym1, _) if (sym == sym1) => result = true
- case SingleType(_, sym1) if (sym == sym1) => result = true
- case _ => mapOver(tp)
+ tp match {
+ case _: ExistentialType =>
+ // ExistentialType#normalize internally calls contains, which leads to exponential performance
+ // for types like: `A[_ <: B[_ <: ... ]]`. Example: pos/existential-contains.scala.
+ //
+ // We can just map over the components and wait until we see the underlying type before we call
+ // normalize.
+ mapOver(tp)
+ case _ =>
+ tp.normalize match {
+ case TypeRef(_, sym1, _) if (sym == sym1) => result = true
+ case SingleType(_, sym1) if (sym == sym1) => result = true
+ case _ => mapOver(tp)
+ }
}
}
}