summaryrefslogtreecommitdiff
path: root/src/reflect
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/reflect
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/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala22
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala3
2 files changed, 17 insertions, 8 deletions
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index ea680867da..9a382649d9 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -363,11 +363,7 @@ trait Definitions extends api.StandardDefinitions {
def Predef_??? = getMemberMethod(PredefModule, nme.???)
def Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly)
- /** Is `sym` a member of Predef with the given name?
- * Note: DON't replace this by sym == Predef_conforms/etc, as Predef_conforms is a `def`
- * which does a member lookup (it can't be a lazy val because we might reload Predef
- * during resident compilations).
- */
+ @deprecated("use sym = currentRun.runDefinitions.Predef_xxx", "2.11.0")
def isPredefMemberNamed(sym: Symbol, name: Name) = (
(sym.name == name) && (sym.owner == PredefModule.moduleClass)
)
@@ -500,7 +496,6 @@ trait Definitions extends api.StandardDefinitions {
def ReflectRuntimeUniverse = ReflectRuntimePackage.map(sym => getMemberValue(sym, nme.universe))
def ReflectRuntimeCurrentMirror = ReflectRuntimePackage.map(sym => getMemberMethod(sym, nme.currentMirror))
- lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest)
lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifestFactory.type]
lazy val FullManifestClass = requiredClass[scala.reflect.Manifest[_]]
lazy val FullManifestModule = requiredModule[scala.reflect.ManifestFactory.type]
@@ -1417,5 +1412,20 @@ trait Definitions extends api.StandardDefinitions {
def universeMemberType(name: TypeName) = universe.tpe.memberType(getTypeMember(universe.symbol, name))
}
+
+ /** Efficient access to member symbols which must be looked up each run. Access via `currentRun.runRefinitions` */
+ final class RunDefinitions {
+ lazy val TagMaterializers = Map[Symbol, Symbol](
+ ClassTagClass -> materializeClassTag,
+ WeakTypeTagClass -> materializeWeakTypeTag,
+ TypeTagClass -> materializeTypeTag
+ )
+ lazy val TagSymbols = TagMaterializers.keySet
+ lazy val Predef_conforms = getMemberMethod(PredefModule, nme.conforms)
+ lazy val Predef_classOf = DefinitionsClass.this.Predef_classOf
+
+ lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest)
+ lazy val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
+ }
}
}
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 8fd58c42be..1f1f07c09a 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -304,7 +304,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.ReflectPackage
definitions.ReflectApiPackage
definitions.ReflectRuntimePackage
- definitions.PartialManifestClass
definitions.PartialManifestModule
definitions.FullManifestClass
definitions.FullManifestModule
@@ -493,4 +492,4 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
erasure.verifiedJavaErasure
erasure.boxingErasure
}
-} \ No newline at end of file
+}