diff options
Diffstat (limited to 'src/reflect/scala/reflect/internal/tpe/TypeMaps.scala')
-rw-r--r-- | src/reflect/scala/reflect/internal/tpe/TypeMaps.scala | 18 |
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) + } } } } |