aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Implicits.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-06-20 15:04:03 +0200
committerMartin Odersky <odersky@gmail.com>2014-06-20 15:04:19 +0200
commitb3364db33ff2ee2d57b4d0eaed03632099244f63 (patch)
treecfc94722c01bf6a7ddb3eff5411149e8a40235e1 /src/dotty/tools/dotc/typer/Implicits.scala
parent7cf6202ea94c016ffc2d2528ad8add186e9f3827 (diff)
downloaddotty-b3364db33ff2ee2d57b4d0eaed03632099244f63.tar.gz
dotty-b3364db33ff2ee2d57b4d0eaed03632099244f63.tar.bz2
dotty-b3364db33ff2ee2d57b4d0eaed03632099244f63.zip
Avoid caching values that depend on typevar state.
TypeVars flip from the initial state, where underlying == origin to the final state where underlying == inst. This flip can invalidate information that depends on the underlying type of a TypeVar. Since we do not know when the flip occurs, we need to avoid keeping any such information in a cache. The commit makes three caches depend on a new value: typerState.ephemeral. The value is set to `true` each time we follow the underlying type of a TypeVar, and this disables cached information to be retained. A test case for this commit is t2693.scala. This test passes typechecking with the previous commit, but fails in -Ycheck:front because of stale cache info in an "#Apply" typeref. The present commit fixes that.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Implicits.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala33
1 files changed, 25 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 86d513fff..da1492d61 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -142,9 +142,15 @@ object Implicits {
if (monitored) record(s"elided eligible refs", elided(this))
eligibles
case None =>
- val eligibles = computeEligible(tp)
- eligibleCache(tp) = eligibles
- eligibles
+ val savedEphemeral = ctx.typerState.ephemeral
+ ctx.typerState.ephemeral = false
+ try {
+ val result = computeEligible(tp)
+ if (ctx.typerState.ephemeral) record("ephemeral cache miss: eligible")
+ else eligibleCache(tp) = result
+ result
+ }
+ finally ctx.typerState.ephemeral |= savedEphemeral
}
}
@@ -334,11 +340,22 @@ trait ImplicitRunInfo { self: RunInfo =>
def iscope(tp: Type, isLifted: Boolean = false): OfTypeImplicits =
if (tp.hash == NotCached || !Config.cacheImplicitScopes)
ofTypeImplicits(collectCompanions(tp))
- else implicitScopeCache.getOrElseUpdate(tp, {
- val liftedTp = if (isLifted) tp else liftToClasses(tp)
- if (liftedTp ne tp) iscope(liftedTp, isLifted = true)
- else ofTypeImplicits(collectCompanions(tp))
- })
+ else implicitScopeCache get tp match {
+ case Some(is) => is
+ case None =>
+ val savedEphemeral = ctx.typerState.ephemeral
+ ctx.typerState.ephemeral = false
+ try {
+ val liftedTp = if (isLifted) tp else liftToClasses(tp)
+ val result =
+ if (liftedTp ne tp) iscope(liftedTp, isLifted = true)
+ else ofTypeImplicits(collectCompanions(tp))
+ if (ctx.typerState.ephemeral) record("ephemeral cache miss: implicitScope")
+ else implicitScopeCache(tp) = result
+ result
+ }
+ finally ctx.typerState.ephemeral |= savedEphemeral
+ }
iscope(tp)
}