summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-04-16 11:52:25 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-04-17 21:27:40 +0200
commite408aa9ccaba736d0f85b7afecd288c3873d05bb (patch)
treeb115dd0261cfe4f8a2f741d1cb4afd1412886e48 /src/compiler
parent17fa0b13480c7dd9796885e32ec562e162253350 (diff)
downloadscala-e408aa9ccaba736d0f85b7afecd288c3873d05bb.tar.gz
scala-e408aa9ccaba736d0f85b7afecd288c3873d05bb.tar.bz2
scala-e408aa9ccaba736d0f85b7afecd288c3873d05bb.zip
adds erasures to concrete type tags
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Importers.scala4
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala8
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala8
-rw-r--r--src/compiler/scala/reflect/internal/TreeBuildUtil.scala8
-rw-r--r--src/compiler/scala/reflect/internal/TreeInfo.scala31
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala2
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Reifiers.scala41
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Typers.scala8
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala26
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Symbols.scala10
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Trees.scala35
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Types.scala27
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Util.scala2
-rw-r--r--src/compiler/scala/reflect/reify/phases/Metalevels.scala4
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reify.scala47
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala6
-rw-r--r--src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala8
-rw-r--r--src/compiler/scala/tools/nsc/ast/FreeVars.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala3
19 files changed, 188 insertions, 94 deletions
diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala
index ab5e19fca9..596d400628 100644
--- a/src/compiler/scala/reflect/internal/Importers.scala
+++ b/src/compiler/scala/reflect/internal/Importers.scala
@@ -71,9 +71,9 @@ trait Importers { self: SymbolTable =>
case x: from.ModuleSymbol =>
linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol)
case x: from.FreeTerm =>
- newFreeTerm(importName(x.name).toTermName, importType(x.info), x.value, x.origin, myflags)
+ newFreeTermSymbol(importName(x.name).toTermName, importType(x.info), x.value, x.flags, x.origin)
case x: from.FreeType =>
- newFreeType(importName(x.name).toTypeName, importType(x.info), x.value, x.origin, myflags)
+ newFreeTypeSymbol(importName(x.name).toTypeName, importType(x.info), x.value, x.flags, x.origin)
case x: from.TermSymbol =>
linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol)
case x: from.TypeSkolem =>
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index bf468affe6..c5fe1ecb45 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -291,11 +291,14 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val AnnotationInfo: NameType = "AnnotationInfo"
val Any: NameType = "Any"
val AnyVal: NameType = "AnyVal"
+ val AppliedTypeTree: NameType = "AppliedTypeTree"
val Apply: NameType = "Apply"
val ArrayAnnotArg: NameType = "ArrayAnnotArg"
+ val Constant: NameType = "Constant"
val ConstantType: NameType = "ConstantType"
val EmptyPackage: NameType = "EmptyPackage"
val EmptyPackageClass: NameType = "EmptyPackageClass"
+ val ExistentialTypeTree: NameType = "ExistentialTypeTree"
val Expr: NameType = "Expr"
val Ident: NameType = "Ident"
val Import: NameType = "Import"
@@ -404,13 +407,15 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val name: NameType = "name"
val ne: NameType = "ne"
val newArray: NameType = "newArray"
+ val newFreeExistential: NameType = "newFreeExistential"
val newFreeTerm: NameType = "newFreeTerm"
val newFreeType: NameType = "newFreeType"
val newNestedSymbol: NameType = "newNestedSymbol"
val newScopeWith: NameType = "newScopeWith"
+ val next: NameType = "next"
val nmeNewTermName: NameType = "newTermName"
val nmeNewTypeName: NameType = "newTypeName"
- val next: NameType = "next"
+ val normalize: NameType = "normalize"
val notifyAll_ : NameType = "notifyAll"
val notify_ : NameType = "notify"
val null_ : NameType = "null"
@@ -465,6 +470,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val view_ : NameType = "view"
val wait_ : NameType = "wait"
val withFilter: NameType = "withFilter"
+ val wrap: NameType = "wrap"
val zip: NameType = "zip"
val synthSwitch: NameType = "$synthSwitch"
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 6eaae7f1ee..74e924add4 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -47,13 +47,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Create a new free term. Its owner is NoSymbol.
*/
- def newFreeTerm(name: TermName, info: Type, value: => Any, origin: String, newFlags: Long = 0L): FreeTerm =
- new FreeTerm(name, value, origin) initFlags newFlags setInfo info
+ def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTerm =
+ new FreeTerm(name, value, origin) initFlags flags setInfo info
/** Create a new free type. Its owner is NoSymbol.
*/
- def newFreeType(name: TypeName, info: Type, value: => Any, origin: String, newFlags: Long = 0L): FreeType =
- new FreeType(name, value, origin) initFlags newFlags setInfo info
+ def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeType =
+ new FreeType(name, value, origin) initFlags flags setInfo info
/** The original owner of a class. Used by the backend to generate
* EnclosingMethod attributes.
diff --git a/src/compiler/scala/reflect/internal/TreeBuildUtil.scala b/src/compiler/scala/reflect/internal/TreeBuildUtil.scala
index fbcd5043bc..d4d4652e91 100644
--- a/src/compiler/scala/reflect/internal/TreeBuildUtil.scala
+++ b/src/compiler/scala/reflect/internal/TreeBuildUtil.scala
@@ -1,6 +1,8 @@
package scala.reflect
package internal
+import Flags._
+
trait TreeBuildUtil extends api.TreeBuildUtil { self: SymbolTable =>
// ``staticClass'' and ``staticModule'' rely on ClassLoaders
@@ -51,9 +53,11 @@ trait TreeBuildUtil extends api.TreeBuildUtil { self: SymbolTable =>
try selectOverloadedMethod(owner, name, index)
catch { case _: MissingRequirementError => NoSymbol }
- def newFreeTerm(name: String, info: Type, value: => Any, origin: String) = newFreeTerm(newTermName(name), info, value, origin)
+ def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTermSymbol(newTermName(name), info, value, flags, origin)
+
+ def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) PARAM else flags) | DEFERRED, origin)
- def newFreeType(name: String, info: Type, value: => Any, origin: String) = newFreeType(newTypeName(name), info, value, origin)
+ def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) EXISTENTIAL else flags) | DEFERRED, origin)
def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers =
Modifiers(flags, privateWithin, annotations)
diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala
index 039c8e557a..937b3ea5d6 100644
--- a/src/compiler/scala/reflect/internal/TreeInfo.scala
+++ b/src/compiler/scala/reflect/internal/TreeInfo.scala
@@ -629,7 +629,7 @@ abstract class TreeInfo {
object ReifiedType {
def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
- case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, List(tpe))) if mrDef.name == nme.MIRROR_SHORT =>
+ case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, tpe :: _)) if mrDef.name == nme.MIRROR_SHORT =>
Some(reifee, symbolTable, tpe)
case _ =>
None
@@ -646,11 +646,11 @@ abstract class TreeInfo {
}
object FreeDef {
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match {
- case FreeTermDef(mrRef, name, binding, origin) =>
- Some(mrRef, name, binding, origin)
- case FreeTypeDef(mrRef, name, binding, origin) =>
- Some(mrRef, name, binding, origin)
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
+ case FreeTermDef(mrRef, name, binding, flags, origin) =>
+ Some(mrRef, name, binding, flags, origin)
+ case FreeTypeDef(mrRef, name, binding, flags, origin) =>
+ Some(mrRef, name, binding, flags, origin)
case _ =>
None
}
@@ -659,28 +659,29 @@ abstract class TreeInfo {
object FreeTermDef {
lazy val newFreeTermMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeTerm)
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match {
- case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(origin: String)))))
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
+ case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(flags: Long)), Literal(Constant(origin: String)))))
if mrRef.name == nme.MIRROR_SHORT && newFreeTerm == newFreeTermMethod.name =>
- Some(mrRef, name, binding, origin)
+ Some(mrRef, name, binding, flags, origin)
case _ =>
None
}
}
object FreeTypeDef {
- lazy val newFreeTypeMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeType)
+ lazy val newFreeExistentialMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeType)
+ lazy val newFreeTypeMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeExistential)
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match {
- case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(origin: String)))))
- if mrRef1.name == nme.MIRROR_SHORT && newFreeType == newFreeTypeMethod.name =>
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
+ 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))))
if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply =>
- Some(mrRef1, name, binding, origin)
+ Some(mrRef1, name, binding, flags, origin)
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, origin)
+ Some(mrRef1, name, binding, flags, origin)
case _ =>
throw new Error("unsupported free type def: " + showRaw(tree))
}
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index fc57a130d1..7115cafc33 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -277,7 +277,7 @@ trait Types extends api.Types { self: SymbolTable =>
case SuperType(_, _) => false
case SingleType(pre, sym) => notConcreteSym(sym)
case ConstantType(_) => false
- case TypeRef(_, sym, _) => notConcreteSym(sym)
+ case TypeRef(_, sym, args) => notConcreteSym(sym) || (args exists (arg => notConcreteTpe(arg)))
case RefinedType(_, _) => false
case ExistentialType(_, _) => false
case AnnotatedType(_, tp, _) => notConcreteTpe(tp)
diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
index 2488b06d6c..3586adc590 100644
--- a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
@@ -10,6 +10,7 @@ trait Reifiers {
self: Context =>
import mirror._
+ import definitions._
lazy val reflectMirrorPrefix: Tree = {
// [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure?
@@ -24,6 +25,44 @@ trait Reifiers {
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(c => c.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree]
+ val typetagInScope = callsiteTyper.context.withMacrosDisabled(callsiteTyper.resolveTypeTag(positionBearer, gen.mkAttributedRef(Reflect_mirror).tpe, tpe, full = true))
+ def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == ConcreteTypeTagModule))
+ typetagInScope match {
+ case success if !success.isEmpty && !typetagIsSynthetic(success) =>
+ val factory = TypeApply(Select(Ident(ClassTagModule), nme.apply), List(TypeTree(tpe)))
+ Apply(factory, List(typetagInScope))
+ case _ =>
+ if (tpe.typeSymbol == ArrayClass) {
+ val componentTpe = tpe.typeArguments(0)
+ val componentTag = callsiteTyper.resolveClassTag(positionBearer, componentTpe)
+ Select(componentTag, nme.wrap)
+ } else {
+ // [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?
+ if (tpe.isSpliceable) throw new ReificationError(enclosingPosition, "tpe %s is an unresolved spliceable type".format(tpe))
+ // [Eugene] imho this logic should be moved into `erasure`
+ var erasure = 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
+ var result = tpe.erasure.normalize // necessary to deal with erasures of HK types, typeConstructor won't work
+ result = result match {
+ case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result
+ case _ => result
+ }
+ result
+ }
+ }
+ val factory = TypeApply(Select(Ident(ClassTagModule), nme.apply), List(TypeTree(tpe)))
+ Apply(factory, List(TypeApply(Select(Ident(PredefModule), nme.classOf), List(TypeTree(erasure)))))
+ }
+ }
+ }
+
def unreifyTree(tree: Tree): Tree =
Select(tree, definitions.ExprEval)
@@ -34,7 +73,7 @@ trait Reifiers {
try {
val result = reifier.reified
- logFreeVars(expandee.pos, result)
+ logFreeVars(enclosingPosition, result)
result
} catch {
case ex: reifier.ReificationError =>
diff --git a/src/compiler/scala/reflect/makro/runtime/Typers.scala b/src/compiler/scala/reflect/makro/runtime/Typers.scala
index 38e819746d..b32d4fb7b1 100644
--- a/src/compiler/scala/reflect/makro/runtime/Typers.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Typers.scala
@@ -34,9 +34,9 @@ trait Typers {
def trace(msg: Any) = if (mirror.settings.Ymacrodebug.value) println(msg)
trace("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled))
import mirror.analyzer.SearchResult
- val wrapper1 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[SearchResult] _) else (callsiteTyper.context.withMacrosDisabled[SearchResult] _)
- def wrapper (inference: => SearchResult) = wrapper1(inference)
val context = callsiteTyper.context.makeImplicit(true)
+ val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _)
+ def wrapper (inference: => SearchResult) = wrapper1(inference)
wrapper(mirror.analyzer.inferImplicit(mirror.EmptyTree, pt, true, false, context, !silent, pos)) match {
case failure if failure.tree.isEmpty =>
trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits")
@@ -51,11 +51,11 @@ trait Typers {
def trace(msg: Any) = if (mirror.settings.Ymacrodebug.value) println(msg)
trace("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous))
import mirror.analyzer.SearchResult
- val wrapper1 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[SearchResult] _) else (callsiteTyper.context.withMacrosDisabled[SearchResult] _)
+ val context = callsiteTyper.context.makeImplicit(reportAmbiguous)
+ val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _)
def wrapper (inference: => SearchResult) = wrapper1(inference)
val fun1 = mirror.definitions.FunctionClass(1)
val viewTpe = mirror.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to))
- val context = callsiteTyper.context.makeImplicit(reportAmbiguous)
wrapper(mirror.analyzer.inferImplicit(mirror.EmptyTree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match {
case failure if failure.tree.isEmpty =>
trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits")
diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala
index 16c26734b2..c89ebf0d39 100644
--- a/src/compiler/scala/reflect/reify/Reifier.scala
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -47,6 +47,15 @@ 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)
@@ -73,11 +82,11 @@ abstract class Reifier extends Phases
CannotReifyReifeeThatHasTypeLocalToReifee(tree)
val manifestedType = typer.packedType(tree, NoSymbol)
- val manifestedRtype = reifyType(manifestedType)
val tagModule = if (definitelyConcrete) ConcreteTypeTagModule else TypeTagModule
- var typeTagCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType)))
- var exprCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), ExprModule.name), List(TypeTree(manifestedType)))
- Apply(Apply(exprCtor, List(rtree)), List(Apply(typeTagCtor, List(manifestedRtype))))
+ 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))
+ Apply(Apply(exprCtor, List(rtree)), List(Apply(tagCtor, tagArgs)))
case tpe: Type =>
reifyTrace("reifying = ")(tpe.toString)
@@ -85,9 +94,10 @@ abstract class Reifier extends Phases
val rtree = reify(tpe)
val manifestedType = tpe
- var tagModule = if (definitelyConcrete) ConcreteTypeTagModule else TypeTagModule
- var ctor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType)))
- Apply(ctor, List(rtree))
+ 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)
+ Apply(ctor, args)
case _ =>
throw new Error("reifee %s of type %s is not supported".format(reifee, if (reifee == null) "null" else reifee.getClass.toString))
@@ -126,7 +136,7 @@ abstract class Reifier extends Phases
// 3) local freeterm inlining in Metalevels
// 4) trivial tree splice inlining in Reify (Trees.scala)
// 5) trivial type splice inlining in Reify (Types.scala)
- val freevarBindings = symbolTable collect { case freedef @ FreeDef(_, _, binding, _) => binding.symbol } toSet
+ val freevarBindings = symbolTable collect { case entry @ FreeDef(_, _, binding, _, _) => binding.symbol } toSet
val untyped = resetAllAttrs(wrapped, leaveAlone = {
case ValDef(_, mr, _, _) if mr == nme.MIRROR_SHORT => true
case tree if freevarBindings contains tree.symbol => true
diff --git a/src/compiler/scala/reflect/reify/codegen/Symbols.scala b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
index 2fc0002838..0513f99366 100644
--- a/src/compiler/scala/reflect/reify/codegen/Symbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
@@ -63,9 +63,9 @@ trait Symbols {
assert(value.isInstanceOf[Ident], showRaw(value))
val capturedTpe = capturedVariableType(sym)
val capturedValue = referenceCapturedVariable(sym)
- locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(origin(sym))))
+ locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(sym.flags), reify(origin(sym))))
} else {
- locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(origin(sym))))
+ locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(sym.flags), reify(origin(sym))))
}
}
@@ -77,8 +77,8 @@ trait Symbols {
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))))
- // todo. implement info reification for free types: type bounds, HK-arity, whatever else that can be useful
- locallyReify(sym, name, mirrorCall(nme.newFreeType, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(origin(sym))))
+ 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))))
}
def reifySymDef(sym: Symbol): Tree =
@@ -169,7 +169,7 @@ trait Symbols {
if (sym.annotations.isEmpty) EmptyTree
else Apply(Select(locallyReified(sym), nme.setAnnotations), List(reify(sym.annotations)))
} else {
- val rset = Apply(Select(locallyReified(sym), nme.setTypeSignature), List(reifyType(sym.info)))
+ val rset = Apply(Select(locallyReified(sym), nme.setTypeSignature), List(reify(sym.info)))
if (sym.annotations.isEmpty) rset
else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations)))
}
diff --git a/src/compiler/scala/reflect/reify/codegen/Trees.scala b/src/compiler/scala/reflect/reify/codegen/Trees.scala
index 5ad53c0009..c9f5fc5b8d 100644
--- a/src/compiler/scala/reflect/reify/codegen/Trees.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Trees.scala
@@ -7,6 +7,7 @@ trait Trees {
import mirror._
import definitions._
import treeInfo._
+ import scala.reflect.api.Modifier
// unfortunately, these are necessary to reify AnnotatedTypes
// I'd gladly got rid of them, but I don't fancy making a metaprogramming API that doesn't work with annotated types
@@ -46,7 +47,7 @@ trait Trees {
reifyMirrorObject(EmptyTree)
case mirror.emptyValDef =>
mirrorSelect(nme.emptyValDef)
- case FreeDef(_, _, _, _) =>
+ case FreeDef(_, _, _, _, _) =>
reifyNestedFreeDef(tree)
case FreeRef(_, _) =>
reifyNestedFreeRef(tree)
@@ -57,6 +58,28 @@ trait Trees {
case NestedExpr(_, _, _) =>
reifyNestedExpr(tree)
case Literal(const @ Constant(_)) =>
+ // [Eugene] was necessary when we reified erasures as normalized tycons
+ // now, when we do existentialAbstraction on normalizations, everything works great
+ // todo. find an explanation
+// if (const.tag == ClazzTag) {
+//// def preprocess(tpe: Type): Type = tpe.typeSymbol match {
+//// case ArrayClass => appliedType(ArrayClass, preprocess(tpe.typeArgs.head))
+//// case _ => tpe.typeConstructor
+//// }
+//// val tpe = preprocess(const.typeValue)
+// val tpe = const.typeValue
+// var reified = reify(tpe)
+// reified = mirrorCall(nme.Literal, mirrorCall(nme.Constant, reified))
+//// val skolems = ClassClass.typeParams map (_ => newTypeName(typer.context.unit.fresh.newName("_$")))
+//// var existential = mirrorCall(nme.AppliedTypeTree, mirrorCall(nme.TypeTree, reify(ClassClass.typeConstructor)), mkList(skolems map (skolem => mirrorCall(nme.Ident, reify(skolem)))))
+//// existential = mirrorCall(nme.ExistentialTypeTree, existential, reify(skolems map (skolem => TypeDef(Modifiers(Set(Modifier.deferred: Modifier)), skolem, Nil, TypeBoundsTree(Ident(NothingClass) setType NothingClass.tpe, Ident(AnyClass) setType AnyClass.tpe)))))
+//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(existential)))
+// // why is this required??
+//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(mirrorCall(nme.TypeTree, reify(appliedType(ClassClass.tpe, List(AnyClass.tpe)))))))
+// reified
+// } else {
+// mirrorCall(nme.Literal, reifyProduct(const))
+// }
mirrorCall(nme.Literal, reifyProduct(const))
case Import(expr, selectors) =>
mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct))
@@ -68,11 +91,11 @@ trait Trees {
// however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why.
if (reifyTreeSymbols && tree.hasSymbol) {
if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree))
- rtree = Apply(Select(rtree, nme.setSymbol), List(reifySymRef(tree.symbol)))
+ rtree = Apply(Select(rtree, nme.setSymbol), List(reify(tree.symbol)))
}
if (reifyTreeTypes && tree.tpe != null) {
if (reifyDebug) println("reifying type %s for tree %s".format(tree.tpe, tree))
- rtree = Apply(Select(rtree, nme.setType), List(reifyType(tree.tpe)))
+ rtree = Apply(Select(rtree, nme.setType), List(reify(tree.tpe)))
}
rtree
@@ -98,7 +121,7 @@ trait Trees {
case InlinedTreeSplice(_, inlinedSymbolTable, tree, _) =>
if (reifyDebug) println("inlining the splicee")
// all free vars local to the enclosing reifee should've already been inlined by ``Metalevels''
- inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _) if binding.symbol.isLocalToReifee => assert(false, freedef) }
+ inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) }
symbolTable ++= inlinedSymbolTable
tree
case tree =>
@@ -172,7 +195,7 @@ trait Trees {
val spliced = spliceType(tpe)
if (spliced == EmptyTree) {
if (reifyDebug) println("splicing failed: reify as is")
- mirrorCall(nme.TypeTree, reifyType(tpe))
+ mirrorCall(nme.TypeTree, reify(tpe))
} else {
spliced match {
case TypeRefToFreeType(freeType) =>
@@ -189,7 +212,7 @@ trait Trees {
mirrorCall(nme.Ident, reify(sym))
} else {
if (reifyDebug) println("tpe is an alias, but not a locatable: reify as TypeTree(%s)".format(tpe))
- mirrorCall(nme.TypeTree, reifyType(tpe))
+ mirrorCall(nme.TypeTree, reify(tpe))
}
}
}
diff --git a/src/compiler/scala/reflect/reify/codegen/Types.scala b/src/compiler/scala/reflect/reify/codegen/Types.scala
index 948728088e..e2a2a69828 100644
--- a/src/compiler/scala/reflect/reify/codegen/Types.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Types.scala
@@ -65,8 +65,16 @@ trait Types {
private var spliceTypesEnabled = !dontSpliceAtTopLevel
/** Keeps track of whether this reification contains abstract type parameters */
- var maybeConcrete = true
- var definitelyConcrete = true
+ private var _definitelyConcrete = true
+ def definitelyConcrete = _definitelyConcrete
+ def definitelyConcrete_=(value: Boolean) {
+ _definitelyConcrete = value
+ if (!value && requireConcreteTypeTag) {
+ assert(current.isInstanceOf[Type], current)
+ val offender = current.asInstanceOf[Type]
+ CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(offender)
+ }
+ }
private type SpliceCacheKey = (Symbol, Symbol)
private lazy val spliceCache: collection.mutable.Map[SpliceCacheKey, Tree] = {
@@ -75,7 +83,9 @@ trait Types {
}
def spliceType(tpe: Type): Tree = {
- if (tpe.isSpliceable) {
+ // [Eugene] it seems that depending on the context the very same symbol can be either a spliceable tparam or a quantified existential. very weird!
+ val quantified = currents collect { case ExistentialType(quantified, _) => quantified } flatMap identity
+ if (tpe.isSpliceable && !(quantified contains tpe.typeSymbol)) {
if (reifyDebug) println("splicing " + tpe)
if (spliceTypesEnabled) {
@@ -89,22 +99,18 @@ 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))
- val positionBearer = mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree]
typer.resolveTypeTag(positionBearer, prefix.tpe, tpe, requireConcreteTypeTag) match {
case failure if failure.isEmpty =>
if (reifyDebug) println("implicit search was fruitless")
- definitelyConcrete &= false
- maybeConcrete &= false
EmptyTree
case success =>
if (reifyDebug) println("implicit search has produced a result: " + success)
- definitelyConcrete |= requireConcreteTypeTag
- maybeConcrete |= true
+ definitelyConcrete &= requireConcreteTypeTag
var splice = Select(success, nme.tpe)
splice match {
case InlinedTypeSplice(_, inlinedSymbolTable, tpe) =>
// all free vars local to the enclosing reifee should've already been inlined by ``Metalevels''
- inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _) if binding.symbol.isLocalToReifee => assert(false, freedef) }
+ inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) }
symbolTable ++= inlinedSymbolTable
reifyTrace("inlined the splicee: ")(tpe)
case tpe =>
@@ -117,8 +123,7 @@ trait Types {
if (reifyDebug) println("splicing has been cancelled: spliceTypesEnabled = false")
}
- if (requireConcreteTypeTag)
- CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(tpe)
+ definitelyConcrete = false
}
spliceTypesEnabled = true
diff --git a/src/compiler/scala/reflect/reify/codegen/Util.scala b/src/compiler/scala/reflect/reify/codegen/Util.scala
index bb369a1adb..8d7cf39ff7 100644
--- a/src/compiler/scala/reflect/reify/codegen/Util.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Util.scala
@@ -14,6 +14,8 @@ trait Util {
object reifiedNodePrinters extends { val global: mirror.type = mirror } with tools.nsc.ast.NodePrinters with NodePrinters
val reifiedNodeToString = reifiedNodePrinters.reifiedNodeToString
+ val positionBearer = mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree]
+
def reifyList(xs: List[Any]): Tree =
mkList(xs map reify)
diff --git a/src/compiler/scala/reflect/reify/phases/Metalevels.scala b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
index bb0b8ac138..206f3b1118 100644
--- a/src/compiler/scala/reflect/reify/phases/Metalevels.scala
+++ b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
@@ -115,7 +115,7 @@ trait Metalevels {
if (reifyDebug) println("entering inlineable splice: " + splicee)
val Block(mrDef :: symbolTable, expr) = splicee
// [Eugene] how to express the fact that a scrutinee is both of some type and matches an extractor?
- val freedefsToInline = symbolTable collect { case freedef @ FreeTermDef(_, _, binding, _) if binding.symbol.isLocalToReifee => freedef.asInstanceOf[ValDef] }
+ val freedefsToInline = symbolTable collect { case freedef @ FreeTermDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => freedef.asInstanceOf[ValDef] }
freedefsToInline foreach (vdef => this.freedefsToInline(vdef.name) = vdef)
val symbolTable1 = symbolTable diff freedefsToInline
val tree1 = Select(Block(mrDef :: symbolTable1, expr), flavor)
@@ -138,7 +138,7 @@ trait Metalevels {
// some of them need to be rebuilt, some of them need to be removed, because they're no longer necessary
case FreeRef(mr, name) if freedefsToInline contains name =>
if (reifyDebug) println("inlineable free ref: %s in %s".format(name, showRaw(tree)))
- val freedef @ FreeDef(_, _, binding, _) = freedefsToInline(name)
+ val freedef @ FreeDef(_, _, binding, _, _) = freedefsToInline(name)
if (reifyDebug) println("related definition: %s".format(showRaw(freedef)))
val inlined = reify(binding)
if (reifyDebug) println("verdict: inlined as %s".format(showRaw(inlined)))
diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala
index 02a96987ed..a1ff486ed7 100644
--- a/src/compiler/scala/reflect/reify/phases/Reify.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reify.scala
@@ -23,24 +23,33 @@ trait Reify extends Symbols
* Reifies any supported value.
* For internal use only, use ``reified'' instead.
*/
- def reify(reifee: Any): Tree = reifee match {
- // before adding some case here, in global scope, please, consider
- // whether it can be localized like reifyAnnotationInfo or reifyScope
- // this will help reification stay as sane as possible
- case sym: Symbol => reifySymRef(sym)
- case tpe: Type => reifyType(tpe)
- case name: Name => reifyName(name)
- case tree: Tree => reifyTree(tree)
- // disabled because this is a very special case that I plan to remove later
- // why do I dislike annotations? see comments to `reifyAnnotationInfo`
-// case ann: AnnotationInfo => reifyAnnotationInfo(ann)
- case pos: Position => reifyPosition(pos)
- case mods: mirror.Modifiers => reifyModifiers(mods)
- case xs: List[_] => reifyList(xs)
- case s: String => Literal(Constant(s))
- case v if isAnyVal(v) => Literal(Constant(v))
- case null => Literal(Constant(null))
- case _ =>
- throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass))
+ var currents: List[Any] = reifee :: Nil
+ def current = currents.head
+ def reify(reifee: Any): Tree = {
+ currents = reifee :: currents
+ try {
+ reifee match {
+ // before adding some case here, in global scope, please, consider
+ // whether it can be localized like reifyAnnotationInfo or reifyScope
+ // this will help reification stay as sane as possible
+ case sym: Symbol => reifySymRef(sym)
+ case tpe: Type => reifyType(tpe)
+ case name: Name => reifyName(name)
+ case tree: Tree => reifyTree(tree)
+ // disabled because this is a very special case that I plan to remove later
+ // why do I dislike annotations? see comments to `reifyAnnotationInfo`
+// case ann: AnnotationInfo => reifyAnnotationInfo(ann)
+ case pos: Position => reifyPosition(pos)
+ case mods: mirror.Modifiers => reifyModifiers(mods)
+ case xs: List[_] => reifyList(xs)
+ case s: String => Literal(Constant(s))
+ case v if isAnyVal(v) => Literal(Constant(v))
+ case null => Literal(Constant(null))
+ case _ =>
+ throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass))
+ }
+ } finally {
+ currents = currents.tail
+ }
}
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
index e700604612..4ab306a13f 100644
--- a/src/compiler/scala/reflect/reify/phases/Reshape.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -78,12 +78,6 @@ trait Reshape {
if (reifyDebug) println("unapplying unapply: " + tree)
val fun1 = extractExtractor(fun)
Apply(fun1, args).copyAttrs(unapply)
- case Literal(const @ Constant(tpe: Type)) =>
- // todo. implement this
- ???
- case Literal(const @ Constant(sym: Symbol)) =>
- // todo. implement this
- ???
case _ =>
tree
}
diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
index 6fc5f7ed8a..4048e94d0f 100644
--- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -14,11 +14,11 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol =
synchronized { super.connectModuleToClass(m, moduleClass) }
- override def newFreeTerm(name: TermName, info: Type, value: => Any, origin: String = null, newFlags: Long = 0L): FreeTerm =
- new FreeTerm(name, value, origin) with SynchronizedTermSymbol initFlags newFlags setInfo info
+ override def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTerm =
+ new FreeTerm(name, value, origin) with SynchronizedTermSymbol initFlags flags setInfo info
- override def newFreeType(name: TypeName, info: Type, value: => Any, origin: String = null, newFlags: Long = 0L): FreeType =
- new FreeType(name, value, origin) with SynchronizedTypeSymbol initFlags newFlags setInfo info
+ override def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeType =
+ new FreeType(name, value, origin) with SynchronizedTypeSymbol initFlags flags setInfo info
override protected def makeNoSymbol: NoSymbol = new NoSymbol with SynchronizedSymbol
diff --git a/src/compiler/scala/tools/nsc/ast/FreeVars.scala b/src/compiler/scala/tools/nsc/ast/FreeVars.scala
index 1bf36e8bf2..a1983d1834 100644
--- a/src/compiler/scala/tools/nsc/ast/FreeVars.scala
+++ b/src/compiler/scala/tools/nsc/ast/FreeVars.scala
@@ -13,9 +13,9 @@ trait FreeVars extends reflect.internal.FreeVars { self: Global =>
case Reified(_, symbolTable, _) =>
// logging free vars only when they are untyped prevents avalanches of duplicate messages
symbolTable foreach {
- case FreeTermDef(_, _, binding, origin) if settings.logFreeTerms.value && binding.tpe == null =>
+ case FreeTermDef(_, _, binding, _, origin) if settings.logFreeTerms.value && binding.tpe == null =>
reporter.echo(position, "free term: %s %s".format(showRaw(binding), origin))
- case FreeTypeDef(_, _, binding, origin) if settings.logFreeTypes.value && binding.tpe == null =>
+ case FreeTypeDef(_, _, binding, _, origin) if settings.logFreeTypes.value && binding.tpe == null =>
reporter.echo(position, "free type: %s %s".format(showRaw(binding), origin))
case _ =>
// do nothing
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 4fb9362ccc..30a79917c9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1161,7 +1161,8 @@ trait Implicits {
// todo. migrate hardcoded materialization in Implicits to corresponding implicit macros
var materializer = atPos(pos.focus)(Apply(TypeApply(Ident(TagMaterializers(tagClass)), List(TypeTree(tp))), List(prefix)))
if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer))
- success(materializer)
+ if (context.macrosEnabled) success(materializer)
+ else failure(materializer, "macros are disabled")
}
/** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest.