diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-10-29 16:04:17 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-11-08 08:25:18 +0100 |
commit | a5127a8392fd2a0bce9b3ced302b4ebe1a80bc65 (patch) | |
tree | 4d52b8ed7dd8fcfb10d4bef41198ffe6ecc7cfe6 | |
parent | 3dba9932fcc79ce0ea6f7c9282320c14c95d133f (diff) | |
download | scala-a5127a8392fd2a0bce9b3ced302b4ebe1a80bc65.tar.gz scala-a5127a8392fd2a0bce9b3ced302b4ebe1a80bc65.tar.bz2 scala-a5127a8392fd2a0bce9b3ced302b4ebe1a80bc65.zip |
SI-7678 Don't cache member symbols of TypeTags in Definitions.
It we can only safely use vals in Definitions for top-level symbols.
Otherwise, when the IDE switches to loading the symbol from source,
we can hold on to a stale symbol, which in turn impedes implicit
materialization of TypeTags.
This commit moves (most) of the accessors for member symbols
into RunDefinitions, and changes calling code accordingly.
This is a win for presentation compiler correctness, and
might even shave of a few cycles.
In a few cases, I have had to leave a `def` to a member symbol
in Definitions so we can get to it from the SymbolTable cake,
which doesn't see RunDefinitions.
The macro FastTrack facility now correctly recreates the mapping
from Symbol to macro implementation each run, using a new facility
in perRunCaches to create a run-indexed cache.
The enclosed test recreates the situation reported in the ticket,
in which TypeTags.scala is loaded from source.
31 files changed, 284 insertions, 148 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala index 45bb87fc47..30ba082a81 100644 --- a/src/compiler/scala/reflect/macros/compiler/Errors.scala +++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala @@ -12,6 +12,8 @@ trait Errors extends Traces { import definitions._ import typer.TyperErrorGen._ import typer.infer.InferErrorGen._ + private val runDefinitions = currentRun.runDefinitions + import runDefinitions._ def globalSettings = global.settings // sanity check errors diff --git a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala index 49a5c01ad7..9c4db1990b 100644 --- a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala +++ b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala @@ -12,6 +12,8 @@ trait Resolvers { import definitions.{EmptyPackageClass => _, _} import treeInfo._ import gen._ + private val runDefinitions = currentRun.runDefinitions + import runDefinitions.{Predef_???, _} /** Determines the type of context implied by the macro def. */ diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala index b3e8131e34..088b108844 100644 --- a/src/compiler/scala/reflect/macros/compiler/Validators.scala +++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala @@ -11,6 +11,8 @@ trait Validators { import global._ import analyzer._ import definitions._ + private val runDefinitions = currentRun.runDefinitions + import runDefinitions.{Predef_???, _} def validateMacroImplRef() = { sanityCheck() diff --git a/src/compiler/scala/reflect/macros/util/Helpers.scala b/src/compiler/scala/reflect/macros/util/Helpers.scala index dd23b0fc32..bb4f2055ad 100644 --- a/src/compiler/scala/reflect/macros/util/Helpers.scala +++ b/src/compiler/scala/reflect/macros/util/Helpers.scala @@ -23,6 +23,9 @@ trait Helpers { * or to streamline creation of the list of macro arguments. */ def transformTypeTagEvidenceParams(macroImplRef: Tree, transform: (Symbol, Symbol) => Symbol): List[List[Symbol]] = { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + val MacroContextUniverse = definitions.MacroContextUniverse val treeInfo.MacroImplReference(isBundle, _, macroImpl, _) = macroImplRef val paramss = macroImpl.paramss @@ -51,15 +54,25 @@ trait Helpers { * * @see Metalevels.scala for more information and examples about metalevels */ - def increaseMetalevel(pre: Type, tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { - case tp => typeRef(pre, MacroContextExprClass, List(tp)) + def increaseMetalevel(pre: Type, tp: Type): Type = { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + + transparentShallowTransform(RepeatedParamClass, tp) { + case tp => typeRef(pre, MacroContextExprClass, List(tp)) + } } /** Transforms c.Expr[T] types into c.Tree and leaves the rest unchanged. */ - def untypeMetalevel(tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { - case ExprClassOf(_) => typeRef(tp.prefix, TreesTreeType, Nil) - case tp => tp + def untypeMetalevel(tp: Type): Type = { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + + transparentShallowTransform(RepeatedParamClass, tp) { + case ExprClassOf(_) => typeRef(tp.prefix, TreesTreeType, Nil) + case tp => tp + } } /** Decreases metalevel of the type, i.e. transforms: @@ -68,8 +81,12 @@ trait Helpers { * * @see Metalevels.scala for more information and examples about metalevels */ - def decreaseMetalevel(tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { - case ExprClassOf(runtimeType) => runtimeType - case _ => AnyTpe // so that macro impls with rhs = ??? don't screw up our inference + def decreaseMetalevel(tp: Type): Type = { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + transparentShallowTransform(RepeatedParamClass, tp) { + case ExprClassOf(runtimeType) => runtimeType + case _ => AnyTpe // so that macro impls with rhs = ??? don't screw up our inference + } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index 74949fce6d..ad0632f93e 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -20,6 +20,8 @@ abstract class Reifier extends States val global: Global import global._ import definitions._ + private val runDefinitions = currentRun.runDefinitions + import runDefinitions._ val typer: global.analyzer.Typer val universe: Tree @@ -110,7 +112,7 @@ abstract class Reifier extends States // maybe try `resetLocalAttrs` once the dust settles var importantSymbols = Set[Symbol]( NothingClass, AnyClass, SingletonClass, PredefModule, ScalaRunTimeModule, TypeCreatorClass, TreeCreatorClass, MirrorClass, - ApiUniverseClass, JavaUniverseClass, ReflectRuntimePackage, ReflectRuntimeCurrentMirror) + ApiUniverseClass, JavaUniverseClass, ReflectRuntimePackage, runDefinitions.ReflectRuntimeCurrentMirror) importantSymbols ++= importantSymbols map (_.companionSymbol) importantSymbols ++= importantSymbols map (_.moduleClass) importantSymbols ++= importantSymbols map (_.linkedClassOfClass) diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala index 0bffe55403..0c7831b592 100644 --- a/src/compiler/scala/reflect/reify/Taggers.scala +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -8,6 +8,8 @@ abstract class Taggers { import c.universe._ import definitions._ + private val runDefinitions = currentRun.runDefinitions + import runDefinitions._ val coreTags = Map( ByteTpe -> nme.Byte, diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala index 6c94726231..99b968be3b 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -6,6 +6,8 @@ trait GenTypes { import global._ import definitions._ + private val runDefinitions = currentRun.runDefinitions + import runDefinitions.{ReflectRuntimeUniverse, ReflectRuntimeCurrentMirror, _} /** * Reify a type. diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala index 30cfec8e2a..eea63d8f28 100644 --- a/src/compiler/scala/reflect/reify/package.scala +++ b/src/compiler/scala/reflect/reify/package.scala @@ -63,11 +63,11 @@ package object reify { tpe.dealiasWiden match { case TypeRef(_, ArrayClass, componentTpe :: Nil) => val componentErasure = reifyRuntimeClass(global)(typer0, componentTpe, concrete) - gen.mkMethodCall(arrayClassMethod, List(componentErasure)) + gen.mkMethodCall(currentRun.runDefinitions.arrayClassMethod, List(componentErasure)) case _ => var erasure = tpe.erasure if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe - gen.mkNullaryCall(Predef_classOf, List(erasure)) + gen.mkNullaryCall(currentRun.runDefinitions.Predef_classOf, List(erasure)) } } diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala index fff6978653..6c073c0b4c 100644 --- a/src/compiler/scala/reflect/reify/phases/Reshape.scala +++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala @@ -9,6 +9,8 @@ trait Reshape { import global._ import definitions._ import treeInfo.Unapplied + private val runDefinitions = currentRun.runDefinitions + import runDefinitions._ /** * Rolls back certain changes that were introduced during typechecking of the reifee. diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index a80fee876e..d44e7a9312 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -702,7 +702,7 @@ abstract class GenICode extends SubComponent { } genLoadApply3 - case Apply(fun @ _, List(expr)) if (definitions.isBox(fun.symbol)) => + case Apply(fun @ _, List(expr)) if currentRun.runDefinitions.isBox(fun.symbol) => def genLoadApply4 = { debuglog("BOX : " + fun.symbol.fullName) val ctx1 = genLoad(expr, ctx, toTypeKind(expr.tpe)) @@ -721,7 +721,7 @@ abstract class GenICode extends SubComponent { } genLoadApply4 - case Apply(fun @ _, List(expr)) if (definitions.isUnbox(fun.symbol)) => + case Apply(fun @ _, List(expr)) if (currentRun.runDefinitions.isUnbox(fun.symbol)) => debuglog("UNBOX : " + fun.symbol.fullName) val ctx1 = genLoad(expr, ctx, toTypeKind(expr.tpe)) val boxType = toTypeKind(fun.symbol.owner.linkedClassOfClass.tpe) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 3bacc26a3a..c166b0bb7e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -623,14 +623,14 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { abort(s"Cannot instantiate $tpt of kind: $generatedType") } - case Apply(fun @ _, List(expr)) if definitions.isBox(fun.symbol) => + case Apply(fun @ _, List(expr)) if currentRun.runDefinitions.isBox(fun.symbol) => val nativeKind = tpeTK(expr) genLoad(expr, nativeKind) val MethodNameAndType(mname, mdesc) = asmBoxTo(nativeKind) bc.invokestatic(BoxesRunTime.getInternalName, mname, mdesc) generatedType = boxResultType(fun.symbol) // was toTypeKind(fun.symbol.tpe.resultType) - case Apply(fun @ _, List(expr)) if definitions.isUnbox(fun.symbol) => + case Apply(fun @ _, List(expr)) if currentRun.runDefinitions.isUnbox(fun.symbol) => genLoad(expr) val boxType = unboxResultType(fun.symbol) // was toTypeKind(fun.symbol.owner.linkedClassOfClass.tpe) generatedType = boxType diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala index 39fea9a486..916d118b6e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala @@ -90,11 +90,11 @@ abstract class BCodeTypes extends BCodeIdiomatic { ) boxResultType = - for(Pair(csym, msym) <- definitions.boxMethod) + for(Pair(csym, msym) <- currentRun.runDefinitions.boxMethod) yield (msym -> classLiteral(primitiveTypeMap(csym))) unboxResultType = - for(Pair(csym, msym) <- definitions.unboxMethod) + for(Pair(csym, msym) <- currentRun.runDefinitions.unboxMethod) yield (msym -> primitiveTypeMap(csym)) // boxed classes are looked up in the `exemplars` map by jvmWiseLUB(). diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 0135190256..3ecce8d7b1 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -168,7 +168,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), REF(reflParamsCacheSym))) def cacheRHS = ((REF(methodCache) DOT methodCache_add)(REF(forReceiverSym), REF(methodSym))) BLOCK( - REF(methodSym) === (REF(ensureAccessibleMethod) APPLY (methodSymRHS)), + REF(methodSym) === (REF(currentRun.runDefinitions.ensureAccessibleMethod) APPLY (methodSymRHS)), REF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS), Return(REF(methodSym)) ) @@ -181,11 +181,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL { def testForName(name: Name): Tree => Tree = t => ( if (nme.CommonOpNames(name)) - gen.mkMethodCall(Boxes_isNumberOrBool, t :: Nil) + gen.mkMethodCall(currentRun.runDefinitions.Boxes_isNumberOrBool, t :: Nil) else if (nme.BooleanOpNames(name)) t IS_OBJ BoxedBooleanClass.tpe else - gen.mkMethodCall(Boxes_isNumber, t :: Nil) + gen.mkMethodCall(currentRun.runDefinitions.Boxes_isNumber, t :: Nil) ) /* The Tree => Tree function in the return is necessary to prevent the original qual @@ -219,6 +219,9 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* ### CALLING THE APPLY ### */ def callAsReflective(paramTypes: List[Type], resType: Type): Tree = { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + gen.evalOnce(qual, currentOwner, unit) { qual1 => /* Some info about the type of the method being called. */ val methSym = ad.symbol @@ -518,7 +521,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { // // See SI-6611; we must *only* do this for literal vararg arrays. case Apply(appMeth, List(Apply(wrapRefArrayMeth, List(arg @ StripCast(ArrayValue(_, _)))), _)) - if wrapRefArrayMeth.symbol == Predef_wrapRefArray && appMeth.symbol == ArrayModule_genericApply => + if wrapRefArrayMeth.symbol == currentRun.runDefinitions.Predef_wrapRefArray && appMeth.symbol == ArrayModule_genericApply => super.transform(arg) case Apply(appMeth, List(elem0, Apply(wrapArrayMeth, List(rest @ ArrayValue(elemtpt, _))))) if wrapArrayMeth.symbol == Predef_wrapArray(elemtpt.tpe) && appMeth.symbol == ArrayModule_apply(elemtpt.tpe) => diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 2ec7e97ac5..b97b1e3527 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -362,6 +362,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { * be an error to pass it to array_update(.., .., Object). */ def rewriteArrayUpdate(tree: Tree): Tree = { + val arrayUpdateMethod = currentRun.runDefinitions.arrayUpdateMethod val adapter = new Transformer { override def transform(t: Tree): Tree = t match { case Apply(fun @ Select(receiver, method), List(xs, idx, v)) if fun.symbol == arrayUpdateMethod => diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 4cf3bef939..1723c69180 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -101,6 +101,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private val concreteSpecMethods = perRunCaches.newWeakSet[Symbol]() private def specializedOn(sym: Symbol): List[Symbol] = { + val GroupOfSpecializable = currentRun.runDefinitions.GroupOfSpecializable sym getAnnotation SpecializedClass match { case Some(AnnotationInfo(_, Nil, _)) => specializableTypes.map(_.typeSymbol) case Some(ann @ AnnotationInfo(_, args, _)) => { diff --git a/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala b/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala index 41b8461c46..f83b6f857e 100644 --- a/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala +++ b/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala @@ -25,7 +25,7 @@ trait TypeAdaptingTransformer { } private def isSafelyRemovableUnbox(fn: Tree, arg: Tree): Boolean = { - isUnbox(fn.symbol) && { + currentRun.runDefinitions.isUnbox(fn.symbol) && { val cls = arg.tpe.typeSymbol (cls == definitions.NullClass) || isBoxedValueClass(cls) } @@ -75,7 +75,7 @@ trait TypeAdaptingTransformer { log(s"boxing an unbox: ${tree.symbol} -> ${arg.tpe}") arg case _ => - (REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectTpe + (REF(currentRun.runDefinitions.boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectTpe } } } @@ -123,7 +123,7 @@ trait TypeAdaptingTransformer { case x => assert(x != ArrayClass) // don't `setType pt` the Apply tree, as the Apply's fun won't be typechecked if the Apply tree already has a type - Apply(unboxMethod(pt.typeSymbol), tree) + Apply(currentRun.runDefinitions.unboxMethod(pt.typeSymbol), tree) } } typer.typedPos(tree.pos)(tree1) @@ -184,4 +184,4 @@ trait TypeAdaptingTransformer { cast(tree, pt) } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala index c8dbbb02bb..06b39b035a 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala @@ -72,7 +72,7 @@ trait MatchCodeGen extends Interface { // for name-based matching, but this was an expedient route for the basics. def drop(tgt: Tree)(n: Int): Tree = { def callDirect = fn(tgt, nme.drop, LIT(n)) - def callRuntime = Apply(REF(traversableDropMethod), tgt :: LIT(n) :: Nil) + def callRuntime = Apply(REF(currentRun.runDefinitions.traversableDropMethod), tgt :: LIT(n) :: Nil) def needsRuntime = (tgt.tpe ne null) && (typeOfMemberNamedDrop(tgt.tpe) == NoType) if (needsRuntime) callRuntime else callDirect diff --git a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala index 567d5d0ecd..0b5b0759b2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala @@ -24,6 +24,8 @@ trait Adaptations { trait Adaptation { self: Typer => + import runDefinitions._ + def checkValidAdaptation(t: Tree, args: List[Tree]): Boolean = { def applyArg = t match { case Apply(_, arg :: Nil) => arg diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index dc60631421..b1a48f7478 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -338,7 +338,7 @@ trait Implicits { val wildPt = approximate(pt) private val runDefintions = currentRun.runDefinitions - import runDefintions.{ TagMaterializers, TagSymbols, Predef_conforms, PartialManifestClass, ManifestSymbols } + import runDefintions._ def undet_s = if (undetParams.isEmpty) "" else undetParams.mkString(" inferring ", ", ", "") def tree_s = typeDebug ptTree tree diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index d1045757a5..02fb70f3e5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -104,7 +104,10 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { targs: List[Tree]) { // Was this binding derived from a `def ... = macro ???` definition? - def is_??? = className == Predef_???.owner.javaClassName && methName == Predef_???.name.encoded + def is_??? = { + val Predef_??? = currentRun.runDefinitions.Predef_??? + className == Predef_???.owner.javaClassName && methName == Predef_???.name.encoded + } } /** Macro def -> macro impl bindings are serialized into a `macroImpl` annotation @@ -146,6 +149,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { } def pickle(macroImplRef: Tree): Tree = { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ val MacroImplReference(isBundle, owner, macroImpl, targs) = macroImplRef // todo. refactor when fixing SI-5498 @@ -311,7 +316,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { def fail() = { if (macroDef != null) macroDef setFlag IS_ERROR; macroDdef setType ErrorType; EmptyTree } def success(macroImplRef: Tree) = { bindMacroImpl(macroDef, macroImplRef); macroImplRef } - if (!typer.checkFeature(macroDdef.pos, MacrosFeature, immediate = true)) { + if (!typer.checkFeature(macroDdef.pos, currentRun.runDefinitions.MacrosFeature, immediate = true)) { macroLogVerbose("typecheck terminated unexpectedly: language.experimental.macros feature is not enabled") fail() } else { diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 36f889f8a4..84531608e0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -945,7 +945,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } def checkImplicitViewOptionApply(pos: Position, fn: Tree, args: List[Tree]): Unit = if (settings.lint) (fn, args) match { - case (tap@TypeApply(fun, targs), List(view: ApplyImplicitView)) if fun.symbol == Option_apply => + case (tap@TypeApply(fun, targs), List(view: ApplyImplicitView)) if fun.symbol == currentRun.runDefinitions.Option_apply => unit.warning(pos, s"Suspicious application of an implicit view (${view.fun}) in the argument to Option.apply.") // SI-6567 case _ => } diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index 32a66aa4dd..90ec3a89b8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -10,6 +10,9 @@ trait Tags { trait Tag { self: Typer => + private val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = enteringTyper { def wrapper (tree: => Tree): Tree = if (allowMaterialization) (context.withMacrosEnabled[Tree](tree)) else (context.withMacrosDisabled[Tree](tree)) wrapper(inferImplicit( diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index c385e7533a..a9bb81c691 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -115,6 +115,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper import context0.unit import typeDebug.{ ptTree, ptBlock, ptLine, inGreen, inRed } import TyperErrorGen._ + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ val infer = new Inferencer(context0) { // See SI-3281 re undoLog @@ -3847,7 +3849,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (sameLength(tparams, args)) { val targs = args map (_.tpe) checkBounds(tree, NoPrefix, NoSymbol, tparams, targs, "") - if (fun.symbol == Predef_classOf) + if (isPredefClassOf(fun.symbol)) typedClassOf(tree, args.head, noGen = true) else { if (!isPastTyper && fun.symbol == Any_isInstanceOf && targs.nonEmpty) { @@ -4807,7 +4809,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper typed1(This(sym.owner) setPos tree.pos, mode, pt) // Inferring classOf type parameter from expected type. Otherwise an // actual call to the stubbed classOf method is generated, returning null. - else if (isPredefMemberNamed(sym, nme.classOf) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) + else if (isPredefClassOf(sym) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) typedClassOf(tree, TypeTree(pt.typeArgs.head)) else { val pre1 = if (sym.isTopLevel) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala index ad1d4c896b..dd92e14602 100644 --- a/src/compiler/scala/tools/reflect/FastTrack.scala +++ b/src/compiler/scala/tools/reflect/FastTrack.scala @@ -37,14 +37,19 @@ trait FastTrack { } /** A map from a set of pre-established macro symbols to their implementations. */ - lazy val fastTrack = Map[Symbol, FastTrackEntry]( - make( materializeClassTag) { case Applied(_, ttag :: Nil, _) => _.materializeClassTag(ttag.tpe) }, - make( materializeWeakTypeTag) { case Applied(_, ttag :: Nil, (u :: _) :: _) => _.materializeTypeTag(u, EmptyTree, ttag.tpe, concrete = false) }, - make( materializeTypeTag) { case Applied(_, ttag :: Nil, (u :: _) :: _) => _.materializeTypeTag(u, EmptyTree, ttag.tpe, concrete = true) }, - make( ApiUniverseReify) { case Applied(_, ttag :: Nil, (expr :: _) :: _) => c => c.materializeExpr(c.prefix.tree, EmptyTree, expr) }, - make( StringContext_f) { case Applied(Select(Apply(_, ps), _), _, args) => c => c.macro_StringInterpolation_f(ps, args.flatten, c.expandee.pos) }, - make(ReflectRuntimeCurrentMirror) { case _ => c => currentMirror(c).tree }, - make( QuasiquoteClass_api_apply) { case _ => _.expandQuasiquote }, - make(QuasiquoteClass_api_unapply) { case _ => _.expandQuasiquote } - ) + def fastTrack: Map[Symbol, FastTrackEntry] = fastTrackCache() + private val fastTrackCache = perRunCaches.newGeneric[Map[Symbol, FastTrackEntry]] { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + Map[Symbol, FastTrackEntry]( + make( materializeClassTag) { case Applied(_, ttag :: Nil, _) => _.materializeClassTag(ttag.tpe) }, + make( materializeWeakTypeTag) { case Applied(_, ttag :: Nil, (u :: _) :: _) => _.materializeTypeTag(u, EmptyTree, ttag.tpe, concrete = false) }, + make( materializeTypeTag) { case Applied(_, ttag :: Nil, (u :: _) :: _) => _.materializeTypeTag(u, EmptyTree, ttag.tpe, concrete = true) }, + make( ApiUniverseReify) { case Applied(_, ttag :: Nil, (expr :: _) :: _) => c => c.materializeExpr(c.prefix.tree, EmptyTree, expr) }, + make( StringContext_f) { case Applied(Select(Apply(_, ps), _), _, args) => c => c.macro_StringInterpolation_f(ps, args.flatten, c.expandee.pos) }, + make(ReflectRuntimeCurrentMirror) { case _ => c => currentMirror(c).tree }, + make( QuasiquoteClass_api_apply) { case _ => _.expandQuasiquote }, + make(QuasiquoteClass_api_unapply) { case _ => _.expandQuasiquote } + ) + } } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 9a382649d9..7cb051c63d 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -68,7 +68,7 @@ trait Definitions extends api.StandardDefinitions { tpnme.Unit -> VOID_TAG ) - private def catastrophicFailure() = + private[Definitions] def catastrophicFailure() = abort("Could not find value classes! This is a catastrophic failure. scala " + scala.util.Properties.versionString) @@ -78,16 +78,8 @@ trait Definitions extends api.StandardDefinitions { case _ => catastrophicFailure() } } - private def valueClassCompanion(name: TermName): ModuleSymbol = { - getMember(ScalaPackageClass, name) match { - case x: ModuleSymbol => x - case _ => catastrophicFailure() - } - } - private def valueCompanionMember(className: Name, methodName: TermName): TermSymbol = - getMemberMethod(valueClassCompanion(className.toTermName).moduleClass, methodName) - private def classesMap[T](f: Name => T) = symbolsMap(ScalaValueClassesNoUnit, f) + private[Definitions] def classesMap[T](f: Name => T) = symbolsMap(ScalaValueClassesNoUnit, f) private def symbolsMap[T](syms: List[Symbol], f: Name => T): Map[Symbol, T] = mapFrom(syms)(x => f(x.name)) private def symbolsMapFilt[T](syms: List[Symbol], p: Name => Boolean, f: Name => T) = symbolsMap(syms filter (x => p(x.name)), f) @@ -99,8 +91,6 @@ trait Definitions extends api.StandardDefinitions { lazy val boxedClass = classesMap(x => getClassByName(boxedName(x))) lazy val refClass = classesMap(x => getRequiredClass("scala.runtime." + x + "Ref")) lazy val volatileRefClass = classesMap(x => getRequiredClass("scala.runtime.Volatile" + x + "Ref")) - lazy val boxMethod = classesMap(x => valueCompanionMember(x, nme.box)) - lazy val unboxMethod = classesMap(x => valueCompanionMember(x, nme.unbox)) def isNumericSubClass(sub: Symbol, sup: Symbol) = ( (numericWeight contains sub) @@ -125,9 +115,9 @@ trait Definitions extends api.StandardDefinitions { lazy val FloatClass = valueClassSymbol(tpnme.Float) lazy val DoubleClass = valueClassSymbol(tpnme.Double) lazy val BooleanClass = valueClassSymbol(tpnme.Boolean) - lazy val Boolean_and = getMemberMethod(BooleanClass, nme.ZAND) - lazy val Boolean_or = getMemberMethod(BooleanClass, nme.ZOR) - lazy val Boolean_not = getMemberMethod(BooleanClass, nme.UNARY_!) + def Boolean_and = getMemberMethod(BooleanClass, nme.ZAND) + def Boolean_or = getMemberMethod(BooleanClass, nme.ZOR) + def Boolean_not = getMemberMethod(BooleanClass, nme.UNARY_!) lazy val UnitTpe = UnitClass.tpe lazy val ByteTpe = ByteClass.tpe @@ -356,14 +346,9 @@ trait Definitions extends api.StandardDefinitions { // Those modules and their module classes lazy val UnqualifiedOwners = UnqualifiedModules.toSet ++ UnqualifiedModules.map(_.moduleClass) - lazy val PredefModule = requiredModule[scala.Predef.type] - def Predef_classOf = getMemberMethod(PredefModule, nme.classOf) - def Predef_wrapRefArray = getMemberMethod(PredefModule, nme.wrapRefArray) - def Predef_wrapArray(tp: Type) = getMemberMethod(PredefModule, wrapArrayMethodName(tp)) - def Predef_??? = getMemberMethod(PredefModule, nme.???) - def Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly) - - @deprecated("use sym = currentRun.runDefinitions.Predef_xxx", "2.11.0") + lazy val PredefModule = requiredModule[scala.Predef.type] + def Predef_wrapArray(tp: Type) = getMemberMethod(PredefModule, wrapArrayMethodName(tp)) + def Predef_??? = getMemberMethod(PredefModule, nme.???) def isPredefMemberNamed(sym: Symbol, name: Name) = ( (sym.name == name) && (sym.owner == PredefModule.moduleClass) ) @@ -371,24 +356,13 @@ trait Definitions extends api.StandardDefinitions { /** Specialization. */ lazy val SpecializableModule = requiredModule[Specializable] - lazy val GroupOfSpecializable = getMemberClass(SpecializableModule, tpnme.Group) lazy val ScalaRunTimeModule = requiredModule[scala.runtime.ScalaRunTime.type] lazy val SymbolModule = requiredModule[scala.Symbol.type] - lazy val Symbol_apply = getMemberMethod(SymbolModule, nme.apply) - - def arrayApplyMethod = getMemberMethod(ScalaRunTimeModule, nme.array_apply) - def arrayUpdateMethod = getMemberMethod(ScalaRunTimeModule, nme.array_update) - def arrayLengthMethod = getMemberMethod(ScalaRunTimeModule, nme.array_length) - def arrayCloneMethod = getMemberMethod(ScalaRunTimeModule, nme.array_clone) - def ensureAccessibleMethod = getMemberMethod(ScalaRunTimeModule, nme.ensureAccessible) - def arrayClassMethod = getMemberMethod(ScalaRunTimeModule, nme.arrayClass) - def traversableDropMethod = getMemberMethod(ScalaRunTimeModule, nme.drop) + def Symbol_apply = getMemberMethod(SymbolModule, nme.apply) // classes with special meanings lazy val StringAddClass = requiredClass[scala.runtime.StringAdd] - lazy val ArrowAssocClass = getRequiredClass("scala.Predef.ArrowAssoc") // SI-5731 - lazy val StringAdd_+ = getMemberMethod(StringAddClass, nme.PLUS) lazy val ScalaNumberClass = requiredClass[scala.math.ScalaNumber] lazy val TraitSetterAnnotationClass = requiredClass[scala.runtime.TraitSetter] lazy val DelayedInitClass = requiredClass[scala.DelayedInit] @@ -450,7 +424,6 @@ trait Definitions extends api.StandardDefinitions { def isReferenceArray(tp: Type) = elementTest(ArrayClass, tp)(_ <:< AnyRefTpe) def isArrayOfSymbol(tp: Type, elem: Symbol) = elementTest(ArrayClass, tp)(_.typeSymbol == elem) def elementType(container: Symbol, tp: Type): Type = elementExtract(container, tp) - object ExprClassOf { def unapply(tp: Type): Option[Type] = elementExtractOption(ExprClass, tp) } // collections classes lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]] @@ -462,7 +435,7 @@ trait Definitions extends api.StandardDefinitions { lazy val TraversableClass = requiredClass[scala.collection.Traversable[_]] lazy val ListModule = requiredModule[scala.collection.immutable.List.type] - lazy val List_apply = getMemberMethod(ListModule, nme.apply) + def List_apply = getMemberMethod(ListModule, nme.apply) lazy val NilModule = requiredModule[scala.collection.immutable.Nil.type] lazy val SeqModule = requiredModule[scala.collection.Seq.type] @@ -503,28 +476,17 @@ trait Definitions extends api.StandardDefinitions { lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type] lazy val TreesClass = getClassIfDefined("scala.reflect.api.Trees") // defined in scala-reflect.jar, so we need to be careful - lazy val TreesTreeType = TreesClass.map(sym => getTypeMember(sym, tpnme.Tree)) - object TreeType { def unapply(tpe: Type): Boolean = tpe.typeSymbol.overrideChain contains TreesTreeType } - object SubtreeType { def unapply(tpe: Type): Boolean = tpe.typeSymbol.overrideChain exists (_.tpe <:< TreesTreeType.tpe) } lazy val ExprsClass = getClassIfDefined("scala.reflect.api.Exprs") // defined in scala-reflect.jar, so we need to be careful - lazy val ExprClass = ExprsClass.map(sym => getMemberClass(sym, tpnme.Expr)) + def ExprClass = ExprsClass.map(sym => getMemberClass(sym, tpnme.Expr)) def ExprSplice = ExprClass.map(sym => getMemberMethod(sym, nme.splice)) def ExprValue = ExprClass.map(sym => getMemberMethod(sym, nme.value)) lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]] lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]] lazy val TypeTagsClass = getClassIfDefined("scala.reflect.api.TypeTags") // defined in scala-reflect.jar, so we need to be careful - lazy val WeakTypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.WeakTypeTag)) - lazy val WeakTypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.WeakTypeTag)) - lazy val TypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.TypeTag)) - lazy val TypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.TypeTag)) - def materializeClassTag = getMemberMethod(ReflectPackage, nme.materializeClassTag) - def materializeWeakTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeWeakTypeTag)) - def materializeTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeTypeTag)) lazy val ApiUniverseClass = getClassIfDefined("scala.reflect.api.Universe") // defined in scala-reflect.jar, so we need to be careful - def ApiUniverseReify = ApiUniverseClass.map(sym => getMemberMethod(sym, nme.reify)) lazy val JavaUniverseClass = getClassIfDefined("scala.reflect.api.JavaUniverse") // defined in scala-reflect.jar, so we need to be careful lazy val MirrorClass = getClassIfDefined("scala.reflect.api.Mirror") // defined in scala-reflect.jar, so we need to be careful @@ -545,7 +507,6 @@ trait Definitions extends api.StandardDefinitions { lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl] lazy val StringContextClass = requiredClass[scala.StringContext] - def StringContext_f = getMemberMethod(StringContextClass, nme.f) lazy val QuasiquoteClass = if (ApiUniverseClass != NoSymbol) getMember(ApiUniverseClass, tpnme.Quasiquote) else NoSymbol lazy val QuasiquoteClass_api = if (QuasiquoteClass != NoSymbol) getMember(QuasiquoteClass, tpnme.api) else NoSymbol @@ -558,7 +519,6 @@ trait Definitions extends api.StandardDefinitions { // Option classes lazy val OptionClass: ClassSymbol = requiredClass[Option[_]] lazy val OptionModule: ModuleSymbol = requiredModule[scala.Option.type] - lazy val Option_apply = getMemberMethod(OptionModule, nme.apply) lazy val SomeClass: ClassSymbol = requiredClass[Some[_]] lazy val NoneModule: ModuleSymbol = requiredModule[scala.None.type] lazy val SomeModule: ModuleSymbol = requiredModule[scala.Some.type] @@ -566,10 +526,6 @@ trait Definitions extends api.StandardDefinitions { def compilerTypeFromTag(tt: ApiUniverse # WeakTypeTag[_]): Type = tt.in(rootMirror).tpe def compilerSymbolFromTag(tt: ApiUniverse # WeakTypeTag[_]): Symbol = tt.in(rootMirror).tpe.typeSymbol - // The given symbol represents either String.+ or StringAdd.+ - def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+ - def isArrowAssoc(sym: Symbol) = sym.owner == ArrowAssocClass - // The given symbol is a method with the right name and signature to be a runnable java program. def isJavaMainMethod(sym: Symbol) = (sym.name == nme.main) && (sym.info match { case MethodType(p :: Nil, restpe) => isArrayOfSymbol(p.tpe, StringClass) && restpe.typeSymbol == UnitClass @@ -590,6 +546,9 @@ trait Definitions extends api.StandardDefinitions { else appliedType(apply(arity), args ++ others: _*) } } + // would be created synthetically for the default args. We call all objects in this method from the generated code + // in JavaUniverseForce, so it is clearer to define this explicitly define this in source. + object VarArityClass val MaxTupleArity, MaxProductArity, MaxFunctionArity = 22 @@ -1083,9 +1042,6 @@ trait Definitions extends api.StandardDefinitions { lazy val BoxedFloatClass = requiredClass[java.lang.Float] lazy val BoxedDoubleClass = requiredClass[java.lang.Double] - lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean) - lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber) - lazy val BoxedUnitClass = requiredClass[scala.runtime.BoxedUnit] lazy val BoxedUnitModule = getRequiredModule("scala.runtime.BoxedUnit") def BoxedUnit_UNIT = getMemberValue(BoxedUnitModule, nme.UNIT) @@ -1143,14 +1099,6 @@ trait Definitions extends api.StandardDefinitions { // Language features lazy val languageFeatureModule = getRequiredModule("scala.languageFeature") - lazy val experimentalModule = getMemberModule(languageFeatureModule, nme.experimental) - lazy val MacrosFeature = getLanguageFeature("macros", experimentalModule) - lazy val DynamicsFeature = getLanguageFeature("dynamics") - lazy val PostfixOpsFeature = getLanguageFeature("postfixOps") - lazy val ReflectiveCallsFeature = getLanguageFeature("reflectiveCalls") - lazy val ImplicitConversionsFeature = getLanguageFeature("implicitConversions") - lazy val HigherKindsFeature = getLanguageFeature("higherKinds") - lazy val ExistentialsFeature = getLanguageFeature("existentials") def isMetaAnnotation(sym: Symbol): Boolean = metaAnnotations(sym) || ( // Trying to allow for deprecated locations @@ -1291,9 +1239,6 @@ trait Definitions extends api.StandardDefinitions { newPolyMethod(1, owner, name, flags)(tparams => (Some(Nil), createFn(tparams.head))) } - lazy val isUnbox = unboxMethod.values.toSet[Symbol] - lazy val isBox = boxMethod.values.toSet[Symbol] - /** Is symbol a phantom class for which no runtime representation exists? */ lazy val isPhantomClass = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass) /** Lists core classes that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */ @@ -1413,16 +1358,97 @@ 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` */ + /** Efficient access to member symbols which must be looked up each run. Access via `currentRun.runDefinitions` */ final class RunDefinitions { + lazy val StringAdd_+ = getMemberMethod(StringAddClass, nme.PLUS) + + // The given symbol represents either String.+ or StringAdd.+ + def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+ + + lazy val StringContext_f = getMemberMethod(StringContextClass, nme.f) + + lazy val ArrowAssocClass = getMemberClass(PredefModule, TypeName("ArrowAssoc")) // SI-5731 + def isArrowAssoc(sym: Symbol) = sym.owner == ArrowAssocClass + + lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean) + lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber) + + private def valueClassCompanion(name: TermName): ModuleSymbol = { + getMember(ScalaPackageClass, name) match { + case x: ModuleSymbol => x + case _ => catastrophicFailure() + } + } + + private def valueCompanionMember(className: Name, methodName: TermName): TermSymbol = + getMemberMethod(valueClassCompanion(className.toTermName).moduleClass, methodName) + + lazy val boxMethod = classesMap(x => valueCompanionMember(x, nme.box)) + lazy val unboxMethod = classesMap(x => valueCompanionMember(x, nme.unbox)) + lazy val isUnbox = unboxMethod.values.toSet[Symbol] + lazy val isBox = boxMethod.values.toSet[Symbol] + + lazy val Option_apply = getMemberMethod(OptionModule, nme.apply) + lazy val List_apply = DefinitionsClass.this.List_apply + + /** + * Is the given symbol `List.apply`? + * To to avoid bootstrapping cycles, this return false if the given symbol or List itself is not initialized. + */ + def isListApply(sym: Symbol) = sym.isInitialized && ListModule.hasCompleteInfo && sym == List_apply + def isPredefClassOf(sym: Symbol) = if (PredefModule.hasCompleteInfo) sym == Predef_classOf else isPredefMemberNamed(sym, nme.classOf) + 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 Predef_conforms = getMemberMethod(PredefModule, nme.conforms) + lazy val Predef_classOf = getMemberMethod(PredefModule, nme.classOf) + lazy val Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly) + lazy val Predef_wrapRefArray = getMemberMethod(PredefModule, nme.wrapRefArray) + lazy val Predef_??? = DefinitionsClass.this.Predef_??? + + lazy val arrayApplyMethod = getMemberMethod(ScalaRunTimeModule, nme.array_apply) + lazy val arrayUpdateMethod = getMemberMethod(ScalaRunTimeModule, nme.array_update) + lazy val arrayLengthMethod = getMemberMethod(ScalaRunTimeModule, nme.array_length) + lazy val arrayCloneMethod = getMemberMethod(ScalaRunTimeModule, nme.array_clone) + lazy val ensureAccessibleMethod = getMemberMethod(ScalaRunTimeModule, nme.ensureAccessible) + lazy val arrayClassMethod = getMemberMethod(ScalaRunTimeModule, nme.arrayClass) + lazy val traversableDropMethod = getMemberMethod(ScalaRunTimeModule, nme.drop) + + lazy val GroupOfSpecializable = getMemberClass(SpecializableModule, tpnme.Group) + + lazy val WeakTypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.WeakTypeTag)) + lazy val WeakTypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.WeakTypeTag)) + lazy val TypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.TypeTag)) + lazy val TypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.TypeTag)) + lazy val MacroContextUniverse = DefinitionsClass.this.MacroContextUniverse + + lazy val materializeClassTag = getMemberMethod(ReflectPackage, nme.materializeClassTag) + lazy val materializeWeakTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeWeakTypeTag)) + lazy val materializeTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeTypeTag)) + + lazy val experimentalModule = getMemberModule(languageFeatureModule, nme.experimental) + lazy val MacrosFeature = getLanguageFeature("macros", experimentalModule) + lazy val DynamicsFeature = getLanguageFeature("dynamics") + lazy val PostfixOpsFeature = getLanguageFeature("postfixOps") + lazy val ReflectiveCallsFeature = getLanguageFeature("reflectiveCalls") + lazy val ImplicitConversionsFeature = getLanguageFeature("implicitConversions") + lazy val HigherKindsFeature = getLanguageFeature("higherKinds") + lazy val ExistentialsFeature = getLanguageFeature("existentials") + + lazy val ApiUniverseReify = ApiUniverseClass.map(sym => getMemberMethod(sym, nme.reify)) + + lazy val ReflectRuntimeUniverse = DefinitionsClass.this.ReflectRuntimeUniverse + lazy val ReflectRuntimeCurrentMirror = DefinitionsClass.this.ReflectRuntimeCurrentMirror + + lazy val TreesTreeType = TreesClass.map(sym => getTypeMember(sym, tpnme.Tree)) + object TreeType { def unapply(tpe: Type): Boolean = tpe.typeSymbol.overrideChain contains TreesTreeType } + object SubtreeType { def unapply(tpe: Type): Boolean = tpe.typeSymbol.overrideChain exists (_.tpe <:< TreesTreeType.tpe) } + + object ExprClassOf { def unapply(tp: Type): Option[Type] = elementExtractOption(ExprClass, tp) } lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest) lazy val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass) diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 8386d02b7c..4998580a7d 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -358,6 +358,21 @@ abstract class SymbolTable extends macros.Universe def newMap[K, V]() = recordCache(mutable.HashMap[K, V]()) def newSet[K]() = recordCache(mutable.HashSet[K]()) def newWeakSet[K <: AnyRef]() = recordCache(new WeakHashSet[K]()) + def newGeneric[T](f: => T): () => T = { + val NoCached: T = null.asInstanceOf[T] + var cached: T = NoCached + var cachedRunId = NoRunId + caches += new Clearable { + def clear(): Unit = cached = NoCached + } + () => { + if (currentRunId != cachedRunId || cached == NoCached) { + cached = f + cachedRunId = currentRunId + } + cached + } + } } /** The set of all installed infotransformers. */ diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 8e822ca4f0..7cc5176507 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -60,6 +60,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni val universe: thisUniverse.type = thisUniverse import definitions._ + private[reflect] lazy val runDefinitions = new definitions.RunDefinitions // only one "run" in the reflection universe + import runDefinitions._ override lazy val RootPackage = new RootPackage with SynchronizedTermSymbol override lazy val RootClass = new RootClass with SynchronizedModuleClassSymbol @@ -306,7 +308,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni lazy val bytecodefulObjectMethods = Set[Symbol](Object_clone, Object_equals, Object_finalize, Object_hashCode, Object_toString, Object_notify, Object_notifyAll) ++ ObjectClass.info.member(nme.wait_).asTerm.alternatives.map(_.asMethod) private def isBytecodelessMethod(meth: MethodSymbol): Boolean = { - if (isGetClass(meth) || isStringConcat(meth) || meth.owner.isPrimitiveValueClass || meth == Predef_classOf || meth.isMacro) return true + if (isGetClass(meth) || isStringConcat(meth) || meth.owner.isPrimitiveValueClass || meth == runDefinitions.Predef_classOf || meth.isMacro) return true bytecodelessMethodOwners(meth.owner) && !bytecodefulObjectMethods(meth) } diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 1f1f07c09a..4d69a6673c 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -254,13 +254,9 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.UnqualifiedOwners definitions.PredefModule definitions.SpecializableModule - definitions.GroupOfSpecializable definitions.ScalaRunTimeModule definitions.SymbolModule - definitions.Symbol_apply definitions.StringAddClass - definitions.ArrowAssocClass - definitions.StringAdd_$plus definitions.ScalaNumberClass definitions.TraitSetterAnnotationClass definitions.DelayedInitClass @@ -276,7 +272,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.ByNameParamClass definitions.JavaRepeatedParamClass definitions.RepeatedParamClass - definitions.ExprClassOf definitions.ConsClass definitions.IteratorClass definitions.IterableClass @@ -285,7 +280,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.StringBuilderClass definitions.TraversableClass definitions.ListModule - definitions.List_apply definitions.NilModule definitions.SeqModule definitions.ArrayModule @@ -310,18 +304,10 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.OptManifestClass definitions.NoManifest definitions.TreesClass - definitions.TreesTreeType - definitions.TreeType - definitions.SubtreeType definitions.ExprsClass - definitions.ExprClass definitions.ClassTagModule definitions.ClassTagClass definitions.TypeTagsClass - definitions.WeakTypeTagClass - definitions.WeakTypeTagModule - definitions.TypeTagClass - definitions.TypeTagModule definitions.ApiUniverseClass definitions.JavaUniverseClass definitions.MirrorClass @@ -340,7 +326,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.ScalaLongSignatureAnnotation definitions.OptionClass definitions.OptionModule - definitions.Option_apply definitions.SomeClass definitions.NoneModule definitions.SomeModule @@ -384,8 +369,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.BoxedLongClass definitions.BoxedFloatClass definitions.BoxedDoubleClass - definitions.Boxes_isNumberOrBool - definitions.Boxes_isNumber definitions.BoxedUnitClass definitions.BoxedUnitModule definitions.AnnotationClass @@ -432,18 +415,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.MethodTargetClass definitions.LanguageFeatureAnnot definitions.languageFeatureModule - definitions.experimentalModule - definitions.MacrosFeature - definitions.DynamicsFeature - definitions.PostfixOpsFeature - definitions.ReflectiveCallsFeature - definitions.ImplicitConversionsFeature - definitions.HigherKindsFeature - definitions.ExistentialsFeature definitions.metaAnnotations definitions.AnnotationDefaultAttr - definitions.isUnbox - definitions.isBox definitions.isPhantomClass definitions.syntheticCoreClasses definitions.syntheticCoreMethods @@ -457,8 +430,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.boxedClass definitions.refClass definitions.volatileRefClass - definitions.boxMethod - definitions.unboxMethod definitions.UnitClass definitions.ByteClass definitions.ShortClass @@ -468,9 +439,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.FloatClass definitions.DoubleClass definitions.BooleanClass - definitions.Boolean_and - definitions.Boolean_or - definitions.Boolean_not definitions.UnitTpe definitions.ByteTpe definitions.ShortTpe diff --git a/test/files/presentation/t7678.check b/test/files/presentation/t7678.check new file mode 100644 index 0000000000..f06434b322 --- /dev/null +++ b/test/files/presentation/t7678.check @@ -0,0 +1 @@ +reload: TypeTag.scala diff --git a/test/files/presentation/t7678/Runner.scala b/test/files/presentation/t7678/Runner.scala new file mode 100644 index 0000000000..14d6dc2a70 --- /dev/null +++ b/test/files/presentation/t7678/Runner.scala @@ -0,0 +1,62 @@ +import scala.tools.nsc.interactive.tests._ +import scala.reflect.internal.util._ + +object Test extends InteractiveTest { + + import compiler._, definitions._ + + override def runDefaultTests() { + def resolveTypeTagHyperlink() { + val sym = compiler.askForResponse(() => compiler.currentRun.runDefinitions.TypeTagClass).get.left.get + val r = new Response[Position] + compiler.askLinkPos(sym, new BatchSourceFile("", source), r) + r.get + } + + def checkTypeTagSymbolConsistent() { + compiler.askForResponse { + () => { + val runDefinitions = currentRun.runDefinitions + import runDefinitions._ + assert(TypeTagsClass.map(sym => getMemberClass(sym, tpnme.TypeTag)) == TypeTagClass) + assert(TypeTagsClass.map(sym => getMemberClass(sym, tpnme.WeakTypeTag)) == WeakTypeTagClass) + assert(TypeTagsClass.map(sym => getMemberModule(sym, nme.WeakTypeTag)) == WeakTypeTagModule) + assert(getMemberMethod(ReflectPackage, nme.materializeClassTag) == materializeClassTag) + assert(ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeWeakTypeTag)) == materializeWeakTypeTag) + assert(ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeTypeTag)) == materializeTypeTag) + () + } + }.get match { + case Right(t) => t.printStackTrace + case Left(_) => + } + } + resolveTypeTagHyperlink() + // The presentation compiler loads TypeTags from source; we'll get new symbols for its members. + // Need to make sure we didn't cache the old ones in Definitions. + checkTypeTagSymbolConsistent() + } + + def source = + """ + |package scala + |package reflect + |package api + | + |trait TypeTags { self: Universe => + | import definitions._ + | + | @annotation.implicitNotFound(msg = "No WeakTypeTag available for ${T}") + | trait WeakTypeTag[T] extends Equals with Serializable { + | val mirror: Mirror + | def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # WeakTypeTag[T] + | def tpe: Type + | } + | object WeakTypeTag + | + | trait TypeTag[T] extends WeakTypeTag[T] with Equals with Serializable { + | } + | object TypeTag + | + """.stripMargin +} diff --git a/test/files/presentation/t7678/src/TypeTag.scala b/test/files/presentation/t7678/src/TypeTag.scala new file mode 100644 index 0000000000..0b222f8851 --- /dev/null +++ b/test/files/presentation/t7678/src/TypeTag.scala @@ -0,0 +1,9 @@ +package test + +object Test { + import scala.reflect.runtime.{ universe => ru } + def getTypeTag(implicit tag: ru.TypeTag[Int] ) = () + locally { + getTypeTag/*?*/ + } +} |