summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-09-16 08:27:10 -0700
committerEugene Burmako <xeno.by@gmail.com>2012-09-16 08:27:10 -0700
commit4d8d2e52361586f32a1a52b9a78728aca0d5bf0c (patch)
tree3a227e84d0c795bd3cb81bdcc8a9d98fc675054e
parent24580ac84242679619d27f20258078dd012c120a (diff)
parent05be78101c694974ae964bb26b48c1a0b5a372c1 (diff)
downloadscala-4d8d2e52361586f32a1a52b9a78728aca0d5bf0c.tar.gz
scala-4d8d2e52361586f32a1a52b9a78728aca0d5bf0c.tar.bz2
scala-4d8d2e52361586f32a1a52b9a78728aca0d5bf0c.zip
Merge pull request #1311 from scalamacros/topic/magic
deals with magic
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/library/scala/StringContext.scala3
-rw-r--r--src/library/scala/reflect/base/Universe.scala3
-rw-r--r--src/library/scala/reflect/macros/internal/package.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala22
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala92
-rw-r--r--src/reflect/scala/reflect/runtime/package.scala3
8 files changed, 76 insertions, 55 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 5ca4712cd2..144cc841b4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -717,7 +717,8 @@ trait ContextErrors {
Some(EOL + stackTraceString(realex))
}
} catch {
- // if the magic above goes boom, just fall back to uninformative, but better than nothing, getMessage
+ // the code above tries various tricks to detect the relevant portion of the stack trace
+ // if these tricks fail, just fall back to uninformative, but better than nothing, getMessage
case NonFatal(ex) =>
macroLogVerbose("got an exception when processing a macro generated exception\n" +
"offender = " + stackTraceString(realex) + "\n" +
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index e3f0756b6c..dd7f26861f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1334,7 +1334,7 @@ trait Implicits {
def wrapResult(tree: Tree): SearchResult =
if (tree == EmptyTree) SearchFailure else new SearchResult(tree, EmptyTreeTypeSubstituter)
- /** Materializes implicits of magic types (currently, manifests and tags).
+ /** Materializes implicits of predefined types (currently, manifests and tags).
* Will be replaced by implicit macros once we fix them.
*/
private def materializeImplicit(pt: Type): SearchResult =
diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala
index 453f29d9e6..1201b1accd 100644
--- a/src/library/scala/StringContext.scala
+++ b/src/library/scala/StringContext.scala
@@ -96,7 +96,8 @@ case class StringContext(parts: String*) {
* string literally. This is achieved by replacing each such occurrence by the
* format specifier `%%`.
*/
- // The implementation is magically hardwired into `scala.tools.reflect.MacroImplementations.macro_StringInterpolation_f`
+ // The implementation is hardwired to `scala.tools.reflect.MacroImplementations.macro_StringInterpolation_f`
+ // Using the mechanism implemented in `scala.tools.reflect.FastTrack`
def f(args: Any*): String = ??? // macro
}
diff --git a/src/library/scala/reflect/base/Universe.scala b/src/library/scala/reflect/base/Universe.scala
index 11290401ec..36b85ca714 100644
--- a/src/library/scala/reflect/base/Universe.scala
+++ b/src/library/scala/reflect/base/Universe.scala
@@ -61,6 +61,7 @@ abstract class Universe extends Symbols
* * Since reified trees can be compiled outside of the scope they've been created in,
* special measures are taken to ensure that all members accessed in the reifee remain visible
*/
- // implementation is magically hardwired to `scala.reflect.reify.Taggers`
+ // implementation is hardwired to `scala.reflect.reify.Taggers`
+ // using the mechanism implemented in `scala.tools.reflect.FastTrack`
def reify[T](expr: T): Expr[T] = ??? // macro
} \ No newline at end of file
diff --git a/src/library/scala/reflect/macros/internal/package.scala b/src/library/scala/reflect/macros/internal/package.scala
index aca2b765f1..8457285752 100644
--- a/src/library/scala/reflect/macros/internal/package.scala
+++ b/src/library/scala/reflect/macros/internal/package.scala
@@ -4,7 +4,8 @@ import scala.reflect.base.{Universe => BaseUniverse}
import scala.reflect.ClassTag
// anchors for materialization macros emitted during tag materialization in Implicits.scala
-// implementation is magically hardwired into `scala.reflect.reify.Taggers`
+// implementation is hardwired into `scala.reflect.reify.Taggers`
+// using the mechanism implemented in `scala.tools.reflect.FastTrack`
// todo. once we have implicit macros for tag generation, we can remove these anchors
package object internal {
private[scala] def materializeClassTag[T](u: BaseUniverse): ClassTag[T] = ??? // macro
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 6d7aa19738..4a5ace4248 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -1116,7 +1116,8 @@ trait Definitions extends api.StandardDefinitions {
/** Is symbol a phantom class for which no runtime representation exists? */
lazy val isPhantomClass = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass)
- lazy val magicSymbols = List(
+ /** Lists core classes that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
+ lazy val syntheticCoreClasses = List(
AnnotationDefaultAttr, // #2264
RepeatedParamClass,
JavaRepeatedParamClass,
@@ -1127,7 +1128,10 @@ trait Definitions extends api.StandardDefinitions {
NullClass,
NothingClass,
SingletonClass,
- EqualsPatternClass,
+ EqualsPatternClass
+ )
+ /** Lists core methods that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
+ lazy val syntheticCoreMethods = List(
Any_==,
Any_!=,
Any_equals,
@@ -1145,10 +1149,19 @@ trait Definitions extends api.StandardDefinitions {
Object_synchronized,
Object_isInstanceOf,
Object_asInstanceOf,
- String_+,
+ String_+
+ )
+ /** Lists core classes that do have underlying bytecode, but are adjusted on-the-fly in every reflection universe */
+ lazy val hijackedCoreClasses = List(
ComparableClass,
JavaSerializableClass
)
+ /** Lists symbols that are synthesized or hijacked by the compiler.
+ *
+ * Such symbols either don't have any underlying bytecode at all ("synthesized")
+ * or get loaded from bytecode but have their metadata adjusted ("hijacked").
+ */
+ lazy val symbolsNotPresentInBytecode = syntheticCoreClasses ++ syntheticCoreMethods ++ hijackedCoreClasses
/** Is the symbol that of a parent which is added during parsing? */
lazy val isPossibleSyntheticParent = ProductClass.toSet[Symbol] + ProductRootClass + SerializableClass
@@ -1212,7 +1225,8 @@ trait Definitions extends api.StandardDefinitions {
def init() {
if (isInitialized) return
- val forced = magicSymbols // force initialization of every symbol that is entered as a side effect
+ // force initialization of every symbol that is synthesized or hijacked by the compiler
+ val forced = symbolsNotPresentInBytecode
isInitialized = true
} //init
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index be2661149a..e56441b672 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -23,7 +23,7 @@ import scala.language.existentials
import scala.runtime.{ScalaRunTime, BoxesRunTime}
import scala.reflect.internal.util.Collections._
-trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: SymbolTable =>
+trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUniverse: SymbolTable =>
private lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]()
@@ -62,9 +62,9 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
class JavaMirror(owner: Symbol,
/** Class loader that is a mastermind behind the reflexive mirror */
val classLoader: ClassLoader
- ) extends Roots(owner) with super.JavaMirror { wholemirror =>
+ ) extends Roots(owner) with super.JavaMirror { thisMirror =>
- val universe: self.type = self
+ val universe: thisUniverse.type = thisUniverse
import definitions._
@@ -190,7 +190,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
private class JavaInstanceMirror[T: ClassTag](val instance: T)
extends InstanceMirror {
- def symbol = wholemirror.classSymbol(preciseClass(instance))
+ def symbol = thisMirror.classSymbol(preciseClass(instance))
def reflectField(field: TermSymbol): FieldMirror = {
checkMemberOf(field, symbol)
if ((field.isMethod && !field.isAccessor) || field.isModule) ErrorNotField(field)
@@ -265,14 +265,13 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
// the "symbol == Any_getClass || symbol == Object_getClass" test doesn't cut it
// because both AnyVal and its primitive descendants define their own getClass methods
private def isGetClass(meth: MethodSymbol) = meth.name.toString == "getClass" && meth.params.flatten.isEmpty
- private def isMagicPrimitiveMethod(meth: MethodSymbol) = meth.owner.isPrimitiveValueClass
- private def isStringConcat(meth: MethodSymbol) = meth == String_+ || (isMagicPrimitiveMethod(meth) && meth.returnType =:= StringClass.toType)
- lazy val magicMethodOwners = Set[Symbol](AnyClass, AnyValClass, AnyRefClass, ObjectClass, ArrayClass) ++ ScalaPrimitiveValueClasses
- lazy val nonMagicObjectMethods = 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 isMagicMethod(meth: MethodSymbol): Boolean = {
- if (isGetClass(meth) || isStringConcat(meth) || isMagicPrimitiveMethod(meth) || meth == Predef_classOf || meth.isTermMacro) return true
- magicMethodOwners(meth.owner) && !nonMagicObjectMethods(meth)
+ private def isStringConcat(meth: MethodSymbol) = meth == String_+ || (meth.owner.isPrimitiveValueClass && meth.returnType =:= StringClass.toType)
+ lazy val bytecodelessMethodOwners = Set[Symbol](AnyClass, AnyValClass, AnyRefClass, ObjectClass, ArrayClass) ++ ScalaPrimitiveValueClasses
+ 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.isTermMacro) return true
+ bytecodelessMethodOwners(meth.owner) && !bytecodefulObjectMethods(meth)
}
// unlike other mirrors, method mirrors are created by a factory
@@ -280,7 +279,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
// therefore we move special cases into separate subclasses
// rather than have them on a hot path them in a unified implementation of the `apply` method
private def mkJavaMethodMirror[T: ClassTag](receiver: T, symbol: MethodSymbol): JavaMethodMirror = {
- if (isMagicMethod(symbol)) new JavaMagicMethodMirror(receiver, symbol)
+ if (isBytecodelessMethod(symbol)) new JavaBytecodelessMethodMirror(receiver, symbol)
else if (symbol.params.flatten exists (p => isByNameParamType(p.info))) new JavaByNameMethodMirror(receiver, symbol)
else new JavaVanillaMethodMirror(receiver, symbol)
}
@@ -315,11 +314,11 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
}
}
- private class JavaMagicMethodMirror[T: ClassTag](val receiver: T, symbol: MethodSymbol)
+ private class JavaBytecodelessMethodMirror[T: ClassTag](val receiver: T, symbol: MethodSymbol)
extends JavaMethodMirror(symbol) {
def apply(args: Any*): Any = {
// checking type conformance is too much of a hassle, so we don't do it here
- // actually it's not even necessary, because we manually dispatch arguments to magic methods below
+ // actually it's not even necessary, because we manually dispatch arguments below
val params = symbol.paramss.flatten
val perfectMatch = args.length == params.length
// todo. this doesn't account for multiple vararg parameter lists
@@ -337,36 +336,36 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
def objArgs = args.asInstanceOf[Seq[AnyRef]]
def fail(msg: String) = throw new ScalaReflectionException(msg + ", it cannot be invoked with mirrors")
- def invokeMagicPrimitiveMethod = {
+ def invokePrimitiveMethod = {
val jmeths = classOf[BoxesRunTime].getDeclaredMethods.filter(_.getName == nme.primitiveMethodName(symbol.name).toString)
assert(jmeths.length == 1, jmeths.toList)
jinvoke(jmeths.head, null, objReceiver +: objArgs)
}
symbol match {
- case Any_== | Object_== => ScalaRunTime.inlinedEquals(objReceiver, objArg0)
- case Any_!= | Object_!= => !ScalaRunTime.inlinedEquals(objReceiver, objArg0)
- case Any_## | Object_## => ScalaRunTime.hash(objReceiver)
- case Any_equals => receiver.equals(objArg0)
- case Any_hashCode => receiver.hashCode
- case Any_toString => receiver.toString
- case Object_eq => objReceiver eq objArg0
- case Object_ne => objReceiver ne objArg0
- case Object_synchronized => objReceiver.synchronized(objArg0)
- case sym if isGetClass(sym) => preciseClass(receiver)
- case Any_asInstanceOf => fail("Any.asInstanceOf requires a type argument")
- case Any_isInstanceOf => fail("Any.isInstanceOf requires a type argument")
- case Object_asInstanceOf => fail("AnyRef.$asInstanceOf is an internal method")
- case Object_isInstanceOf => fail("AnyRef.$isInstanceOf is an internal method")
- case Array_length => ScalaRunTime.array_length(objReceiver)
- case Array_apply => ScalaRunTime.array_apply(objReceiver, args(0).asInstanceOf[Int])
- case Array_update => ScalaRunTime.array_update(objReceiver, args(0).asInstanceOf[Int], args(1))
- case Array_clone => ScalaRunTime.array_clone(objReceiver)
- case sym if isStringConcat(sym) => receiver.toString + objArg0
- case sym if isMagicPrimitiveMethod(sym) => invokeMagicPrimitiveMethod
- case sym if sym == Predef_classOf => fail("Predef.classOf is a compile-time function")
- case sym if sym.isTermMacro => fail(s"${symbol.fullName} is a macro, i.e. a compile-time function")
- case _ => assert(false, this)
+ case Any_== | Object_== => ScalaRunTime.inlinedEquals(objReceiver, objArg0)
+ case Any_!= | Object_!= => !ScalaRunTime.inlinedEquals(objReceiver, objArg0)
+ case Any_## | Object_## => ScalaRunTime.hash(objReceiver)
+ case Any_equals => receiver.equals(objArg0)
+ case Any_hashCode => receiver.hashCode
+ case Any_toString => receiver.toString
+ case Object_eq => objReceiver eq objArg0
+ case Object_ne => objReceiver ne objArg0
+ case Object_synchronized => objReceiver.synchronized(objArg0)
+ case sym if isGetClass(sym) => preciseClass(receiver)
+ case Any_asInstanceOf => fail("Any.asInstanceOf requires a type argument")
+ case Any_isInstanceOf => fail("Any.isInstanceOf requires a type argument")
+ case Object_asInstanceOf => fail("AnyRef.$asInstanceOf is an internal method")
+ case Object_isInstanceOf => fail("AnyRef.$isInstanceOf is an internal method")
+ case Array_length => ScalaRunTime.array_length(objReceiver)
+ case Array_apply => ScalaRunTime.array_apply(objReceiver, args(0).asInstanceOf[Int])
+ case Array_update => ScalaRunTime.array_update(objReceiver, args(0).asInstanceOf[Int], args(1))
+ case Array_clone => ScalaRunTime.array_clone(objReceiver)
+ case sym if isStringConcat(sym) => receiver.toString + objArg0
+ case sym if sym.owner.isPrimitiveValueClass => invokePrimitiveMethod
+ case sym if sym == Predef_classOf => fail("Predef.classOf is a compile-time function")
+ case sym if sym.isTermMacro => fail(s"${symbol.fullName} is a macro, i.e. a compile-time function")
+ case _ => assert(false, this)
}
}
}
@@ -469,7 +468,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
}
private object unpickler extends UnPickler {
- val global: self.type = self
+ val global: thisUniverse.type = thisUniverse
}
/** how connected????
@@ -616,7 +615,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
completeRest()
}
- def completeRest(): Unit = self.synchronized {
+ def completeRest(): Unit = thisUniverse.synchronized {
val tparams = clazz.rawInfo.typeParams
val parents = try {
@@ -1200,9 +1199,9 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
mirrors(rootToLoader getOrElseUpdate(root, findLoader)).get.get
}
- private lazy val magicClasses: Map[(String, Name), Symbol] = {
+ private lazy val syntheticCoreClasses: Map[(String, Name), Symbol] = {
def mapEntry(sym: Symbol): ((String, Name), Symbol) = (sym.owner.fullName, sym.name) -> sym
- Map() ++ (definitions.magicSymbols filter (_.isType) map mapEntry)
+ Map() ++ (definitions.syntheticCoreClasses map mapEntry)
}
/** 1. If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package
@@ -1221,9 +1220,12 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
if (name.isTermName && !owner.isEmptyPackageClass)
return mirror.makeScalaPackage(
if (owner.isRootSymbol) name.toString else owner.fullName+"."+name)
- magicClasses get (owner.fullName, name) match {
+ syntheticCoreClasses get (owner.fullName, name) match {
case Some(tsym) =>
- owner.info.decls enter tsym
+ // synthetic core classes are only present in root mirrors
+ // because Definitions.scala, which initializes and enters them, only affects rootMirror
+ // therefore we need to enter them manually for non-root mirrors
+ if (mirror ne thisUniverse.rootMirror) owner.info.decls enter tsym
return tsym
case None =>
}
diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala
index d325cf6a16..7b9f69e657 100644
--- a/src/reflect/scala/reflect/runtime/package.scala
+++ b/src/reflect/scala/reflect/runtime/package.scala
@@ -5,7 +5,8 @@ package object runtime {
// type is api.JavaUniverse because we only want to expose the `scala.reflect.api.*` subset of reflection
lazy val universe: api.JavaUniverse = new runtime.JavaUniverse
- // implementation magically hardwired to the `currentMirror` method below
+ // implementation hardwired to the `currentMirror` method below
+ // using the mechanism implemented in `scala.tools.reflect.FastTrack`
def currentMirror: universe.Mirror = ??? // macro
}