summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala14
-rw-r--r--src/reflect/scala/reflect/api/Universe.scala2
-rw-r--r--src/reflect/scala/reflect/api/package.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala74
-rw-r--r--src/reflect/scala/reflect/internal/Importers.scala664
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala5
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala13
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala13
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala19
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala93
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala6
-rw-r--r--src/reflect/scala/reflect/internal/util/TriState.scala26
-rw-r--r--src/reflect/scala/reflect/macros/Macro.scala39
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala4
-rw-r--r--src/reflect/scala/reflect/runtime/package.scala2
15 files changed, 580 insertions, 398 deletions
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index f4ada814af..f7a6a68946 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -296,6 +296,20 @@ trait Trees { self: Universe =>
def name: Name
}
+ /** The constructor/extractor for `RefTree` instances.
+ * @group Extractors
+ */
+ val RefTree: RefTreeExtractor
+
+ /** An extractor class to create and pattern match with syntax `RefTree(qual, name)`.
+ * This AST node corresponds to either Ident, Select or SelectFromTypeTree.
+ * @group Extractors
+ */
+ abstract class RefTreeExtractor {
+ def apply(qualifier: Tree, name: Name): RefTree
+ def unapply(refTree: RefTree): Option[(Tree, Name)]
+ }
+
/** A tree which defines a symbol-carrying entity.
* @group Trees
* @template
diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala
index 799fbd0dfb..cb629f9c5a 100644
--- a/src/reflect/scala/reflect/api/Universe.scala
+++ b/src/reflect/scala/reflect/api/Universe.scala
@@ -94,5 +94,5 @@ abstract class Universe extends Symbols
*/
// implementation is hardwired to `scala.reflect.reify.Taggers`
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
- def reify[T](expr: T): Expr[T] = ??? // macro
+ def reify[T](expr: T): Expr[T] = macro ???
}
diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala
index 14dcc9247f..a8f409e123 100644
--- a/src/reflect/scala/reflect/api/package.scala
+++ b/src/reflect/scala/reflect/api/package.scala
@@ -43,6 +43,6 @@ package object api {
// implementation is hardwired into `scala.reflect.reify.Taggers`
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
// todo. once we have implicit macros for tag generation, we can remove these anchors
- private[scala] def materializeWeakTypeTag[T](u: ApiUniverse): u.WeakTypeTag[T] = ??? // macro
- private[scala] def materializeTypeTag[T](u: ApiUniverse): u.TypeTag[T] = ??? // macro
+ private[scala] def materializeWeakTypeTag[T](u: ApiUniverse): u.WeakTypeTag[T] = macro ???
+ private[scala] def materializeTypeTag[T](u: ApiUniverse): u.TypeTag[T] = macro ???
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 5cd86b7eed..851fc98a32 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -111,8 +111,10 @@ trait Definitions extends api.StandardDefinitions {
/** Is symbol a numeric value class? */
def isNumericValueClass(sym: Symbol) = ScalaNumericValueClasses contains sym
- def isGetClass(sym: Symbol) =
- (sym.name == nme.getClass_) && flattensToEmpty(sym.paramss)
+ def isGetClass(sym: Symbol) = (
+ sym.name == nme.getClass_ // this condition is for performance only, this is called from `Typer#stabliize`.
+ && getClassMethods(sym)
+ )
lazy val UnitClass = valueClassSymbol(tpnme.Unit)
lazy val ByteClass = valueClassSymbol(tpnme.Byte)
@@ -491,8 +493,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val ReflectPackage = requiredModule[scala.reflect.`package`.type]
lazy val ReflectApiPackage = getPackageObjectIfDefined("scala.reflect.api") // defined in scala-reflect.jar, so we need to be careful
lazy val ReflectRuntimePackage = getPackageObjectIfDefined("scala.reflect.runtime") // defined in scala-reflect.jar, so we need to be careful
- def ReflectRuntimeUniverse = if (ReflectRuntimePackage != NoSymbol) getMemberValue(ReflectRuntimePackage, nme.universe) else NoSymbol
- def ReflectRuntimeCurrentMirror = if (ReflectRuntimePackage != NoSymbol) getMemberMethod(ReflectRuntimePackage, nme.currentMirror) else NoSymbol
+ def ReflectRuntimeUniverse = ReflectRuntimePackage.map(sym => getMemberValue(sym, nme.universe))
+ def ReflectRuntimeCurrentMirror = ReflectRuntimePackage.map(sym => getMemberMethod(sym, nme.currentMirror))
lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest)
lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifestFactory.type]
@@ -501,24 +503,38 @@ trait Definitions extends api.StandardDefinitions {
lazy val OptManifestClass = requiredClass[scala.reflect.OptManifest[_]]
lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type]
+ lazy val TreesClass = getClassIfDefined("scala.reflect.api.Trees") // defined in scala-reflect.jar, so we need to be careful
+ lazy val TreesTreeType = TreesClass.map(sym => getTypeMember(sym, tpnme.Tree))
+ object TreeType {
+ def unapply(tpe: Type): Boolean = unapply(tpe.typeSymbol)
+ def unapply(sym: Symbol): Boolean = sym.overrideChain contains TreesTreeType
+ }
+
lazy val ExprsClass = getClassIfDefined("scala.reflect.api.Exprs") // defined in scala-reflect.jar, so we need to be careful
- lazy val ExprClass = if (ExprsClass != NoSymbol) getMemberClass(ExprsClass, tpnme.Expr) else NoSymbol
- def ExprSplice = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.splice) else NoSymbol
- def ExprValue = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.value) else NoSymbol
+ lazy val ExprClass = ExprsClass.map(sym => getMemberClass(sym, tpnme.Expr))
+ def ExprSplice = ExprClass.map(sym => getMemberMethod(sym, nme.splice))
+ def ExprValue = ExprClass.map(sym => getMemberMethod(sym, nme.value))
+ object ExprClassOf {
+ def unapply(tpe: Type): Option[Type] = tpe.dealias match {
+ case ExistentialType(_, underlying) => unapply(underlying)
+ case TypeRef(_, ExprClass, t :: Nil) => Some(t)
+ case _ => None
+ }
+ }
lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]]
lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]]
lazy val TypeTagsClass = getClassIfDefined("scala.reflect.api.TypeTags") // defined in scala-reflect.jar, so we need to be careful
- lazy val WeakTypeTagClass = if (TypeTagsClass != NoSymbol) getMemberClass(TypeTagsClass, tpnme.WeakTypeTag) else NoSymbol
- lazy val WeakTypeTagModule = if (TypeTagsClass != NoSymbol) getMemberModule(TypeTagsClass, nme.WeakTypeTag) else NoSymbol
- lazy val TypeTagClass = if (TypeTagsClass != NoSymbol) getMemberClass(TypeTagsClass, tpnme.TypeTag) else NoSymbol
- lazy val TypeTagModule = if (TypeTagsClass != NoSymbol) getMemberModule(TypeTagsClass, nme.TypeTag) else NoSymbol
+ lazy val WeakTypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.WeakTypeTag))
+ lazy val WeakTypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.WeakTypeTag))
+ lazy val TypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.TypeTag))
+ lazy val TypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.TypeTag))
def materializeClassTag = getMemberMethod(ReflectPackage, nme.materializeClassTag)
- def materializeWeakTypeTag = if (ReflectApiPackage != NoSymbol) getMemberMethod(ReflectApiPackage, nme.materializeWeakTypeTag) else NoSymbol
- def materializeTypeTag = if (ReflectApiPackage != NoSymbol) getMemberMethod(ReflectApiPackage, nme.materializeTypeTag) else NoSymbol
+ def materializeWeakTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeWeakTypeTag))
+ def materializeTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeTypeTag))
lazy val ApiUniverseClass = getClassIfDefined("scala.reflect.api.Universe") // defined in scala-reflect.jar, so we need to be careful
- def ApiUniverseReify = if (ApiUniverseClass != NoSymbol) getMemberMethod(ApiUniverseClass, nme.reify) else NoSymbol
+ def ApiUniverseReify = ApiUniverseClass.map(sym => getMemberMethod(sym, nme.reify))
lazy val JavaUniverseClass = getClassIfDefined("scala.reflect.api.JavaUniverse") // defined in scala-reflect.jar, so we need to be careful
lazy val MirrorClass = getClassIfDefined("scala.reflect.api.Mirror") // defined in scala-reflect.jar, so we need to be careful
@@ -526,14 +542,18 @@ trait Definitions extends api.StandardDefinitions {
lazy val TypeCreatorClass = getClassIfDefined("scala.reflect.api.TypeCreator") // defined in scala-reflect.jar, so we need to be careful
lazy val TreeCreatorClass = getClassIfDefined("scala.reflect.api.TreeCreator") // defined in scala-reflect.jar, so we need to be careful
- lazy val MacroContextClass = getClassIfDefined("scala.reflect.macros.Context") // defined in scala-reflect.jar, so we need to be careful
- def MacroContextPrefix = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.prefix) else NoSymbol
- def MacroContextPrefixType = if (MacroContextClass != NoSymbol) getTypeMember(MacroContextClass, tpnme.PrefixType) else NoSymbol
- def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol
- lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl]
+ lazy val MacroClass = getClassIfDefined("scala.reflect.macros.Macro") // defined in scala-reflect.jar, so we need to be careful
+ lazy val MacroContextClass = getClassIfDefined("scala.reflect.macros.Context") // defined in scala-reflect.jar, so we need to be careful
+ def MacroContextPrefix = MacroContextClass.map(sym => getMemberMethod(sym, nme.prefix))
+ def MacroContextPrefixType = MacroContextClass.map(sym => getTypeMember(sym, tpnme.PrefixType))
+ def MacroContextUniverse = MacroContextClass.map(sym => getMemberMethod(sym, nme.universe))
+ def MacroContextExprClass = MacroContextClass.map(sym => getTypeMember(sym, tpnme.Expr))
+ def MacroContextWeakTypeTagClass = MacroContextClass.map(sym => getTypeMember(sym, tpnme.WeakTypeTag))
+ def MacroContextTreeType = MacroContextClass.map(sym => getTypeMember(sym, tpnme.Tree))
+ lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl]
- lazy val StringContextClass = requiredClass[scala.StringContext]
- def StringContext_f = getMemberMethod(StringContextClass, nme.f)
+ lazy val StringContextClass = requiredClass[scala.StringContext]
+ def StringContext_f = getMemberMethod(StringContextClass, nme.f)
lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature]
lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature]
@@ -640,6 +660,12 @@ trait Definitions extends api.StandardDefinitions {
}
def isTupleType(tp: Type) = isTupleTypeDirect(tp.dealiasWiden)
+ def isMacroBundleType(tp: Type) = {
+ val isNonTrivial = tp != ErrorType && tp != NothingTpe && tp != NullTpe
+ val isMacroCompatible = MacroClass != NoSymbol && tp <:< MacroClass.tpe
+ isNonTrivial && isMacroCompatible
+ }
+
lazy val ProductRootClass: ClassSymbol = requiredClass[scala.Product]
def Product_productArity = getMemberMethod(ProductRootClass, nme.productArity)
def Product_productElement = getMemberMethod(ProductRootClass, nme.productElement)
@@ -753,6 +779,12 @@ trait Definitions extends api.StandardDefinitions {
lazy val Any_isInstanceOf = newT1NullaryMethod(AnyClass, nme.isInstanceOf_, FINAL)(_ => BooleanTpe)
lazy val Any_asInstanceOf = newT1NullaryMethod(AnyClass, nme.asInstanceOf_, FINAL)(_.typeConstructor)
+ lazy val primitiveGetClassMethods = Set[Symbol](Any_getClass, AnyVal_getClass) ++ (
+ ScalaValueClasses map (_.tpe member nme.getClass_)
+ )
+
+ lazy val getClassMethods: Set[Symbol] = primitiveGetClassMethods + Object_getClass
+
// A type function from T => Class[U], used to determine the return
// type of getClass calls. The returned type is:
//
diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala
index b0d3cda629..f8584ac9b0 100644
--- a/src/reflect/scala/reflect/internal/Importers.scala
+++ b/src/reflect/scala/reflect/internal/Importers.scala
@@ -6,17 +6,17 @@ import scala.collection.mutable.WeakHashMap
import scala.ref.WeakReference
// SI-6241: move importers to a mirror
-trait Importers extends api.Importers { self: SymbolTable =>
+trait Importers extends api.Importers { to: SymbolTable =>
def mkImporter(from0: api.Universe): Importer { val from: from0.type } = (
- if (self eq from0) {
+ if (to eq from0) {
new Importer {
val from = from0
- val reverse = this.asInstanceOf[from.Importer{ val from: self.type }]
- def importSymbol(sym: from.Symbol) = sym.asInstanceOf[self.Symbol]
- def importType(tpe: from.Type) = tpe.asInstanceOf[self.Type]
- def importTree(tree: from.Tree) = tree.asInstanceOf[self.Tree]
- def importPosition(pos: from.Position) = pos.asInstanceOf[self.Position]
+ val reverse = this.asInstanceOf[from.Importer{ val from: to.type }]
+ def importSymbol(their: from.Symbol) = their.asInstanceOf[to.Symbol]
+ def importType(their: from.Type) = their.asInstanceOf[to.Type]
+ def importTree(their: from.Tree) = their.asInstanceOf[to.Tree]
+ def importPosition(their: from.Position) = their.asInstanceOf[to.Position]
}
} else {
// todo. fix this loophole
@@ -29,8 +29,8 @@ trait Importers extends api.Importers { self: SymbolTable =>
val from: SymbolTable
- protected lazy val symMap = new Cache[from.Symbol, Symbol]()
- protected lazy val tpeMap = new Cache[from.Type, Type]()
+ protected lazy val symMap = new Cache[from.Symbol, to.Symbol]()
+ protected lazy val tpeMap = new Cache[from.Type, to.Type]()
protected class Cache[K <: AnyRef, V <: AnyRef] extends WeakHashMap[K, WeakReference[V]] {
def weakGet(key: K): Option[V] = this get key flatMap WeakReference.unapply
def weakUpdate(key: K, value: V) = this.update(key, WeakReference(value))
@@ -50,158 +50,162 @@ trait Importers extends api.Importers { self: SymbolTable =>
}
object reverse extends from.StandardImporter {
- val from: self.type = self
+ val from: to.type = to
// FIXME this and reverse should be constantly kept in sync
// not just synced once upon the first usage of reverse
- for ((fromsym, WeakReference(mysym)) <- StandardImporter.this.symMap) symMap += ((mysym, WeakReference(fromsym)))
- for ((fromtpe, WeakReference(mytpe)) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, WeakReference(fromtpe)))
+ for ((theirsym, WeakReference(mysym)) <- StandardImporter.this.symMap) symMap += ((mysym, WeakReference(theirsym)))
+ for ((theirtpe, WeakReference(mytpe)) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, WeakReference(theirtpe)))
}
- // todo. careful import of positions
- def importPosition(pos: from.Position): Position =
- pos.asInstanceOf[Position]
+ // ============== SYMBOLS ==============
+
+ protected def recreatedSymbolCompleter(my: to.Symbol, their: from.Symbol) = {
+ // we lock the symbol that is imported for a very short period of time
+ // i.e. only for when type parameters of the symbol are being imported
+ // the lock is used to communicate to the recursive importSymbol calls
+ // that type parameters need to be created from scratch
+ // because otherwise type parameters are imported by looking into owner.typeParams
+ // which is obviously unavailable while the completer is being created
+ try {
+ my setFlag Flags.LOCKED
+ val mytypeParams = their.typeParams map importSymbol
+ new LazyPolyType(mytypeParams) with FlagAgnosticCompleter {
+ override def complete(my: to.Symbol): Unit = {
+ val theirCore = their.info match {
+ case from.PolyType(_, core) => core
+ case core => core
+ }
+ my setInfo GenPolyType(mytypeParams, importType(theirCore))
+ my setAnnotations (their.annotations map importAnnotationInfo)
+ }
+ }
+ } finally {
+ my resetFlag Flags.LOCKED
+ }
+ }
+
+ protected def recreateSymbol(their: from.Symbol): to.Symbol = {
+ val myowner = importSymbol(their.owner)
+ val mypos = importPosition(their.pos)
+ val myname = importName(their.name)
+ val myflags = their.flags
+ def linkReferenced(my: TermSymbol, their: from.TermSymbol, op: from.Symbol => Symbol): Symbol = {
+ symMap.weakUpdate(their, my)
+ my.referenced = op(their.referenced)
+ my
+ }
+ val my = their match {
+ case their: from.MethodSymbol =>
+ linkReferenced(myowner.newMethod(myname.toTermName, mypos, myflags), their, importSymbol)
+ case their: from.ModuleSymbol =>
+ val ret = linkReferenced(myowner.newModuleSymbol(myname.toTermName, mypos, myflags), their, importSymbol)
+ ret.associatedFile = their.associatedFile
+ ret
+ case their: from.FreeTermSymbol =>
+ newFreeTermSymbol(myname.toTermName, their.value, their.flags, their.origin) setInfo importType(their.info)
+ case their: from.FreeTypeSymbol =>
+ newFreeTypeSymbol(myname.toTypeName, their.flags, their.origin)
+ case their: from.TermSymbol =>
+ linkReferenced(myowner.newValue(myname.toTermName, mypos, myflags), their, importSymbol)
+ case their: from.TypeSkolem =>
+ val origin = their.unpackLocation match {
+ case null => null
+ case theirloc: from.Tree => importTree(theirloc)
+ case theirloc: from.Symbol => importSymbol(theirloc)
+ }
+ myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags)
+ case their: from.ModuleClassSymbol =>
+ val my = myowner.newModuleClass(myname.toTypeName, mypos, myflags)
+ symMap.weakUpdate(their, my)
+ my.sourceModule = importSymbol(their.sourceModule)
+ my
+ case their: from.ClassSymbol =>
+ val my = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
+ symMap.weakUpdate(their, my)
+ if (their.thisSym != their) {
+ my.typeOfThis = importType(their.typeOfThis)
+ my.thisSym setName importName(their.thisSym.name)
+ }
+ my.associatedFile = their.associatedFile
+ my
+ case their: from.TypeSymbol =>
+ myowner.newTypeSymbol(myname.toTypeName, mypos, myflags)
+ }
+ symMap.weakUpdate(their, my)
+ my setInfo recreatedSymbolCompleter(my, their)
+ }
- def importSymbol(sym0: from.Symbol): Symbol = {
- def doImport(sym: from.Symbol): Symbol =
- symMap weakGet sym match {
+ def importSymbol(their0: from.Symbol): Symbol = {
+ def cachedRecreateSymbol(their: from.Symbol): Symbol =
+ symMap weakGet their match {
case Some(result) => result
- case _ =>
- val myowner = importSymbol(sym.owner)
- val mypos = importPosition(sym.pos)
- val myname = importName(sym.name).toTermName
- val myflags = sym.flags
- def linkReferenced(mysym: TermSymbol, x: from.TermSymbol, op: from.Symbol => Symbol): Symbol = {
- symMap.weakUpdate(x, mysym)
- mysym.referenced = op(x.referenced)
- mysym
- }
- val mysym = sym match {
- case x: from.MethodSymbol =>
- linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol)
- case x: from.ModuleSymbol =>
- linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol)
- case x: from.FreeTermSymbol =>
- newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info)
- case x: from.FreeTypeSymbol =>
- newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin)
- case x: from.TermSymbol =>
- linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol)
- case x: from.TypeSkolem =>
- val origin = x.unpackLocation match {
- case null => null
- case y: from.Tree => importTree(y)
- case y: from.Symbol => importSymbol(y)
- }
- myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags)
- case x: from.ModuleClassSymbol =>
- val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags)
- symMap.weakUpdate(x, mysym)
- mysym.sourceModule = importSymbol(x.sourceModule)
- mysym
- case x: from.ClassSymbol =>
- val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
- symMap.weakUpdate(x, mysym)
- if (sym.thisSym != sym) {
- mysym.typeOfThis = importType(sym.typeOfThis)
- mysym.thisSym setName importName(sym.thisSym.name)
- }
- mysym
- case x: from.TypeSymbol =>
- myowner.newTypeSymbol(myname.toTypeName, mypos, myflags)
- }
- symMap.weakUpdate(sym, mysym)
- mysym setFlag Flags.LOCKED
- mysym setInfo {
- val mytypeParams = sym.typeParams map importSymbol
- new LazyPolyType(mytypeParams) with FlagAgnosticCompleter {
- override def complete(s: Symbol) {
- val result = sym.info match {
- case from.PolyType(_, res) => res
- case result => result
- }
- s setInfo GenPolyType(mytypeParams, importType(result))
- s setAnnotations (sym.annotations map importAnnotationInfo)
- }
- }
- }
- mysym resetFlag Flags.LOCKED
- } // end doImport
+ case _ => recreateSymbol(their)
+ }
- def importOrRelink: Symbol = {
- val sym = sym0 // makes sym visible in the debugger
- if (sym == null)
+ def recreateOrRelink: Symbol = {
+ val their = their0 // makes their visible in the debugger
+ if (their == null)
null
- else if (sym == from.NoSymbol)
+ else if (their == from.NoSymbol)
NoSymbol
- else if (sym.isRoot)
+ else if (their.isRoot)
rootMirror.RootClass // !!! replace with actual mirror when we move importers to the mirror
else {
- val name = sym.name
- val owner = sym.owner
- var scope = if (owner.isClass && !owner.isRefinementClass) owner.info else from.NoType
- var existing = scope.decl(name)
- if (sym.isModuleClass)
- existing = existing.moduleClass
-
- if (!existing.exists) scope = from.NoType
-
- val myname = importName(name)
- val myowner = importSymbol(owner)
- val myscope = if (scope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType
- var myexisting = if (myscope != NoType) myowner.info.decl(myname) else NoSymbol // cannot load myexisting in general case, because it creates cycles for methods
- if (sym.isModuleClass)
- myexisting = importSymbol(sym.sourceModule).moduleClass
-
- if (!sym.isOverloaded && myexisting.isOverloaded) {
- myexisting =
- if (sym.isMethod) {
- val localCopy = doImport(sym)
- myexisting filter (_.tpe matches localCopy.tpe)
- } else {
- myexisting filter (!_.isMethod)
+ val isModuleClass = their.isModuleClass
+ val isTparam = their.isTypeParameter && their.paramPos >= 0
+ val isOverloaded = their.isOverloaded
+
+ var theirscope = if (their.owner.isClass && !their.owner.isRefinementClass) their.owner.info else from.NoType
+ val theirexisting = if (isModuleClass) theirscope.decl(their.name).moduleClass else theirscope.decl(their.name)
+ if (!theirexisting.exists) theirscope = from.NoType
+
+ val myname = importName(their.name)
+ val myowner = importSymbol(their.owner)
+ val myscope = if (theirscope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType
+ val myexisting = {
+ if (isModuleClass) importSymbol(their.sourceModule).moduleClass
+ else if (isTparam) (if (myowner hasFlag Flags.LOCKED) NoSymbol else myowner.typeParams(their.paramPos))
+ else if (isOverloaded) myowner.newOverloaded(myowner.thisType, their.alternatives map importSymbol)
+ else {
+ def disambiguate(my: Symbol) = {
+ val result =
+ if (their.isMethod) {
+ val localCopy = cachedRecreateSymbol(their)
+ my filter (_.tpe matches localCopy.tpe)
+ } else {
+ my filter (!_.isMethod)
+ }
+ assert(!result.isOverloaded,
+ "import failure: cannot determine unique overloaded method alternative from\n "+
+ (result.alternatives map (_.defString) mkString "\n")+"\n that matches "+their+":"+their.tpe)
+ result
}
- assert(!myexisting.isOverloaded,
- "import failure: cannot determine unique overloaded method alternative from\n "+
- (myexisting.alternatives map (_.defString) mkString "\n")+"\n that matches "+sym+":"+sym.tpe)
- }
- val mysym = {
- if (sym.isOverloaded) {
- myowner.newOverloaded(myowner.thisType, sym.alternatives map importSymbol)
- } else if (sym.isTypeParameter && sym.paramPos >= 0 && !(myowner hasFlag Flags.LOCKED)) {
- assert(myowner.typeParams.length > sym.paramPos,
- "import failure: cannot determine parameter "+sym+" (#"+sym.paramPos+") in "+
- myowner+typeParamsString(myowner.rawInfo)+"\n original symbol was: "+
- sym.owner+from.typeParamsString(sym.owner.info))
- myowner.typeParams(sym.paramPos)
- } else {
- if (myexisting != NoSymbol) {
- myexisting
- } else {
- val mysym = doImport(sym)
-
- if (myscope != NoType) {
- assert(myowner.info.decls.lookup(myname) == NoSymbol, myname+" "+myowner.info.decl(myname)+" "+myexisting)
- myowner.info.decls enter mysym
- }
-
- mysym
- }
+ val myexisting = if (myscope != NoType) myscope.decl(myname) else NoSymbol
+ if (myexisting.isOverloaded) disambiguate(myexisting)
+ else myexisting
}
}
- mysym
+ myexisting.orElse {
+ val my = cachedRecreateSymbol(their)
+ if (myscope != NoType) {
+ assert(myscope.decls.lookup(myname) == NoSymbol, myname+" "+myscope.decl(myname)+" "+myexisting)
+ myscope.decls enter my
+ }
+ my
+ }
}
- } // end importOrRelink
+ } // end recreateOrRelink
- val sym = sym0
- symMap.weakGet(sym) match {
+ val their = their0
+ symMap.weakGet(their) match {
case Some(result) => result
case None =>
pendingSyms += 1
try {
- val result = importOrRelink
- symMap.weakUpdate(sym, result)
+ val result = recreateOrRelink
+ symMap.weakUpdate(their, result)
result
} finally {
pendingSyms -= 1
@@ -210,69 +214,70 @@ trait Importers extends api.Importers { self: SymbolTable =>
}
}
- def importType(tpe: from.Type): Type = {
- def doImport(tpe: from.Type): Type = tpe match {
- case from.TypeRef(pre, sym, args) =>
- TypeRef(importType(pre), importSymbol(sym), args map importType)
- case from.ThisType(clazz) =>
- ThisType(importSymbol(clazz))
- case from.SingleType(pre, sym) =>
- SingleType(importType(pre), importSymbol(sym))
- case from.MethodType(params, restpe) =>
- MethodType(params map importSymbol, importType(restpe))
- case from.PolyType(tparams, restpe) =>
- PolyType(tparams map importSymbol, importType(restpe))
- case from.NullaryMethodType(restpe) =>
- NullaryMethodType(importType(restpe))
- case from.ConstantType(constant @ from.Constant(_)) =>
- ConstantType(importConstant(constant))
- case from.SuperType(thistpe, supertpe) =>
- SuperType(importType(thistpe), importType(supertpe))
- case from.TypeBounds(lo, hi) =>
- TypeBounds(importType(lo), importType(hi))
- case from.BoundedWildcardType(bounds) =>
- BoundedWildcardType(importTypeBounds(bounds))
- case from.ClassInfoType(parents, decls, clazz) =>
- val myclazz = importSymbol(clazz)
- val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope
- val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz)
- myclazz setInfo GenPolyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope
- decls foreach importSymbol // will enter itself into myclazz
- myclazzTpe
- case from.RefinedType(parents, decls) =>
- RefinedType(parents map importType, importScope(decls), importSymbol(tpe.typeSymbol))
- case from.ExistentialType(tparams, restpe) =>
- newExistentialType(tparams map importSymbol, importType(restpe))
- case from.OverloadedType(pre, alts) =>
- OverloadedType(importType(pre), alts map importSymbol)
- case from.AntiPolyType(pre, targs) =>
- AntiPolyType(importType(pre), targs map importType)
- case x: from.TypeVar =>
- TypeVar(importType(x.origin), importTypeConstraint(x.constr), x.typeArgs map importType, x.params map importSymbol)
- case from.AnnotatedType(annots, tpe, selfsym) =>
- AnnotatedType(annots map importAnnotationInfo, importType(tpe), importSymbol(selfsym))
- case from.ErrorType =>
- ErrorType
- case from.WildcardType =>
- WildcardType
- case from.NoType =>
- NoType
- case from.NoPrefix =>
- NoPrefix
- case null =>
- null
- } // end doImport
-
- def importOrRelink: Type =
- doImport(tpe)
+ // ============== TYPES ==============
+
+ def recreateType(their: from.Type): Type = their match {
+ case from.TypeRef(pre, sym, args) =>
+ TypeRef(importType(pre), importSymbol(sym), args map importType)
+ case from.ThisType(clazz) =>
+ ThisType(importSymbol(clazz))
+ case from.SingleType(pre, sym) =>
+ SingleType(importType(pre), importSymbol(sym))
+ case from.MethodType(params, result) =>
+ MethodType(params map importSymbol, importType(result))
+ case from.PolyType(tparams, result) =>
+ PolyType(tparams map importSymbol, importType(result))
+ case from.NullaryMethodType(result) =>
+ NullaryMethodType(importType(result))
+ case from.ConstantType(constant @ from.Constant(_)) =>
+ ConstantType(importConstant(constant))
+ case from.SuperType(thistpe, supertpe) =>
+ SuperType(importType(thistpe), importType(supertpe))
+ case from.TypeBounds(lo, hi) =>
+ TypeBounds(importType(lo), importType(hi))
+ case from.BoundedWildcardType(bounds) =>
+ BoundedWildcardType(importType(bounds).asInstanceOf[TypeBounds])
+ case from.ClassInfoType(parents, decls, clazz) =>
+ val myclazz = importSymbol(clazz)
+ val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope
+ val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz)
+ myclazz setInfo GenPolyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope
+ decls foreach importSymbol // will enter itself into myclazz
+ myclazzTpe
+ case from.RefinedType(parents, decls) =>
+ RefinedType(parents map importType, importScope(decls), importSymbol(their.typeSymbol))
+ case from.ExistentialType(tparams, result) =>
+ newExistentialType(tparams map importSymbol, importType(result))
+ case from.OverloadedType(pre, alts) =>
+ OverloadedType(importType(pre), alts map importSymbol)
+ case from.AntiPolyType(pre, targs) =>
+ AntiPolyType(importType(pre), targs map importType)
+ case their: from.TypeVar =>
+ val myconstr = new TypeConstraint(their.constr.loBounds map importType, their.constr.hiBounds map importType)
+ myconstr.inst = importType(their.constr.inst)
+ TypeVar(importType(their.origin), myconstr, their.typeArgs map importType, their.params map importSymbol)
+ case from.AnnotatedType(annots, result, selfsym) =>
+ AnnotatedType(annots map importAnnotationInfo, importType(result), importSymbol(selfsym))
+ case from.ErrorType =>
+ ErrorType
+ case from.WildcardType =>
+ WildcardType
+ case from.NoType =>
+ NoType
+ case from.NoPrefix =>
+ NoPrefix
+ case null =>
+ null
+ }
- tpeMap.weakGet(tpe) match {
+ def importType(their: from.Type): Type = {
+ tpeMap.weakGet(their) match {
case Some(result) => result
case None =>
pendingTpes += 1
try {
- val result = importOrRelink
- tpeMap.weakUpdate(tpe, result)
+ val result = recreateType(their)
+ tpeMap.weakUpdate(their, result)
result
} finally {
pendingTpes -= 1
@@ -281,7 +286,136 @@ trait Importers extends api.Importers { self: SymbolTable =>
}
}
- def importTypeBounds(bounds: from.TypeBounds) = importType(bounds).asInstanceOf[TypeBounds]
+ // ============== TREES ==============
+
+ def recreatedTreeCompleter(their: from.Tree, my: to.Tree): Unit = {
+ if (their.canHaveAttrs) {
+ if (my.hasSymbolField) my.symbol = importSymbol(their.symbol)
+ my.pos = importPosition(their.pos)
+ (their, my) match {
+ case (their: from.TypeTree, my: to.TypeTree) =>
+ if (their.wasEmpty) my.defineType(importType(their.tpe)) else my.setType(importType(their.tpe))
+ case (_, _) =>
+ my.tpe = importType(their.tpe)
+ }
+ }
+ }
+
+ def recreateTree(their: from.Tree): to.Tree = their match {
+ case from.ClassDef(mods, name, tparams, impl) =>
+ new ClassDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTemplate(impl))
+ case from.PackageDef(pid, stats) =>
+ new PackageDef(importRefTree(pid), stats map importTree)
+ case from.ModuleDef(mods, name, impl) =>
+ new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl))
+ case from.emptyValDef =>
+ emptyValDef
+ case from.pendingSuperCall =>
+ pendingSuperCall
+ case from.ValDef(mods, name, tpt, rhs) =>
+ new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs))
+ case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ new DefDef(importModifiers(mods), importName(name).toTermName, tparams map importTypeDef, mmap(vparamss)(importValDef), importTree(tpt), importTree(rhs))
+ case from.TypeDef(mods, name, tparams, rhs) =>
+ new TypeDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTree(rhs))
+ case from.LabelDef(name, params, rhs) =>
+ new LabelDef(importName(name).toTermName, params map importIdent, importTree(rhs))
+ case from.Import(expr, selectors) =>
+ new Import(importTree(expr), selectors map importImportSelector)
+ case from.Template(parents, self, body) =>
+ new Template(parents map importTree, importValDef(self), body map importTree)
+ case from.Block(stats, expr) =>
+ new Block(stats map importTree, importTree(expr))
+ case from.CaseDef(pat, guard, body) =>
+ new CaseDef(importTree(pat), importTree(guard), importTree(body))
+ case from.Alternative(trees) =>
+ new Alternative(trees map importTree)
+ case from.Star(elem) =>
+ new Star(importTree(elem))
+ case from.Bind(name, body) =>
+ new Bind(importName(name), importTree(body))
+ case from.UnApply(fun, args) =>
+ new UnApply(importTree(fun), args map importTree)
+ case from.ArrayValue(elemtpt ,elems) =>
+ new ArrayValue(importTree(elemtpt), elems map importTree)
+ case from.Function(vparams, body) =>
+ new Function(vparams map importValDef, importTree(body))
+ case from.Assign(lhs, rhs) =>
+ new Assign(importTree(lhs), importTree(rhs))
+ case from.AssignOrNamedArg(lhs, rhs) =>
+ new AssignOrNamedArg(importTree(lhs), importTree(rhs))
+ case from.If(cond, thenp, elsep) =>
+ new If(importTree(cond), importTree(thenp), importTree(elsep))
+ case from.Match(selector, cases) =>
+ new Match(importTree(selector), cases map importCaseDef)
+ case from.Return(expr) =>
+ new Return(importTree(expr))
+ case from.Try(block, catches, finalizer) =>
+ new Try(importTree(block), catches map importCaseDef, importTree(finalizer))
+ case from.Throw(expr) =>
+ new Throw(importTree(expr))
+ case from.New(tpt) =>
+ new New(importTree(tpt))
+ case from.Typed(expr, tpt) =>
+ new Typed(importTree(expr), importTree(tpt))
+ case from.TypeApply(fun, args) =>
+ new TypeApply(importTree(fun), args map importTree)
+ case from.Apply(fun, args) => their match {
+ case _: from.ApplyToImplicitArgs =>
+ new ApplyToImplicitArgs(importTree(fun), args map importTree)
+ case _: from.ApplyImplicitView =>
+ new ApplyImplicitView(importTree(fun), args map importTree)
+ case _ =>
+ new Apply(importTree(fun), args map importTree)
+ }
+ case from.ApplyDynamic(qual, args) =>
+ new ApplyDynamic(importTree(qual), args map importTree)
+ case from.Super(qual, mix) =>
+ new Super(importTree(qual), importName(mix).toTypeName)
+ case from.This(qual) =>
+ new This(importName(qual).toTypeName)
+ case from.Select(qual, name) =>
+ new Select(importTree(qual), importName(name))
+ case from.Ident(name) =>
+ new Ident(importName(name))
+ case from.ReferenceToBoxed(ident) =>
+ new ReferenceToBoxed(importTree(ident) match { case ident: Ident => ident })
+ case from.Literal(constant @ from.Constant(_)) =>
+ new Literal(importConstant(constant))
+ case theirtt @ from.TypeTree() =>
+ val mytt = TypeTree()
+ if (theirtt.original != null) mytt.setOriginal(importTree(theirtt.original))
+ mytt
+ case from.Annotated(annot, arg) =>
+ new Annotated(importTree(annot), importTree(arg))
+ case from.SingletonTypeTree(ref) =>
+ new SingletonTypeTree(importTree(ref))
+ case from.SelectFromTypeTree(qual, name) =>
+ new SelectFromTypeTree(importTree(qual), importName(name).toTypeName)
+ case from.CompoundTypeTree(templ) =>
+ new CompoundTypeTree(importTemplate(templ))
+ case from.AppliedTypeTree(tpt, args) =>
+ new AppliedTypeTree(importTree(tpt), args map importTree)
+ case from.TypeBoundsTree(lo, hi) =>
+ new TypeBoundsTree(importTree(lo), importTree(hi))
+ case from.ExistentialTypeTree(tpt, whereClauses) =>
+ new ExistentialTypeTree(importTree(tpt), whereClauses map importTree)
+ case from.EmptyTree =>
+ EmptyTree
+ case null =>
+ null
+ }
+
+ def importTree(their: from.Tree): Tree = {
+ val my = recreateTree(their)
+ if (my != null) {
+ addFixup(recreatedTreeCompleter(their, my))
+ tryFixup()
+ }
+ my
+ }
+
+ // ============== MISCELLANEOUS ==============
def importAnnotationInfo(ann: from.AnnotationInfo): AnnotationInfo = {
val atp1 = importType(ann.atp)
@@ -302,11 +436,9 @@ trait Importers extends api.Importers { self: SymbolTable =>
NestedAnnotArg(importAnnotationInfo(annInfo))
}
- def importTypeConstraint(constr: from.TypeConstraint): TypeConstraint = {
- val result = new TypeConstraint(constr.loBounds map importType, constr.hiBounds map importType)
- result.inst = importType(constr.inst)
- result
- }
+ // todo. careful import of positions
+ def importPosition(their: from.Position): to.Position =
+ their.asInstanceOf[Position]
// !!! todo: override to cater for PackageScopes
def importScope(decls: from.Scope): Scope =
@@ -314,138 +446,12 @@ trait Importers extends api.Importers { self: SymbolTable =>
def importName(name: from.Name): Name =
if (name.isTypeName) newTypeName(name.toString) else newTermName(name.toString)
- def importTypeName(name: from.TypeName): TypeName = importName(name).toTypeName
def importModifiers(mods: from.Modifiers): Modifiers =
new Modifiers(mods.flags, importName(mods.privateWithin), mods.annotations map importTree)
def importImportSelector(sel: from.ImportSelector): ImportSelector =
new ImportSelector(importName(sel.name), sel.namePos, if (sel.rename != null) importName(sel.rename) else null, sel.renamePos)
-
- def importTree(tree: from.Tree): Tree = {
- val mytree = tree match {
- case from.ClassDef(mods, name, tparams, impl) =>
- new ClassDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTemplate(impl))
- case from.PackageDef(pid, stats) =>
- new PackageDef(importRefTree(pid), stats map importTree)
- case from.ModuleDef(mods, name, impl) =>
- new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl))
- case from.emptyValDef =>
- emptyValDef
- case from.pendingSuperCall =>
- pendingSuperCall
- case from.ValDef(mods, name, tpt, rhs) =>
- new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs))
- case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- new DefDef(importModifiers(mods), importName(name).toTermName, tparams map importTypeDef, mmap(vparamss)(importValDef), importTree(tpt), importTree(rhs))
- case from.TypeDef(mods, name, tparams, rhs) =>
- new TypeDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTree(rhs))
- case from.LabelDef(name, params, rhs) =>
- new LabelDef(importName(name).toTermName, params map importIdent, importTree(rhs))
- case from.Import(expr, selectors) =>
- new Import(importTree(expr), selectors map importImportSelector)
- case from.Template(parents, self, body) =>
- new Template(parents map importTree, importValDef(self), body map importTree)
- case from.Block(stats, expr) =>
- new Block(stats map importTree, importTree(expr))
- case from.CaseDef(pat, guard, body) =>
- new CaseDef(importTree(pat), importTree(guard), importTree(body))
- case from.Alternative(trees) =>
- new Alternative(trees map importTree)
- case from.Star(elem) =>
- new Star(importTree(elem))
- case from.Bind(name, body) =>
- new Bind(importName(name), importTree(body))
- case from.UnApply(fun, args) =>
- new UnApply(importTree(fun), args map importTree)
- case from.ArrayValue(elemtpt ,elems) =>
- new ArrayValue(importTree(elemtpt), elems map importTree)
- case from.Function(vparams, body) =>
- new Function(vparams map importValDef, importTree(body))
- case from.Assign(lhs, rhs) =>
- new Assign(importTree(lhs), importTree(rhs))
- case from.AssignOrNamedArg(lhs, rhs) =>
- new AssignOrNamedArg(importTree(lhs), importTree(rhs))
- case from.If(cond, thenp, elsep) =>
- new If(importTree(cond), importTree(thenp), importTree(elsep))
- case from.Match(selector, cases) =>
- new Match(importTree(selector), cases map importCaseDef)
- case from.Return(expr) =>
- new Return(importTree(expr))
- case from.Try(block, catches, finalizer) =>
- new Try(importTree(block), catches map importCaseDef, importTree(finalizer))
- case from.Throw(expr) =>
- new Throw(importTree(expr))
- case from.New(tpt) =>
- new New(importTree(tpt))
- case from.Typed(expr, tpt) =>
- new Typed(importTree(expr), importTree(tpt))
- case from.TypeApply(fun, args) =>
- new TypeApply(importTree(fun), args map importTree)
- case from.Apply(fun, args) => tree match {
- case _: from.ApplyToImplicitArgs =>
- new ApplyToImplicitArgs(importTree(fun), args map importTree)
- case _: from.ApplyImplicitView =>
- new ApplyImplicitView(importTree(fun), args map importTree)
- case _ =>
- new Apply(importTree(fun), args map importTree)
- }
- case from.ApplyDynamic(qual, args) =>
- new ApplyDynamic(importTree(qual), args map importTree)
- case from.Super(qual, mix) =>
- new Super(importTree(qual), importTypeName(mix))
- case from.This(qual) =>
- new This(importName(qual).toTypeName)
- case from.Select(qual, name) =>
- new Select(importTree(qual), importName(name))
- case from.Ident(name) =>
- new Ident(importName(name))
- case from.ReferenceToBoxed(ident) =>
- new ReferenceToBoxed(importTree(ident) match { case ident: Ident => ident })
- case from.Literal(constant @ from.Constant(_)) =>
- new Literal(importConstant(constant))
- case from.TypeTree() =>
- new TypeTree()
- case from.Annotated(annot, arg) =>
- new Annotated(importTree(annot), importTree(arg))
- case from.SingletonTypeTree(ref) =>
- new SingletonTypeTree(importTree(ref))
- case from.SelectFromTypeTree(qual, name) =>
- new SelectFromTypeTree(importTree(qual), importName(name).toTypeName)
- case from.CompoundTypeTree(templ) =>
- new CompoundTypeTree(importTemplate(templ))
- case from.AppliedTypeTree(tpt, args) =>
- new AppliedTypeTree(importTree(tpt), args map importTree)
- case from.TypeBoundsTree(lo, hi) =>
- new TypeBoundsTree(importTree(lo), importTree(hi))
- case from.ExistentialTypeTree(tpt, whereClauses) =>
- new ExistentialTypeTree(importTree(tpt), whereClauses map importTree)
- case from.EmptyTree =>
- EmptyTree
- case null =>
- null
- }
- addFixup({
- if (mytree != null) {
- val mysym = if (tree.hasSymbolField) importSymbol(tree.symbol) else NoSymbol
- val mytpe = importType(tree.tpe)
-
- mytree match {
- case mytt: TypeTree =>
- val tt = tree.asInstanceOf[from.TypeTree]
- if (mytree.hasSymbolField) mytt.symbol = mysym
- if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe)
- if (tt.original != null) mytt.setOriginal(importTree(tt.original))
- case _ =>
- if (mytree.hasSymbolField) mytree.symbol = importSymbol(tree.symbol)
- mytree setType importType(tree.tpe)
- }
- }
- })
- tryFixup()
- mytree
- }
-
def importValDef(tree: from.ValDef): ValDef = importTree(tree).asInstanceOf[ValDef]
def importTypeDef(tree: from.TypeDef): TypeDef = importTree(tree).asInstanceOf[TypeDef]
def importTemplate(tree: from.Template): Template = importTree(tree).asInstanceOf[Template]
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index a20307882d..81fffc833c 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -8,6 +8,7 @@ package reflect
package internal
import java.security.MessageDigest
+import java.util.UUID.randomUUID
import Chars.isOperatorPart
import scala.annotation.switch
import scala.language.implicitConversions
@@ -290,6 +291,9 @@ trait StdNames {
val FAKE_LOCAL_THIS: NameType = "this$"
val LAZY_LOCAL: NameType = "$lzy"
val LAZY_SLOW_SUFFIX: NameType = "$lzycompute"
+ val MACRO_INVOKER_PACKAGE: NameType = "scala.reflect.macros.synthetic"
+ // TODO: if I use dollars in MACRO_INVOKER_SUFFIX, as in "$Invoker$", then Scala reflection fails to load implementations
+ val MACRO_INVOKER_SUFFIX: NameType = "Invoker"
val UNIVERSE_BUILD_PREFIX: NameType = "$u.build."
val UNIVERSE_PREFIX: NameType = "$u."
val UNIVERSE_SHORT: NameType = "$u"
@@ -584,6 +588,7 @@ trait StdNames {
val box: NameType = "box"
val build : NameType = "build"
val bytes: NameType = "bytes"
+ val c: NameType = "c"
val canEqual_ : NameType = "canEqual"
val checkInitialized: NameType = "checkInitialized"
val classOf: NameType = "classOf"
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index e9ef9c7945..d1e8a04553 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -836,8 +836,17 @@ abstract class TreeInfo {
}
def unapply(tree: Tree) = refPart(tree) match {
- case ref: RefTree => Some((ref.qualifier.symbol, ref.symbol, dissectApplied(tree).targs))
- case _ => None
+ case ref: RefTree => {
+ val isBundle = definitions.isMacroBundleType(ref.qualifier.tpe)
+ val owner =
+ if (isBundle) ref.qualifier.tpe.typeSymbol
+ else {
+ val sym = ref.qualifier.symbol
+ if (sym.isModule) sym.moduleClass else sym
+ }
+ Some((isBundle, owner, ref.symbol, dissectApplied(tree).targs))
+ }
+ case _ => None
}
}
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 833adb99c7..8781423a6d 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -253,6 +253,19 @@ trait Trees extends api.Trees { self: SymbolTable =>
def name: Name
}
+ object RefTree extends RefTreeExtractor {
+ def apply(qualifier: Tree, name: Name): RefTree = qualifier match {
+ case EmptyTree =>
+ Ident(name)
+ case qual if qual.isTerm =>
+ Select(qual, name)
+ case qual if qual.isType =>
+ assert(name.isTypeName, s"qual = $qual, name = $name")
+ SelectFromTypeTree(qual, name.toTypeName)
+ }
+ def unapply(refTree: RefTree): Option[(Tree, Name)] = Some((refTree.qualifier, refTree.name))
+ }
+
abstract class DefTree extends SymTree with NameTree with DefTreeApi {
def name: Name
override def isDef = true
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index a435292185..0a50eb8ecc 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -1066,6 +1066,14 @@ trait Types
continue = false
val bcs0 = baseClasses
var bcs = bcs0
+ // omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ def admitPrivateLocal(owner: Symbol): Boolean = {
+ val selectorClass = this match {
+ case tt: ThisType => tt.sym // SI-7507 the first base class is not necessarily the selector class.
+ case _ => bcs0.head
+ }
+ selectorClass.hasTransOwner(owner)
+ }
while (!bcs.isEmpty) {
val decls = bcs.head.info.decls
var entry = decls.lookupEntry(name)
@@ -1075,10 +1083,10 @@ trait Types
if ((flags & required) == required) {
val excl = flags & excluded
if (excl == 0L &&
- (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (
(bcs eq bcs0) ||
(flags & PrivateLocal) != PrivateLocal ||
- (bcs0.head.hasTransOwner(bcs.head)))) {
+ admitPrivateLocal(bcs.head))) {
if (name.isTypeName || (stableOnly && sym.isStable && !sym.hasVolatileType)) {
if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
return sym
@@ -3118,10 +3126,9 @@ trait Types
sameLength(typeArgs, tp.typeArgs) && {
val lhs = if (isLowerBound) tp.typeArgs else typeArgs
val rhs = if (isLowerBound) typeArgs else tp.typeArgs
- // this is a higher-kinded type var with same arity as tp.
- // side effect: adds the type constructor itself as a bound
- addBound(tp.typeConstructor)
- isSubArgs(lhs, rhs, params, AnyDepth)
+ // This is a higher-kinded type var with same arity as tp.
+ // If so (see SI-7517), side effect: adds the type constructor itself as a bound.
+ isSubArgs(lhs, rhs, params, AnyDepth) && { addBound(tp.typeConstructor); true }
}
}
// The type with which we can successfully unify can be hidden
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index 711a94d7bd..63f17dff34 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -4,7 +4,7 @@ package internal
package tpe
import scala.collection.{ mutable }
-import util.Statistics
+import util.{ Statistics, TriState }
import scala.annotation.tailrec
trait TypeComparers {
@@ -118,30 +118,20 @@ trait TypeComparers {
// if (subsametypeRecursions == 0) undoLog.clear()
}
- private def isSameType1(tp1: Type, tp2: Type): Boolean = {
- if ((tp1 eq tp2) ||
- (tp1 eq ErrorType) || (tp1 eq WildcardType) ||
- (tp2 eq ErrorType) || (tp2 eq WildcardType))
- true
- else if ((tp1 eq NoType) || (tp2 eq NoType))
- false
- else if (tp1 eq NoPrefix) // !! I do not see how this would be warranted by the spec
- tp2.typeSymbol.isPackageClass
- else if (tp2 eq NoPrefix) // !! I do not see how this would be warranted by the spec
- tp1.typeSymbol.isPackageClass
- else if (tp1.isInstanceOf[AnnotatedType] || tp2.isInstanceOf[AnnotatedType])
- annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && (tp1.withoutAnnotations =:= tp2.withoutAnnotations)
- else {
- // We flush out any AnnotatedTypes before calling isSameType2 because
- // unlike most other subclasses of Type, we have to allow for equivalence of any
- // combination of { tp1, tp2 } { is, is not } an AnnotatedType - this because the
- // logic of "annotationsConform" is arbitrary and unknown.
- isSameType2(tp1, tp2) || {
- val tp1n = normalizePlus(tp1)
- val tp2n = normalizePlus(tp2)
- ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n)
- }
- }
+ // @pre: at least one argument has annotations
+ private def sameAnnotatedTypes(tp1: Type, tp2: Type) = (
+ annotationsConform(tp1, tp2)
+ && annotationsConform(tp2, tp1)
+ && (tp1.withoutAnnotations =:= tp2.withoutAnnotations)
+ )
+ // We flush out any AnnotatedTypes before calling isSameType2 because
+ // unlike most other subclasses of Type, we have to allow for equivalence of any
+ // combination of { tp1, tp2 } { is, is not } an AnnotatedType - this because the
+ // logic of "annotationsConform" is arbitrary and unknown.
+ private def isSameType1(tp1: Type, tp2: Type): Boolean = typeRelationPreCheck(tp1, tp2) match {
+ case state if state.isKnown => state.booleanValue
+ case _ if typeHasAnnotations(tp1) || typeHasAnnotations(tp2) => sameAnnotatedTypes(tp1, tp2)
+ case _ => isSameType2(tp1, tp2)
}
private def isSameHKTypes(tp1: Type, tp2: Type) = (
@@ -186,6 +176,8 @@ trait TypeComparers {
}
def isSameType2(tp1: Type, tp2: Type): Boolean = {
+ def retry(lhs: Type, rhs: Type) = ((lhs ne tp1) || (rhs ne tp2)) && isSameType(lhs, rhs)
+
/* Here we highlight those unfortunate type-like constructs which
* are hidden bundles of mutable state, cruising the type system picking
* up any type constraints naive enough to get into their hot rods.
@@ -236,6 +228,7 @@ trait TypeComparers {
|| sameSingletonType
|| mutateNonTypeConstructs(tp1, tp2)
|| mutateNonTypeConstructs(tp2, tp1)
+ || retry(normalizePlus(tp1), normalizePlus(tp2))
)
}
@@ -276,12 +269,12 @@ trait TypeComparers {
else
try {
pendingSubTypes += p
- isSubType2(tp1, tp2, depth)
+ isSubType1(tp1, tp2, depth)
} finally {
pendingSubTypes -= p
}
} else {
- isSubType2(tp1, tp2, depth)
+ isSubType1(tp1, tp2, depth)
}
} finally if (!result) undoLog.undoTo(before)
@@ -294,6 +287,39 @@ trait TypeComparers {
// if (subsametypeRecursions == 0) undoLog.clear()
}
+ /** Check whether the subtype or type equivalence relationship
+ * between the argument is predetermined. Returns a tri-state
+ * value: True means the arguments are always sub/same types,
+ * False means they never are, and Unknown means the caller
+ * will have to figure things out.
+ */
+ private def typeRelationPreCheck(tp1: Type, tp2: Type): TriState = {
+ def isTrue = (
+ (tp1 eq tp2)
+ || isErrorOrWildcard(tp1)
+ || isErrorOrWildcard(tp2)
+ || (tp1 eq NoPrefix) && tp2.typeSymbol.isPackageClass // !! I do not see how this would be warranted by the spec
+ || (tp2 eq NoPrefix) && tp1.typeSymbol.isPackageClass // !! I do not see how this would be warranted by the spec
+ )
+ // isFalse, assuming !isTrue
+ def isFalse = (
+ (tp1 eq NoType)
+ || (tp2 eq NoType)
+ || (tp1 eq NoPrefix)
+ || (tp2 eq NoPrefix)
+ )
+
+ if (isTrue) TriState.True
+ else if (isFalse) TriState.False
+ else TriState.Unknown
+ }
+
+ private def isSubType1(tp1: Type, tp2: Type, depth: Int): Boolean = typeRelationPreCheck(tp1, tp2) match {
+ case state if state.isKnown => state.booleanValue
+ case _ if typeHasAnnotations(tp1) || typeHasAnnotations(tp2) => annotationsConform(tp1, tp2) && (tp1.withoutAnnotations <:< tp2.withoutAnnotations)
+ case _ => isSubType2(tp1, tp2, depth)
+ }
+
private def isPolySubType(tp1: PolyType, tp2: PolyType): Boolean = {
val PolyType(tparams1, res1) = tp1
val PolyType(tparams2, res2) = tp2
@@ -332,12 +358,13 @@ trait TypeComparers {
/** Does type `tp1` conform to `tp2`? */
private def isSubType2(tp1: Type, tp2: Type, depth: Int): Boolean = {
- if ((tp1 eq tp2) || isErrorOrWildcard(tp1) || isErrorOrWildcard(tp2)) return true
- if ((tp1 eq NoType) || (tp2 eq NoType)) return false
- if (tp1 eq NoPrefix) return (tp2 eq NoPrefix) || tp2.typeSymbol.isPackageClass // !! I do not see how the "isPackageClass" would be warranted by the spec
- if (tp2 eq NoPrefix) return tp1.typeSymbol.isPackageClass
- if (isSingleType(tp1) && isSingleType(tp2) || isConstantType(tp1) && isConstantType(tp2)) return tp1 =:= tp2
- if (tp1.isHigherKinded || tp2.isHigherKinded) return isHKSubType(tp1, tp2, depth)
+ def retry(lhs: Type, rhs: Type) = ((lhs ne tp1) || (rhs ne tp2)) && isSubType(lhs, rhs, depth)
+
+ if (isSingleType(tp1) && isSingleType(tp2) || isConstantType(tp1) && isConstantType(tp2))
+ return (tp1 =:= tp2) || retry(tp1.underlying, tp2)
+
+ if (tp1.isHigherKinded || tp2.isHigherKinded)
+ return isHKSubType(tp1, tp2, depth)
/* First try, on the right:
* - unwrap Annotated types, BoundedWildcardTypes,
diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala
index a9a1285de3..580ada8254 100644
--- a/src/reflect/scala/reflect/internal/transform/Erasure.scala
+++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala
@@ -55,9 +55,13 @@ trait Erasure {
}
}
+ /** Arrays despite their finality may turn up as refined type parents,
+ * e.g. with "tagged types" like Array[Int] with T.
+ */
protected def unboundedGenericArrayLevel(tp: Type): Int = tp match {
case GenericArray(level, core) if !(core <:< AnyRefTpe) => level
- case _ => 0
+ case RefinedType(ps, _) if ps.nonEmpty => logResult(s"Unbounded generic level for $tp is")(ps map unboundedGenericArrayLevel max)
+ case _ => 0
}
// @M #2585 when generating a java generic signature that includes
diff --git a/src/reflect/scala/reflect/internal/util/TriState.scala b/src/reflect/scala/reflect/internal/util/TriState.scala
new file mode 100644
index 0000000000..c7a35d4637
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/util/TriState.scala
@@ -0,0 +1,26 @@
+package scala
+package reflect
+package internal
+package util
+
+import TriState._
+
+/** A simple true/false/unknown value, for those days when
+ * true and false don't quite partition the space.
+ */
+final class TriState private (val value: Int) extends AnyVal {
+ def isKnown = this != Unknown
+ def booleanValue = this match {
+ case True => true
+ case False => false
+ case _ => sys.error("Not a Boolean value")
+ }
+}
+
+object TriState {
+ implicit def booleanToTriState(b: Boolean): TriState = if (b) True else False
+
+ val Unknown = new TriState(-1)
+ val False = new TriState(0)
+ val True = new TriState(1)
+}
diff --git a/src/reflect/scala/reflect/macros/Macro.scala b/src/reflect/scala/reflect/macros/Macro.scala
new file mode 100644
index 0000000000..44bedf483d
--- /dev/null
+++ b/src/reflect/scala/reflect/macros/Macro.scala
@@ -0,0 +1,39 @@
+package scala.reflect
+package macros
+
+/**
+ * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
+ *
+ * Traditionally macro implementations are defined as methods,
+ * but this trait provides an alternative way of encoding macro impls as
+ * bundles, traits which extend `scala.reflect.macros.Macro`.
+ *
+ * Instead of:
+ *
+ * def impl[T: c.WeakTypeTag](c: Context)(x: c.Expr[Int]) = ...
+ *
+ * One can write:
+ *
+ * trait Impl extends Macro {
+ * def apply[T: c.WeakTypeTag](x: c.Expr[Int]) = ...
+ * }
+ *
+ * Without changing anything else at all.
+ *
+ * This language feature is useful in itself in cases when macro implementations
+ * are complex and need to be modularized. State of the art technique of addressing this need is quite heavyweight:
+ * http://docs.scala-lang.org/overviews/macros/overview.html#writing_bigger_macros.
+ *
+ * However utility of this approach to writing macros isn't limited to just convenience.
+ * When a macro implementation becomes not just a function, but a full-fledged module,
+ * it can define callbacks that will be called by the compiler upon interesting events.
+ * In subsequent commits I will add support for programmable type inference
+ */
+trait Macro {
+ /** The context to be used by the macro implementation.
+ *
+ * Vanilla macro implementations have to carry it in their signatures, however when a macro is a full-fledged module,
+ * it can define the context next to the implementation, makes implementation signature more lightweight.
+ */
+ val c: Context
+}
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index adee155db0..a3684f602f 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -972,8 +972,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
javaTypeToValueClass(jclazz) orElse lookupClass
assert (cls.isType,
- sm"""${if (cls == NoSymbol) "not a type: symbol" else "no symbol could be"}
- | loaded from $jclazz in $owner with name $simpleName and classloader $classLoader""")
+ (if (cls != NoSymbol) s"not a type: symbol $cls" else "no symbol could be") +
+ s" loaded from $jclazz in $owner with name $simpleName and classloader $classLoader")
cls.asClass
}
diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala
index 0354b424d2..41c1310e17 100644
--- a/src/reflect/scala/reflect/runtime/package.scala
+++ b/src/reflect/scala/reflect/runtime/package.scala
@@ -21,7 +21,7 @@ package object runtime {
*/
// implementation hardwired to the `currentMirror` method below
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
- def currentMirror: universe.Mirror = ??? // macro
+ def currentMirror: universe.Mirror = macro ???
}
package runtime {