summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-10-29 16:04:17 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-11-08 08:20:45 +0100
commit3dba9932fcc79ce0ea6f7c9282320c14c95d133f (patch)
treeae37afaf2212d41706bb3f760bd2b4a5a8ff1925 /src/compiler/scala/tools/nsc/typechecker/Implicits.scala
parent4aeb8acf99493a5b3f7c2e012796ded77ae40a7f (diff)
downloadscala-3dba9932fcc79ce0ea6f7c9282320c14c95d133f.tar.gz
scala-3dba9932fcc79ce0ea6f7c9282320c14c95d133f.tar.bz2
scala-3dba9932fcc79ce0ea6f7c9282320c14c95d133f.zip
Add a per-run cache for member symbols
We are all used to calls to `definitions.PredefModule`, or `defintions.Predef_???` to grab the symbol of some well known entity. But you'll notice that some of these are lazy vals, and others are defs. Why is this so? In the presentation compiler, a member like `Predef.???` will be assigned a new symbol after the user browses into `Predef.scala`. Mistakenly using vals in definitions leads to subtle IDE bugs like SI-7678. We are able to trigger these situations in tests, as noted in the comments of that issue. Changing the vals to defs, on the other hand, has a performance penalty. Some schemes to workaround this have shown up: cache them per-implicit search, or compare method names and owners rather than symbols on hot paths in the type checker. This commit introduces a facility to cache these sort of symbols per-run, and uses it to check for `Predef.conforms` and and for the class/type tag materializers. A followup pull request (WIP: https://github.com/retronym/scala/compare/ticket/7678-2) will expand the use of to address the widespread and unsafe caching of member symbols that I found while investigating SI-7678.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Implicits.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala14
1 files changed, 4 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 8a3bba7d0f..dc60631421 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -337,6 +337,9 @@ trait Implicits {
val undetParams = if (isView) Nil else context.outer.undetparams
val wildPt = approximate(pt)
+ private val runDefintions = currentRun.runDefinitions
+ import runDefintions.{ TagMaterializers, TagSymbols, Predef_conforms, PartialManifestClass, ManifestSymbols }
+
def undet_s = if (undetParams.isEmpty) "" else undetParams.mkString(" inferring ", ", ", "")
def tree_s = typeDebug ptTree tree
def ctx_s = fullSiteString(context)
@@ -806,7 +809,7 @@ trait Implicits {
private def isIneligible(info: ImplicitInfo) = (
info.isCyclicOrErroneous
- || isView && isPredefMemberNamed(info.sym, nme.conforms)
+ || isView && (info.sym eq Predef_conforms)
|| shadower.isShadowed(info.name)
|| (!context.macrosEnabled && info.sym.isTermMacro)
)
@@ -1105,13 +1108,6 @@ trait Implicits {
}
}
- private def TagSymbols = TagMaterializers.keySet
- private val TagMaterializers = Map[Symbol, Symbol](
- ClassTagClass -> materializeClassTag,
- WeakTypeTagClass -> materializeWeakTypeTag,
- TypeTagClass -> materializeTypeTag
- )
-
/** Creates a tree will produce a tag of the requested flavor.
* An EmptyTree is returned if materialization fails.
*/
@@ -1173,8 +1169,6 @@ trait Implicits {
else SearchFailure
}
- private val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
-
/** Creates a tree that calls the relevant factory method in object
* scala.reflect.Manifest for type 'tp'. An EmptyTree is returned if
* no manifest is found. todo: make this instantiate take type params as well?