aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Implicits.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/typer/Implicits.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 38ac709be..b3a1010cb 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -363,7 +363,18 @@ trait ImplicitRunInfo { self: RunInfo =>
computeIScope(cacheResult = false)
else implicitScopeCache get tp match {
case Some(is) => is
- case None => computeIScope(cacheResult = seen.isEmpty)
+ case None =>
+ // Implicit scopes are tricky to cache because of loops. For example
+ // in `tests/pos/implicit-scope-loop.scala`, the scope of B contains
+ // the scope of A which contains the scope of B. We break the loop
+ // by returning EmptyTermRefSet in `collectCompanions` for types
+ // that we have already seen, but this means that we cannot cache
+ // the computed scope of A, it is incomplete.
+ // Keeping track of exactly where these loops happen would require a
+ // lot of book-keeping, instead we choose to be conservative and only
+ // cache scopes before any type has been seen. This is unfortunate
+ // because loops are very common for types in scala.collection.
+ computeIScope(cacheResult = seen.isEmpty)
}
}