diff options
Diffstat (limited to 'src/compiler/scala/reflect')
-rw-r--r-- | src/compiler/scala/reflect/internal/Definitions.scala | 16 | ||||
-rw-r--r-- | src/compiler/scala/reflect/internal/StdNames.scala | 42 | ||||
-rw-r--r-- | src/compiler/scala/reflect/internal/TreeInfo.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/reflect/internal/Types.scala | 21 | ||||
-rw-r--r-- | src/compiler/scala/reflect/makro/runtime/Reifiers.scala | 123 | ||||
-rw-r--r-- | src/compiler/scala/reflect/reify/Errors.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/reflect/reify/Reifier.scala | 38 | ||||
-rw-r--r-- | src/compiler/scala/reflect/reify/codegen/Symbols.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/reflect/reify/codegen/Types.scala | 18 | ||||
-rw-r--r-- | src/compiler/scala/reflect/reify/package.scala | 38 |
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)) + } + } + } } |