summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/reflect')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala16
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala42
-rw-r--r--src/compiler/scala/reflect/internal/TreeInfo.scala6
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala21
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Reifiers.scala123
-rw-r--r--src/compiler/scala/reflect/reify/Errors.scala8
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala38
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Symbols.scala2
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Types.scala18
-rw-r--r--src/compiler/scala/reflect/reify/package.scala38
10 files changed, 138 insertions, 174 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 24fc7c7cc4..28905dd240 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -380,6 +380,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
def arrayCloneMethod = getMember(ScalaRunTimeModule, nme.array_clone)
def ensureAccessibleMethod = getMember(ScalaRunTimeModule, nme.ensureAccessible)
def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements)
+ def arrayClassMethod = getMember(ScalaRunTimeModule, nme.arrayClass)
+ def arrayElementClassMethod = getMember(ScalaRunTimeModule, nme.arrayElementClass)
// classes with special meanings
lazy val StringAddClass = getRequiredClass("scala.runtime.StringAdd")
@@ -409,7 +411,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.tpe)
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe))
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.tpe))
-
+
lazy val MarkerCPSTypes = getClassIfDefined("scala.util.continuations.cpsParam")
def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass
@@ -479,7 +481,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
// scala.reflect
lazy val ReflectPackageClass = getMember(ScalaPackageClass, nme.reflect)
lazy val ReflectPackage = getPackageObject("scala.reflect")
- def Reflect_mirror = getMember(ReflectPackage, nme.mirror)
+ def ReflectMirror = getMember(ReflectPackage, nme.mirror)
+ // [Eugene] is this a good place for ReflectMirrorPrefix?
+ def ReflectMirrorPrefix = gen.mkAttributedRef(ReflectMirror) setType singleType(ReflectMirror.owner.thisPrefix, ReflectMirror)
lazy val ExprClass = getMember(getRequiredClass("scala.reflect.api.Exprs"), tpnme.Expr)
def ExprTree = getMemberClass(ExprClass, nme.tree)
@@ -488,6 +492,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
def ExprValue = getMember(ExprClass, nme.value)
lazy val ExprModule = getMember(getRequiredClass("scala.reflect.api.Exprs"), nme.Expr)
+ lazy val ArrayTagClass = requiredClass[scala.reflect.ArrayTag[_]]
+ lazy val ErasureTagClass = requiredClass[scala.reflect.ErasureTag[_]]
lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]]
lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]]
lazy val TypeTagsClass = requiredClass[scala.reflect.api.TypeTags]
@@ -496,7 +502,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val ConcreteTypeTagClass = getMemberClass(TypeTagsClass, tpnme.ConcreteTypeTag)
lazy val ConcreteTypeTagModule = getMemberModule(TypeTagsClass, nme.ConcreteTypeTag)
- def ClassTagErasure = getMemberMethod(ClassTagClass, nme.erasure)
+ def ArrayTagWrap = getMemberMethod(ArrayTagClass, nme.wrap)
+ def ArrayTagNewArray = getMemberMethod(ArrayTagClass, nme.newArray)
+ def ErasureTagErasure = getMemberMethod(ErasureTagClass, nme.erasure)
def ClassTagTpe = getMemberMethod(ClassTagClass, nme.tpe)
def TypeTagTpe = getMemberMethod(TypeTagClass, nme.tpe)
@@ -507,6 +515,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
def MacroContextReify = getMember(MacroContextClass, nme.reify)
lazy val MacroImplAnnotation = getRequiredClass("scala.reflect.makro.internal.macroImpl")
lazy val MacroInternalPackage = getPackageObject("scala.reflect.makro.internal")
+ def MacroInternal_materializeArrayTag = getMemberMethod(MacroInternalPackage, nme.materializeArrayTag)
+ def MacroInternal_materializeErasureTag = getMemberMethod(MacroInternalPackage, nme.materializeErasureTag)
def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag)
def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag)
def MacroInternal_materializeConcreteTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeConcreteTypeTag)
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index 54be83c98f..4ce6afe1f3 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -562,6 +562,8 @@ trait StdNames {
val applyOrElse: NameType = "applyOrElse"
val args : NameType = "args"
val argv : NameType = "argv"
+ val arrayClass: NameType = "arrayClass"
+ val arrayElementClass: NameType = "arrayElementClass"
val arrayValue: NameType = "arrayValue"
val array_apply : NameType = "array_apply"
val array_clone : NameType = "array_clone"
@@ -628,9 +630,11 @@ trait StdNames {
val main: NameType = "main"
val manifest: NameType = "manifest"
val map: NameType = "map"
+ val materializeArrayTag: NameType = "materializeArrayTag"
val materializeClassTag: NameType = "materializeClassTag"
- val materializeTypeTag: NameType = "materializeTypeTag"
val materializeConcreteTypeTag: NameType = "materializeConcreteTypeTag"
+ val materializeErasureTag: NameType= "materializeErasureTag"
+ val materializeTypeTag: NameType = "materializeTypeTag"
val mirror : NameType = "mirror"
val moduleClass : NameType = "moduleClass"
val name: NameType = "name"
@@ -813,10 +817,11 @@ trait StdNames {
val ROOTPKG: TermName = "_root_"
val EQEQ_LOCAL_VAR: TermName = "eqEqTemp$"
- def getCause = sn.GetCause
- def getClass_ = sn.GetClass
- def getMethod_ = sn.GetMethod
- def invoke_ = sn.Invoke
+ def getCause = sn.GetCause
+ def getClass_ = sn.GetClass
+ def getComponentType = sn.GetComponentType
+ def getMethod_ = sn.GetMethod
+ def invoke_ = sn.Invoke
val ADD = encode("+")
val AND = encode("&")
@@ -1005,6 +1010,7 @@ trait StdNames {
val ForName : TermName
val GetCause : TermName
val GetClass : TermName
+ val GetComponentType : TermName
val GetMethod : TermName
val Invoke : TermName
val JavaLang : TermName
@@ -1090,12 +1096,13 @@ trait StdNames {
final val Throwable: TypeName = "java.lang.Throwable"
final val ValueType: TypeName = tpnme.NO_NAME
- final val ForName: TermName = newTermName("forName")
- final val GetCause: TermName = newTermName("getCause")
- final val GetClass: TermName = newTermName("getClass")
- final val GetMethod: TermName = newTermName("getMethod")
- final val Invoke: TermName = newTermName("invoke")
- final val JavaLang: TermName = newTermName("java.lang")
+ final val ForName: TermName = newTermName("forName")
+ final val GetCause: TermName = newTermName("getCause")
+ final val GetClass: TermName = newTermName("getClass")
+ final val GetComponentType: TermName = newTermName("getComponentType")
+ final val GetMethod: TermName = newTermName("getMethod")
+ final val Invoke: TermName = newTermName("invoke")
+ final val JavaLang: TermName = newTermName("java.lang")
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> BoxedBoolean,
@@ -1127,12 +1134,13 @@ trait StdNames {
final val Throwable: TypeName = "System.Exception"
final val ValueType: TypeName = "System.ValueType"
- final val ForName: TermName = newTermName("GetType")
- final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */
- final val GetClass: TermName = newTermName("GetType")
- final val GetMethod: TermName = newTermName("GetMethod")
- final val Invoke: TermName = newTermName("Invoke")
- final val JavaLang: TermName = newTermName("System")
+ final val ForName: TermName = newTermName("GetType")
+ final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */
+ final val GetClass: TermName = newTermName("GetType")
+ final val GetComponentType: TermName = newTermName("GetElementType")
+ final val GetMethod: TermName = newTermName("GetMethod")
+ final val Invoke: TermName = newTermName("Invoke")
+ final val JavaLang: TermName = newTermName("System")
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> "System.Boolean",
diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala
index 937b3ea5d6..48dfe8bcfc 100644
--- a/src/compiler/scala/reflect/internal/TreeInfo.scala
+++ b/src/compiler/scala/reflect/internal/TreeInfo.scala
@@ -676,14 +676,14 @@ abstract class TreeInfo {
case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(flags: Long)), Literal(Constant(origin: String)))))
if mrRef1.name == nme.MIRROR_SHORT && (newFreeType == newFreeTypeMethod.name || newFreeType == newFreeExistentialMethod.name) =>
value match {
- case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null))))
+ case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null)), _))
if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply =>
Some(mrRef1, name, binding, flags, origin)
- case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null))))
+ case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null)), _))
if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag =>
Some(mrRef1, name, binding, flags, origin)
case _ =>
- throw new Error("unsupported free type def: " + showRaw(tree))
+ throw new Error("unsupported free type def: %s%n%s".format(value, showRaw(value)))
}
case _ =>
None
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 32b09eddeb..815a5c0710 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -264,7 +264,23 @@ trait Types extends api.Types { self: SymbolTable =>
def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name)
def declarations = decls
def typeArguments = typeArgs
- def erasure = transformedType(this)
+ def erasure = this match {
+ case ConstantType(value) => widen.erasure // [Eugene to Martin] constant types are unaffected by erasure. weird.
+ case _ =>
+ var result = transformedType(this)
+ result = result.normalize match { // necessary to deal with erasures of HK types, typeConstructor won't work
+ case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result
+ case _ => result
+ }
+ // [Eugene] erasure screws up all ThisTypes for modules into PackageTypeRefs
+ // we need to unscrew them, or certain typechecks will fail mysteriously
+ // http://groups.google.com/group/scala-internals/browse_thread/thread/6d3277ae21b6d581
+ result = result.map(tpe => tpe match {
+ case tpe: PackageTypeRef => ThisType(tpe.sym)
+ case _ => tpe
+ })
+ result
+ }
def substituteTypes(from: List[Symbol], to: List[Type]): Type = subst(from, to)
// [Eugene] to be discussed and refactored
@@ -1342,7 +1358,8 @@ trait Types extends api.Types { self: SymbolTable =>
if (period != currentPeriod) {
tpe.underlyingPeriod = currentPeriod
if (!isValid(period)) {
- tpe.underlyingCache = tpe.pre.memberType(tpe.sym).resultType;
+ // [Eugene to Paul] needs review
+ tpe.underlyingCache = if (tpe.sym == NoSymbol) ThisType(RootClass) else tpe.pre.memberType(tpe.sym).resultType;
assert(tpe.underlyingCache ne tpe, tpe)
}
}
diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
index d9a89d0e6d..1c5af4b752 100644
--- a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
@@ -12,124 +12,23 @@ trait Reifiers {
import mirror._
import definitions._
- private lazy val ClassTagModule = ClassTagClass.companionSymbol
+ lazy val reflectMirrorPrefix: Tree = ReflectMirrorPrefix
- // [Eugene] imho this logic should be moved into `erasure`
- private def calculateTagErasure(tpe: Type) = tpe match {
- case tpe if tpe.typeSymbol.isDerivedValueClass => tpe // [Eugene to Martin] is this correct?
- case ConstantType(value) => tpe.widen.erasure
- case _ =>
- // [Eugene] magikz. needs review
- // necessary to deal with erasures of HK types, typeConstructor won't work
- tpe.erasure.normalize match {
- // we don't want undets in the result
- case PolyType(undets, underlying) => existentialAbstraction(undets, underlying)
- case result => result
- }
- }
- private def classTagFromArgument(tpe: Type, arg: Tree) = {
- gen.mkMethodCall(ClassTagModule, nme.apply, List(tpe), List(arg))
- // val factory = TypeApply(Select(Ident(ClassTagModule), nme.apply), List(TypeTree(tpe)))
- // Apply(factory, List(typeArg))
- }
- private def classTagFromErasure(tpe: Type) = {
- val erasure = calculateTagErasure(tpe)
- classTagFromArgument(tpe, gen.mkNullaryCall(Predef_classOf, List(erasure)))
- // val targ = TypeApply(Select(Ident(PredefModule), nme.classOf), List(TypeTree(erasure)))
- // classTagFromArgument(tpe, targ)
- }
- private def typetagIsSynthetic(tree: Tree) = tree match {
- case Block(_, _) => true
- case _ => tree exists (_ hasSymbolWhich Set(TypeTagModule, ConcreteTypeTagModule))
+ def reifyTree(prefix: Tree, tree: Tree): Tree = {
+ val result = scala.reflect.reify.`package`.reifyTree(mirror)(callsiteTyper, prefix, tree)
+ logFreeVars(enclosingPosition, result)
+ result
}
- lazy val reflectMirrorPrefix: Tree = {
- // [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure?
- val prefix: Tree = Select(Select(Ident(definitions.ScalaPackage), newTermName("reflect")), newTermName("mirror"))
- val prefixTpe = typeCheck(TypeApply(Select(prefix, newTermName("asInstanceOf")), List(SingletonTypeTree(prefix)))).tpe
- typeCheck(prefix) setType prefixTpe
+ def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree = {
+ val result = scala.reflect.reify.`package`.reifyType(mirror)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete)
+ logFreeVars(enclosingPosition, result)
+ result
}
- def reifyTree(prefix: Tree, tree: Tree): Tree =
- reifyTopLevel(prefix, tree)
-
- def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree =
- reifyTopLevel(prefix, tpe, dontSpliceAtTopLevel, requireConcreteTypeTag)
-
- def reifyErasure(tpe: Type): Tree = {
- val positionBearer = (enclosingMacros.find(_.macroApplication.pos != NoPosition) match {
- case None => EmptyTree
- case Some(m) => m.macroApplication
- }).asInstanceOf[Tree]
-
- val typetagInScope = callsiteTyper.context.withMacrosDisabled(
- callsiteTyper.resolveTypeTag(
- positionBearer,
- singleType(Reflect_mirror.owner.thisPrefix, Reflect_mirror),
- tpe,
- full = true
- )
- )
- typetagInScope match {
- case success if !success.isEmpty && !typetagIsSynthetic(success) =>
- classTagFromArgument(tpe, typetagInScope)
- case _ =>
- if (tpe.typeSymbol == ArrayClass) {
- val componentTpe = tpe.typeArguments(0)
- val componentTag = callsiteTyper.resolveClassTag(positionBearer, componentTpe)
- Select(componentTag, nme.wrap)
- }
- // [Eugene] what's the intended behavior? there's no spec on ClassManifests
- // for example, should we ban Array[T] or should we tag them with Array[AnyRef]?
- // if its the latter, what should be the result of tagging Array[T] where T <: Int?
- else if (tpe.isSpliceable) {
- throw new ReificationError(enclosingPosition,
- "tpe %s is an unresolved spliceable type".format(tpe))
- }
- else classTagFromErasure(tpe)
- }
- }
+ def reifyErasure(tpe: Type, concrete: Boolean = true): Tree =
+ scala.reflect.reify.`package`.reifyErasure(mirror)(callsiteTyper, tpe, concrete)
def unreifyTree(tree: Tree): Tree =
Select(tree, definitions.ExprEval)
-
- def reifyTopLevel(prefix: Tree, reifee: Any, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree = {
- // [Eugene] the plumbing is not very pretty, but anyways factoring out the reifier seems like a necessary step to me
- import scala.reflect.reify._
- val reifier = mkReifier(mirror)(callsiteTyper, prefix, reifee, dontSpliceAtTopLevel, requireConcreteTypeTag)
-
- try {
- val result = reifier.reified
- logFreeVars(enclosingPosition, result)
- result
- } catch {
- case ex: reifier.ReificationError =>
-// // this is a "soft" exception - it will normally be caught by the macro
-// // consequently, we need to log the stack trace here, so that it doesn't get lost
-// if (settings.Yreifydebug.value) {
-// val message = new java.io.StringWriter()
-// ex.printStackTrace(new java.io.PrintWriter(message))
-// println(scala.compat.Platform.EOL + message)
-// }
- val xlated = new ReificationError(ex.pos, ex.msg)
- xlated.setStackTrace(ex.getStackTrace)
- throw xlated
- case ex: reifier.UnexpectedReificationError =>
- val xlated = new UnexpectedReificationError(ex.pos, ex.msg, ex.cause)
- xlated.setStackTrace(ex.getStackTrace)
- throw xlated
- }
- }
-
- class ReificationError(var pos: Position, val msg: String) extends Throwable(msg)
-
- object ReificationError extends ReificationErrorExtractor {
- def unapply(error: ReificationError): Option[(Position, String)] = Some((error.pos, error.msg))
- }
-
- class UnexpectedReificationError(val pos: Position, val msg: String, val cause: Throwable = null) extends Throwable(msg, cause)
-
- object UnexpectedReificationError extends UnexpectedReificationErrorExtractor {
- def unapply(error: UnexpectedReificationError): Option[(Position, String, Throwable)] = Some((error.pos, error.msg, error.cause))
- }
}
diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala
index 30c6c06c7b..1a881455f2 100644
--- a/src/compiler/scala/reflect/reify/Errors.scala
+++ b/src/compiler/scala/reflect/reify/Errors.scala
@@ -1,7 +1,8 @@
package scala.reflect
package reify
-import scala.tools.nsc.Global
+import scala.reflect.makro.ReificationError
+import scala.reflect.makro.UnexpectedReificationError
trait Errors {
self: Reifier =>
@@ -9,9 +10,6 @@ trait Errors {
import mirror._
import definitions._
- class ReificationError(var pos: Position, val msg: String) extends Throwable(msg)
- class UnexpectedReificationError(val pos: Position, val msg: String, val cause: Throwable = null) extends Throwable(msg)
-
lazy val defaultErrorPosition: Position =
mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication.pos).getOrElse(NoPosition)
@@ -60,4 +58,4 @@ trait Errors {
val msg = "internal error: erroneous reifees are not supported, make sure that your reifee has typechecked successfully before passing it to the reifier"
throw new UnexpectedReificationError(defaultErrorPosition, msg)
}
-} \ 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 c89ebf0d39..fea825358e 100644
--- a/src/compiler/scala/reflect/reify/Reifier.scala
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -2,6 +2,8 @@ package scala.reflect
package reify
import scala.tools.nsc.Global
+import scala.reflect.makro.ReificationError
+import scala.reflect.makro.UnexpectedReificationError
/** Given a tree or a type, generate a tree that when executed at runtime produces the original tree or type.
* See more info in the comments to ``reify'' in scala.reflect.api.Universe.
@@ -21,7 +23,7 @@ abstract class Reifier extends Phases
val prefix: Tree
val reifee: Any
val dontSpliceAtTopLevel: Boolean
- val requireConcreteTypeTag: Boolean
+ val concrete: Boolean
/**
* For ``reifee'' and other reification parameters, generate a tree of the form
@@ -47,15 +49,6 @@ abstract class Reifier extends Phases
if (prefix exists (_.isErroneous)) CannotReifyErroneousPrefix(prefix)
if (prefix.tpe == null) CannotReifyUntypedPrefix(prefix)
- def reifyErasure(tpe: Type): Tree = {
- val result = typer.resolveClassTag(positionBearer, tpe)
- if (result == EmptyTree) throw new Error("cannot reify erasure for %s: ".format(tpe))
- result match {
- case Apply(TypeApply(Select(_, _), _), List(clazz)) => clazz
- case _ => Select(result, nme.erasure)
- }
- }
-
val rtree = reifee match {
case tree: Tree =>
reifyTrace("reifying = ")(if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
@@ -81,11 +74,11 @@ abstract class Reifier extends Phases
if (tree.tpe exists (sub => sub.typeSymbol.isLocalToReifee))
CannotReifyReifeeThatHasTypeLocalToReifee(tree)
- val manifestedType = typer.packedType(tree, NoSymbol)
- val tagModule = if (definitelyConcrete) ConcreteTypeTagModule else TypeTagModule
- val tagCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType)))
- val exprCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), ExprModule.name), List(TypeTree(manifestedType)))
- val tagArgs = if (definitelyConcrete) List(reify(manifestedType), reifyErasure(manifestedType)) else List(reify(manifestedType))
+ val taggedType = typer.packedType(tree, NoSymbol)
+ val tagModule = if (reificationIsConcrete) ConcreteTypeTagModule else TypeTagModule
+ val tagCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(taggedType)))
+ val exprCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), ExprModule.name), List(TypeTree(taggedType)))
+ val tagArgs = List(reify(taggedType), reifyErasure(mirror)(typer, taggedType, concrete = false))
Apply(Apply(exprCtor, List(rtree)), List(Apply(tagCtor, tagArgs)))
case tpe: Type =>
@@ -93,10 +86,10 @@ abstract class Reifier extends Phases
reifyTrace("prefix = ")(prefix)
val rtree = reify(tpe)
- val manifestedType = tpe
- val tagModule = if (definitelyConcrete) ConcreteTypeTagModule else TypeTagModule
- val ctor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType)))
- val args = if (definitelyConcrete) List(rtree, reifyErasure(manifestedType)) else List(rtree)
+ val taggedType = tpe
+ val tagModule = if (reificationIsConcrete) ConcreteTypeTagModule else TypeTagModule
+ val ctor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(taggedType)))
+ val args = List(rtree, reifyErasure(mirror)(typer, taggedType, concrete = false))
Apply(ctor, args)
case _ =>
@@ -137,9 +130,16 @@ abstract class Reifier extends Phases
// 4) trivial tree splice inlining in Reify (Trees.scala)
// 5) trivial type splice inlining in Reify (Types.scala)
val freevarBindings = symbolTable collect { case entry @ FreeDef(_, _, binding, _, _) => binding.symbol } toSet
+ // [Eugene] yeah, ugly and extremely brittle, but we do need to do resetAttrs. will be fixed later
+ var importantSymbols = Set[Symbol](PredefModule, ScalaRunTimeModule)
+ importantSymbols ++= importantSymbols map (_.companionSymbol)
+ importantSymbols ++= importantSymbols map (_.moduleClass)
+ importantSymbols ++= importantSymbols map (_.linkedClassOfClass)
+ def importantSymbol(sym: Symbol): Boolean = sym != null && sym != NoSymbol && importantSymbols(sym)
val untyped = resetAllAttrs(wrapped, leaveAlone = {
case ValDef(_, mr, _, _) if mr == nme.MIRROR_SHORT => true
case tree if freevarBindings contains tree.symbol => true
+ case tree if importantSymbol(tree.symbol) => true
case _ => false
})
diff --git a/src/compiler/scala/reflect/reify/codegen/Symbols.scala b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
index 7f8b9c53b6..21a08b7efb 100644
--- a/src/compiler/scala/reflect/reify/codegen/Symbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
@@ -76,7 +76,7 @@ trait Symbols {
case None =>
if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString))
var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name)
- val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.MIRROR_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null))))
+ val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.MIRROR_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null)), Literal(Constant(null))))
val flavor = if (sym.isExistential) nme.newFreeExistential else nme.newFreeType
locallyReify(sym, name, mirrorCall(flavor, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(sym.flags), reify(origin(sym))))
}
diff --git a/src/compiler/scala/reflect/reify/codegen/Types.scala b/src/compiler/scala/reflect/reify/codegen/Types.scala
index e2a2a69828..841ec61e60 100644
--- a/src/compiler/scala/reflect/reify/codegen/Types.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Types.scala
@@ -65,11 +65,11 @@ trait Types {
private var spliceTypesEnabled = !dontSpliceAtTopLevel
/** Keeps track of whether this reification contains abstract type parameters */
- private var _definitelyConcrete = true
- def definitelyConcrete = _definitelyConcrete
- def definitelyConcrete_=(value: Boolean) {
- _definitelyConcrete = value
- if (!value && requireConcreteTypeTag) {
+ private var _reificationIsConcrete = true
+ def reificationIsConcrete = _reificationIsConcrete
+ def reificationIsConcrete_=(value: Boolean) {
+ _reificationIsConcrete = value
+ if (!value && concrete) {
assert(current.isInstanceOf[Type], current)
val offender = current.asInstanceOf[Type]
CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(offender)
@@ -89,7 +89,7 @@ trait Types {
if (reifyDebug) println("splicing " + tpe)
if (spliceTypesEnabled) {
- var tagClass = if (requireConcreteTypeTag) ConcreteTypeTagClass else TypeTagClass
+ var tagClass = if (concrete) ConcreteTypeTagClass else TypeTagClass
val tagTpe = singleType(prefix.tpe, prefix.tpe member tagClass.name)
// [Eugene] this should be enough for an abstract type, right?
@@ -99,13 +99,13 @@ trait Types {
// if this fails, it might produce the dreaded "erroneous or inaccessible type" error
// to find out the whereabouts of the error run scalac with -Ydebug
if (reifyDebug) println("launching implicit search for %s.%s[%s]".format(prefix, tagClass.name, tpe))
- typer.resolveTypeTag(positionBearer, prefix.tpe, tpe, requireConcreteTypeTag) match {
+ typer.resolveTypeTag(positionBearer.pos, prefix.tpe, tpe, concrete) match {
case failure if failure.isEmpty =>
if (reifyDebug) println("implicit search was fruitless")
EmptyTree
case success =>
if (reifyDebug) println("implicit search has produced a result: " + success)
- definitelyConcrete &= requireConcreteTypeTag
+ reificationIsConcrete &= concrete
var splice = Select(success, nme.tpe)
splice match {
case InlinedTypeSplice(_, inlinedSymbolTable, tpe) =>
@@ -123,7 +123,7 @@ trait Types {
if (reifyDebug) println("splicing has been cancelled: spliceTypesEnabled = false")
}
- definitelyConcrete = false
+ reificationIsConcrete = false
}
spliceTypesEnabled = true
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala
index 85cf92fe2f..fa11c6313d 100644
--- a/src/compiler/scala/reflect/reify/package.scala
+++ b/src/compiler/scala/reflect/reify/package.scala
@@ -1,14 +1,16 @@
package scala.reflect
import scala.tools.nsc.Global
+import scala.reflect.makro.ReificationError
+import scala.reflect.makro.UnexpectedReificationError
package object reify {
- def mkReifier(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, reifee: Any, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Reifier { val mirror: global.type } = {
+ private def mkReifier(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, reifee: Any, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Reifier { val mirror: global.type } = {
val typer1: typer.type = typer
val prefix1: prefix.type = prefix
val reifee1 = reifee
val dontSpliceAtTopLevel1 = dontSpliceAtTopLevel
- val requireConcreteTypeTag1 = requireConcreteTypeTag
+ val concrete1 = concrete
new {
val mirror: global.type = global
@@ -16,7 +18,37 @@ package object reify {
val prefix = prefix1
val reifee = reifee1
val dontSpliceAtTopLevel = dontSpliceAtTopLevel1
- val requireConcreteTypeTag = requireConcreteTypeTag1
+ val concrete = concrete1
} with Reifier
}
+
+ def reifyTree(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tree: global.Tree): global.Tree =
+ mkReifier(global)(typer, prefix, tree, false, false).reified.asInstanceOf[global.Tree]
+
+ def reifyType(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tpe: global.Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): global.Tree =
+ mkReifier(global)(typer, prefix, tpe, dontSpliceAtTopLevel, concrete).reified.asInstanceOf[global.Tree]
+
+ def reifyErasure(global: Global)(typer0: global.analyzer.Typer, tpe: global.Type, concrete: Boolean = true): global.Tree = {
+ import global._
+ import definitions._
+ val positionBearer = analyzer.openMacros.find(_.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree]
+ val inScope = typer0.context.withMacrosDisabled(typer0.resolveErasureTag(positionBearer.pos, tpe, concrete = concrete), typer0.resolveArrayTag(positionBearer.pos, tpe))
+ inScope match {
+ case (success, _) if !success.isEmpty =>
+ Select(success, nme.erasure)
+ case (_, success) if !success.isEmpty =>
+ gen.mkMethodCall(arrayElementClassMethod, List(success))
+ case _ =>
+ if (tpe.typeSymbol == ArrayClass) {
+ val componentTpe = tpe.typeArguments(0)
+ val componentErasure = reifyErasure(global)(typer0, componentTpe, concrete)
+ gen.mkMethodCall(arrayClassMethod, List(componentErasure))
+ } else {
+ if (tpe.isSpliceable && concrete) throw new ReificationError(positionBearer.pos, "tpe %s is an unresolved spliceable type".format(tpe))
+ var erasure = tpe.erasure
+ if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe
+ gen.mkNullaryCall(Predef_classOf, List(erasure))
+ }
+ }
+ }
}