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/core/Types.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/core/Types.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index f1cdfe54b..f3e10c5b0 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1075,24 +1075,32 @@ object Types { /** A second fallback to recompute the denotation if necessary */ private def computeDenot(implicit ctx: Context): Denotation = { - val d = lastDenotation match { - case null => - val sym = lastSymbol - if (sym == null) loadDenot else denotOfSym(sym) - case d: SymDenotation => - if (d.validFor.runId == ctx.runId || ctx.stillValid(d)) d.current - else { - val newd = loadDenot - if (newd.exists) newd else d.staleSymbolError - } - case d => - if (d.validFor.runId == ctx.period.runId) d.current - else loadDenot + val savedEphemeral = ctx.typerState.ephemeral + ctx.typerState.ephemeral = false + try { + val d = lastDenotation match { + case null => + val sym = lastSymbol + if (sym == null) loadDenot else denotOfSym(sym) + case d: SymDenotation => + if (d.validFor.runId == ctx.runId || ctx.stillValid(d)) d.current + else { + val newd = loadDenot + if (newd.exists) newd else d.staleSymbolError + } + case d => + if (d.validFor.runId == ctx.period.runId) d.current + else loadDenot + } + if (ctx.typerState.ephemeral) record("ephemeral cache miss: loadDenot") + else { + lastDenotation = d + lastSymbol = d.symbol + checkedPeriod = ctx.period + } + d } - lastDenotation = d - lastSymbol = d.symbol - checkedPeriod = ctx.period - d + finally ctx.typerState.ephemeral |= savedEphemeral } private def denotOfSym(sym: Symbol)(implicit ctx: Context): Denotation = { @@ -1974,7 +1982,11 @@ object Types { /** If the variable is instantiated, its instance, otherwise its origin */ override def underlying(implicit ctx: Context): Type = { val inst = instanceOpt - if (inst.exists) inst else origin + if (inst.exists) inst + else { + ctx.typerState.ephemeral = true + origin + } } override def computeHash: Int = identityHash |