diff options
author | Martin Odersky <odersky@gmail.com> | 2014-06-20 15:04:03 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-06-20 15:04:19 +0200 |
commit | b3364db33ff2ee2d57b4d0eaed03632099244f63 (patch) | |
tree | cfc94722c01bf6a7ddb3eff5411149e8a40235e1 /src/dotty/tools/dotc/typer/Implicits.scala | |
parent | 7cf6202ea94c016ffc2d2528ad8add186e9f3827 (diff) | |
download | dotty-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.scala | 33 |
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) } |