diff options
Diffstat (limited to 'src')
138 files changed, 3882 insertions, 4275 deletions
diff --git a/src/actors-migration/scala/actors/Pattern.scala b/src/actors-migration/scala/actors/Pattern.scala index fa2db79152..a97ee3ba07 100644 --- a/src/actors-migration/scala/actors/Pattern.scala +++ b/src/actors-migration/scala/actors/Pattern.scala @@ -1,6 +1,6 @@ package scala.actors -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import scala.language.implicitConversions object pattern { diff --git a/src/actors-migration/scala/actors/StashingActor.scala b/src/actors-migration/scala/actors/StashingActor.scala index 29f370a3e2..775d115d0b 100644 --- a/src/actors-migration/scala/actors/StashingActor.scala +++ b/src/actors-migration/scala/actors/StashingActor.scala @@ -1,7 +1,7 @@ package scala.actors import scala.collection._ -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import java.util.concurrent.TimeUnit import scala.language.implicitConversions diff --git a/src/actors-migration/scala/actors/Timeout.scala b/src/actors-migration/scala/actors/Timeout.scala index 5540d2880e..c3017d8569 100644 --- a/src/actors-migration/scala/actors/Timeout.scala +++ b/src/actors-migration/scala/actors/Timeout.scala @@ -8,7 +8,7 @@ package scala.actors -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import java.util.concurrent.TimeUnit import scala.language.implicitConversions diff --git a/src/actors/scala/actors/ActorRef.scala b/src/actors/scala/actors/ActorRef.scala index 8f70b13e01..7768f04c2b 100644 --- a/src/actors/scala/actors/ActorRef.scala +++ b/src/actors/scala/actors/ActorRef.scala @@ -1,7 +1,7 @@ package scala.actors import java.util.concurrent.TimeoutException -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration /** * Trait used for migration of Scala actors to Akka. diff --git a/src/build/bnd/continuations.bnd b/src/build/bnd/continuations.bnd new file mode 100644 index 0000000000..748502f653 --- /dev/null +++ b/src/build/bnd/continuations.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Continuations Plugin +Bundle-SymbolicName: org.scala-lang.plugins.continuations +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/build/bnd/scala-actors-migration.bnd b/src/build/bnd/scala-actors-migration.bnd new file mode 100644 index 0000000000..2cddfb620a --- /dev/null +++ b/src/build/bnd/scala-actors-migration.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Actors Migration +Bundle-SymbolicName: org.scala-lang.scala-actors-migration +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/build/bnd/scala-actors.bnd b/src/build/bnd/scala-actors.bnd new file mode 100644 index 0000000000..8d0555777f --- /dev/null +++ b/src/build/bnd/scala-actors.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Actors +Bundle-SymbolicName: org.scala-lang.scala-actors +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/build/bnd/scala-compiler.bnd b/src/build/bnd/scala-compiler.bnd new file mode 100644 index 0000000000..c289843447 --- /dev/null +++ b/src/build/bnd/scala-compiler.bnd @@ -0,0 +1,8 @@ +Bundle-Name: Scala Compiler +Bundle-SymbolicName: org.scala-lang.scala-compiler +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} +Import-Package: scala.tools.jline.*;resolution:=optional, \ + org.apache.tools.ant.*;resolution:=optional, \ + * diff --git a/src/build/bnd/scala-library.bnd b/src/build/bnd/scala-library.bnd new file mode 100644 index 0000000000..03aff45672 --- /dev/null +++ b/src/build/bnd/scala-library.bnd @@ -0,0 +1,6 @@ +Bundle-Name: Scala Standard Library +Bundle-SymbolicName: org.scala-lang.scala-library +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} +Import-Package: sun.misc;resolution:=optional, * diff --git a/src/build/bnd/scala-reflect.bnd b/src/build/bnd/scala-reflect.bnd new file mode 100644 index 0000000000..6cda346d3a --- /dev/null +++ b/src/build/bnd/scala-reflect.bnd @@ -0,0 +1,6 @@ +Bundle-Name: Scala Reflect +Bundle-SymbolicName: org.scala-lang.scala-reflect +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} +Import-Package: scala.tools.nsc;resolution:=optional, * diff --git a/src/build/bnd/scala-swing.bnd b/src/build/bnd/scala-swing.bnd new file mode 100644 index 0000000000..eeacb9bd3f --- /dev/null +++ b/src/build/bnd/scala-swing.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Swing +Bundle-SymbolicName: org.scala-lang.scala-swing +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/compiler/scala/reflect/macros/runtime/Reifiers.scala b/src/compiler/scala/reflect/macros/runtime/Reifiers.scala index ab1de4288b..f15a7ad502 100644 --- a/src/compiler/scala/reflect/macros/runtime/Reifiers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Reifiers.scala @@ -13,17 +13,17 @@ trait Reifiers { import universe._ import definitions._ - lazy val basisUniverse: Tree = gen.mkBasisUniverseRef - lazy val runtimeUniverse: Tree = gen.mkRuntimeUniverseRef def reifyTree(universe: Tree, mirror: Tree, tree: Tree): Tree = { + assert(ExprClass != NoSymbol) val result = scala.reflect.reify.`package`.reifyTree(self.universe)(callsiteTyper, universe, mirror, tree) logFreeVars(enclosingPosition, result) result } def reifyType(universe: Tree, mirror: Tree, tpe: Type, concrete: Boolean = false): Tree = { + assert(TypeTagsClass != NoSymbol) val result = scala.reflect.reify.`package`.reifyType(self.universe)(callsiteTyper, universe, mirror, tpe, concrete) logFreeVars(enclosingPosition, result) result diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index f602fe9b99..6f779be17d 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -109,7 +109,7 @@ abstract class Reifier extends States // maybe try `resetLocalAttrs` once the dust settles var importantSymbols = Set[Symbol]( NothingClass, AnyClass, SingletonClass, PredefModule, ScalaRunTimeModule, TypeCreatorClass, TreeCreatorClass, MirrorOfClass, - BaseUniverseClass, JavaUniverseClass, ReflectRuntimePackage, ReflectRuntimeCurrentMirror) + ApiUniverseClass, JavaUniverseClass, ReflectRuntimePackage, ReflectRuntimeCurrentMirror) importantSymbols ++= importantSymbols map (_.companionSymbol) importantSymbols ++= importantSymbols map (_.moduleClass) importantSymbols ++= importantSymbols map (_.linkedClassOfClass) diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala index bc12d383a4..7db6394734 100644 --- a/src/compiler/scala/reflect/reify/Taggers.scala +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -27,9 +27,9 @@ abstract class Taggers { NothingTpe -> nme.Nothing, NullTpe -> nme.Null) - def materializeClassTag(prefix: Tree, tpe: Type): Tree = { + def materializeClassTag(tpe: Type): Tree = { val tagModule = ClassTagModule - materializeTag(prefix, tpe, tagModule, { + materializeTag(EmptyTree, tpe, tagModule, { val erasure = c.reifyRuntimeClass(tpe, concrete = true) val factory = TypeApply(Select(Ident(tagModule), nme.apply), List(TypeTree(tpe))) Apply(factory, List(erasure)) @@ -38,13 +38,13 @@ abstract class Taggers { def materializeTypeTag(universe: Tree, mirror: Tree, tpe: Type, concrete: Boolean): Tree = { val tagType = if (concrete) TypeTagClass else WeakTypeTagClass - // what we need here is to compose a type BaseUniverse # TypeTag[$tpe] + // what we need here is to compose a type Universe # TypeTag[$tpe] // to look for an implicit that conforms to this type // that's why neither appliedType(tagType, List(tpe)) aka TypeRef(TypeTagsClass.thisType, tagType, List(tpe)) - // nor TypeRef(BaseUniverseClass.thisType, tagType, List(tpe)) won't fit here - // scala> :type -v def foo: scala.reflect.base.Universe#TypeTag[Int] = ??? + // nor TypeRef(ApiUniverseClass.thisType, tagType, List(tpe)) won't fit here + // scala> :type -v def foo: scala.reflect.api.Universe#TypeTag[Int] = ??? // NullaryMethodType(TypeRef(pre = TypeRef(TypeSymbol(Universe)), TypeSymbol(TypeTag), args = List($tpe)))) - val unaffiliatedTagTpe = TypeRef(BaseUniverseClass.typeConstructor, tagType, List(tpe)) + val unaffiliatedTagTpe = TypeRef(ApiUniverseClass.typeConstructor, tagType, List(tpe)) val unaffiliatedTag = c.inferImplicitValue(unaffiliatedTagTpe, silent = true, withMacrosDisabled = true) unaffiliatedTag match { case success if !success.isEmpty => diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala index a76f147dc4..5a23ab7214 100644 --- a/src/compiler/scala/reflect/reify/package.scala +++ b/src/compiler/scala/reflect/reify/package.scala @@ -1,7 +1,6 @@ package scala.reflect import scala.language.implicitConversions -import scala.reflect.base.{Universe => BaseUniverse} import scala.reflect.macros.{Context, ReificationError, UnexpectedReificationError} import scala.tools.nsc.Global @@ -73,7 +72,7 @@ package object reify { def reifyEnclosingRuntimeClass(global: Global)(typer0: global.analyzer.Typer): global.Tree = { import global._ import definitions._ - def isThisInScope = typer0.context.enclosingContextChain exists (_.tree.isInstanceOf[Template]) + def isThisInScope = typer0.context.enclosingContextChain exists (_.tree.isInstanceOf[ImplDef]) if (isThisInScope) { val enclosingClasses = typer0.context.enclosingContextChain map (_.tree) collect { case classDef: ClassDef => classDef } val classInScope = enclosingClasses.headOption getOrElse EmptyTree diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala index baeea8cd9d..b5894e8eb6 100644 --- a/src/compiler/scala/reflect/reify/phases/Reshape.scala +++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala @@ -101,11 +101,11 @@ trait Reshape { // hence we cannot reify references to them, because noone will be able to see them later // when implicit macros are fixed, these sneaky macros will move to corresponding companion objects // of, say, ClassTag or TypeTag - case Apply(TypeApply(_, List(tt)), _) if original.symbol == MacroInternal_materializeClassTag => + case Apply(TypeApply(_, List(tt)), _) if original.symbol == materializeClassTag => gen.mkNullaryCall(Predef_implicitly, List(appliedType(ClassTagClass, tt.tpe))) - case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == MacroInternal_materializeWeakTypeTag => + case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == materializeWeakTypeTag => gen.mkNullaryCall(Predef_implicitly, List(typeRef(pre.tpe, WeakTypeTagClass, List(tt.tpe)))) - case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == MacroInternal_materializeTypeTag => + case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == materializeTypeTag => gen.mkNullaryCall(Predef_implicitly, List(typeRef(pre.tpe, TypeTagClass, List(tt.tpe)))) case _ => original diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala index 1df9efbb82..bf211ceec4 100644 --- a/src/compiler/scala/reflect/reify/utils/Extractors.scala +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -14,12 +14,12 @@ trait Extractors { // val $u: reflect.runtime.universe.type = scala.reflect.runtime.`package`.universe; // val $m: $u.Mirror = $u.runtimeMirror(Test.this.getClass().getClassLoader()); // $u.Expr[List[Int]]($m, { - // final class $treecreator1 extends scala.reflect.base.TreeCreator { + // final class $treecreator1 extends scala.reflect.api.TreeCreator { // def <init>(): $treecreator1 = { // $treecreator1.super.<init>(); // () // }; - // def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = { + // def apply[U >: Nothing <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.api.MirrorOf[U]): U#Tree = { // val $u: U = $m$untyped.universe; // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; // $u.Apply($u.Select($u.Select($u.build.This($m.staticPackage("scala.collection.immutable").moduleClass), $u.newTermName("List")), $u.newTermName("apply")), List($u.Literal($u.Constant(1)), $u.Literal($u.Constant(2)))) @@ -27,12 +27,12 @@ trait Extractors { // }; // new $treecreator1() // })($u.TypeTag[List[Int]]($m, { - // final class $typecreator1 extends scala.reflect.base.TypeCreator { + // final class $typecreator1 extends scala.reflect.api.TypeCreator { // def <init>(): $typecreator1 = { // $typecreator1.super.<init>(); // () // }; - // def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = { + // def apply[U >: Nothing <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.api.MirrorOf[U]): U#Type = { // val $u: U = $m$untyped.universe; // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; // $u.TypeRef($u.ThisType($m.staticPackage("scala.collection.immutable").moduleClass), $m.staticClass("scala.collection.immutable.List"), List($m.staticClass("scala.Int").toTypeConstructor)) @@ -45,8 +45,8 @@ trait Extractors { private def mkCreator(flavor: TypeName, symtab: SymbolTable, rtree: Tree): Tree = { val tparamu = newTypeName("U") val (reifierBase, reifierName, reifierTpt, reifierUniverse) = flavor match { - case tpnme.REIFY_TYPECREATOR_PREFIX => (TypeCreatorClass, nme.apply, SelectFromTypeTree(Ident(tparamu), tpnme.Type), BaseUniverseClass) - case tpnme.REIFY_TREECREATOR_PREFIX => (TreeCreatorClass, nme.apply, SelectFromTypeTree(Ident(tparamu), tpnme.Tree), BaseUniverseClass) + case tpnme.REIFY_TYPECREATOR_PREFIX => (TypeCreatorClass, nme.apply, SelectFromTypeTree(Ident(tparamu), tpnme.Type), ApiUniverseClass) + case tpnme.REIFY_TREECREATOR_PREFIX => (TreeCreatorClass, nme.apply, SelectFromTypeTree(Ident(tparamu), tpnme.Tree), ApiUniverseClass) case _ => throw new Error(s"unexpected flavor $flavor") } val reifierBody = { diff --git a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala index b2999c3c1c..f0480e0699 100644 --- a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala +++ b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala @@ -75,7 +75,7 @@ trait NodePrinters { val printout = scala.collection.mutable.ListBuffer[String](); printout += universe.trim - if (mirrorIsUsed) printout += mirror.replace("MirrorOf[", "scala.reflect.base.MirrorOf[").trim + if (mirrorIsUsed) printout += mirror.replace("MirrorOf[", "scala.reflect.api.MirrorOf[").trim val imports = scala.collection.mutable.ListBuffer[String](); imports += nme.UNIVERSE_SHORT // if (buildIsUsed) imports += nme.build diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 6fb6b1736b..58fcee4b30 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1094,6 +1094,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) // TODO - trim these to the absolute minimum. @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op) + @inline final def afterPostErasure[T](op: => T): T = afterPhase(currentRun.posterasurePhase)(op) @inline final def afterExplicitOuter[T](op: => T): T = afterPhase(currentRun.explicitouterPhase)(op) @inline final def afterFlatten[T](op: => T): T = afterPhase(currentRun.flattenPhase)(op) @inline final def afterIcode[T](op: => T): T = afterPhase(currentRun.icodePhase)(op) @@ -1403,6 +1404,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val specializePhase = phaseNamed("specialize") val explicitouterPhase = phaseNamed("explicitouter") val erasurePhase = phaseNamed("erasure") + val posterasurePhase = phaseNamed("posterasure") // val lazyvalsPhase = phaseNamed("lazyvals") val lambdaliftPhase = phaseNamed("lambdalift") // val constructorsPhase = phaseNamed("constructors") diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index ba8da3b0ec..a1785e5262 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -182,13 +182,13 @@ trait Scanners extends ScannersCommon { /** Are we directly in a string interpolation expression? */ - @inline private def inStringInterpolation = + private def inStringInterpolation = sepRegions.nonEmpty && sepRegions.head == STRINGLIT /** Are we directly in a multiline string interpolation expression? * @pre inStringInterpolation */ - @inline private def inMultiLineInterpolation = + private def inMultiLineInterpolation = inStringInterpolation && sepRegions.tail.nonEmpty && sepRegions.tail.head == STRINGPART /** read next token and return last offset diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index 31c2077097..5d81109ac9 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -480,7 +480,7 @@ abstract class TypeFlowAnalysis { val knownUnsafe = mutable.Set.empty[Symbol] val knownSafe = mutable.Set.empty[Symbol] val knownNever = mutable.Set.empty[Symbol] // `knownNever` needs be cleared only at the very end of the inlining phase (unlike `knownUnsafe` and `knownSafe`) - @inline final def blackballed(msym: Symbol): Boolean = { knownUnsafe(msym) || knownNever(msym) } + final def blackballed(msym: Symbol): Boolean = { knownUnsafe(msym) || knownNever(msym) } val relevantBBs = mutable.Set.empty[BasicBlock] diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 28966eef08..5a5059d58c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -229,11 +229,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters { binarynme.RuntimeNull.toString() -> RuntimeNullClass ) - private def mkFlags(args: Int*) = args.foldLeft(0)(_ | _) - - @inline final private def hasPublicBitSet(flags: Int) = ((flags & asm.Opcodes.ACC_PUBLIC) != 0) - - @inline final private def isRemote(s: Symbol) = (s hasAnnotation RemoteAttr) + private def mkFlags(args: Int*) = args.foldLeft(0)(_ | _) + private def hasPublicBitSet(flags: Int) = (flags & asm.Opcodes.ACC_PUBLIC) != 0 + private def isRemote(s: Symbol) = s hasAnnotation RemoteAttr /** * Return the Java modifiers for the given symbol. @@ -386,8 +384,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { fcs } - @inline final private def jvmWiseLUB(a: Symbol, b: Symbol): Symbol = { - + private def jvmWiseLUB(a: Symbol, b: Symbol): Symbol = { assert(a.isClass) assert(b.isClass) @@ -1544,7 +1541,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { var jmethod: asm.MethodVisitor = _ var jMethodName: String = _ - @inline final def emit(opc: Int) { jmethod.visitInsn(opc) } + final def emit(opc: Int) { jmethod.visitInsn(opc) } def genMethod(m: IMethod, isJInterface: Boolean) { @@ -1781,7 +1778,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { else { jmethod.visitLdcInsn(cst) } } - @inline final def boolconst(b: Boolean) { iconst(if(b) 1 else 0) } + final def boolconst(b: Boolean) { iconst(if(b) 1 else 0) } def iconst(cst: Int) { if (cst >= -1 && cst <= 5) { @@ -1847,44 +1844,44 @@ abstract class GenASM extends SubComponent with BytecodeWriters { } - @inline def load( idx: Int, tk: TypeKind) { emitVarInsn(Opcodes.ILOAD, idx, tk) } - @inline def store(idx: Int, tk: TypeKind) { emitVarInsn(Opcodes.ISTORE, idx, tk) } + def load( idx: Int, tk: TypeKind) { emitVarInsn(Opcodes.ILOAD, idx, tk) } + def store(idx: Int, tk: TypeKind) { emitVarInsn(Opcodes.ISTORE, idx, tk) } - @inline def aload( tk: TypeKind) { emitTypeBased(aloadOpcodes, tk) } - @inline def astore(tk: TypeKind) { emitTypeBased(astoreOpcodes, tk) } + def aload( tk: TypeKind) { emitTypeBased(aloadOpcodes, tk) } + def astore(tk: TypeKind) { emitTypeBased(astoreOpcodes, tk) } - @inline def neg(tk: TypeKind) { emitPrimitive(negOpcodes, tk) } - @inline def add(tk: TypeKind) { emitPrimitive(addOpcodes, tk) } - @inline def sub(tk: TypeKind) { emitPrimitive(subOpcodes, tk) } - @inline def mul(tk: TypeKind) { emitPrimitive(mulOpcodes, tk) } - @inline def div(tk: TypeKind) { emitPrimitive(divOpcodes, tk) } - @inline def rem(tk: TypeKind) { emitPrimitive(remOpcodes, tk) } + def neg(tk: TypeKind) { emitPrimitive(negOpcodes, tk) } + def add(tk: TypeKind) { emitPrimitive(addOpcodes, tk) } + def sub(tk: TypeKind) { emitPrimitive(subOpcodes, tk) } + def mul(tk: TypeKind) { emitPrimitive(mulOpcodes, tk) } + def div(tk: TypeKind) { emitPrimitive(divOpcodes, tk) } + def rem(tk: TypeKind) { emitPrimitive(remOpcodes, tk) } - @inline def invokespecial(owner: String, name: String, desc: String) { + def invokespecial(owner: String, name: String, desc: String) { jmethod.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc) } - @inline def invokestatic(owner: String, name: String, desc: String) { + def invokestatic(owner: String, name: String, desc: String) { jmethod.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc) } - @inline def invokeinterface(owner: String, name: String, desc: String) { + def invokeinterface(owner: String, name: String, desc: String) { jmethod.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc) } - @inline def invokevirtual(owner: String, name: String, desc: String) { + def invokevirtual(owner: String, name: String, desc: String) { jmethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc) } - @inline def goTo(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.GOTO, label) } - @inline def emitIF(cond: TestOp, label: asm.Label) { jmethod.visitJumpInsn(cond.opcodeIF, label) } - @inline def emitIF_ICMP(cond: TestOp, label: asm.Label) { jmethod.visitJumpInsn(cond.opcodeIFICMP, label) } - @inline def emitIF_ACMP(cond: TestOp, label: asm.Label) { + def goTo(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.GOTO, label) } + def emitIF(cond: TestOp, label: asm.Label) { jmethod.visitJumpInsn(cond.opcodeIF, label) } + def emitIF_ICMP(cond: TestOp, label: asm.Label) { jmethod.visitJumpInsn(cond.opcodeIFICMP, label) } + def emitIF_ACMP(cond: TestOp, label: asm.Label) { assert((cond == EQ) || (cond == NE), cond) val opc = (if(cond == EQ) Opcodes.IF_ACMPEQ else Opcodes.IF_ACMPNE) jmethod.visitJumpInsn(opc, label) } - @inline def emitIFNONNULL(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.IFNONNULL, label) } - @inline def emitIFNULL (label: asm.Label) { jmethod.visitJumpInsn(Opcodes.IFNULL, label) } + def emitIFNONNULL(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.IFNONNULL, label) } + def emitIFNULL (label: asm.Label) { jmethod.visitJumpInsn(Opcodes.IFNULL, label) } - @inline def emitRETURN(tk: TypeKind) { + def emitRETURN(tk: TypeKind) { if(tk == UNIT) { jmethod.visitInsn(Opcodes.RETURN) } else { emitTypeBased(returnOpcodes, tk) } } @@ -2161,8 +2158,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { case class LocVarEntry(local: Local, start: asm.Label, end: asm.Label) // start is inclusive while end exclusive. case class Interval(lstart: asm.Label, lend: asm.Label) { - @inline final def start = lstart.getOffset - @inline final def end = lend.getOffset + final def start = lstart.getOffset + final def end = lend.getOffset def precedes(that: Interval): Boolean = { this.end < that.start } @@ -2952,7 +2949,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { // indexOf(local) // } - @inline final def indexOf(local: Local): Int = { + final def indexOf(local: Local): Int = { assert(local.index >= 0, "Invalid index for: " + local + "{" + local.## + "}: ") local.index } diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala index f5df772d7d..dbbc573299 100644 --- a/src/compiler/scala/tools/nsc/doc/Settings.scala +++ b/src/compiler/scala/tools/nsc/doc/Settings.scala @@ -250,15 +250,15 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) * the function result should be a humanly-understandable description of the type class */ val knownTypeClasses: Map[String, String => String] = Map() + - ("scala.math.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) + - ("scala.math.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) + - ("scala.math.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) + - ("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) + - ("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.WeakTypeTag" -> ((tparam: String) => tparam + " is accompanied by an WeakTypeTag, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.base.TypeTags.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure")) + ("scala.math.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) + + ("scala.math.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) + + ("scala.math.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) + + ("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) + + ("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.api.TypeTags.WeakTypeTag" -> ((tparam: String) => tparam + " is accompanied by an WeakTypeTag, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.api.TypeTags.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure")) /** * Set of classes to exclude from index and diagrams diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala index f27c4a8123..9503c7d970 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package interpreter import scala.language.implicitConversions -import scala.reflect.base.{Universe => BaseUniverse} +import scala.reflect.api.{Universe => ApiUniverse} import scala.reflect.runtime.{universe => ru} /** A class which the repl utilizes to expose predefined objects. @@ -65,7 +65,7 @@ object ReplVals { * I have this forwarder which widens the type and then cast the result back * to the dependent type. */ - def compilerTypeFromTag(t: BaseUniverse # WeakTypeTag[_]): Global#Type = + def compilerTypeFromTag(t: ApiUniverse # WeakTypeTag[_]): Global#Type = definitions.compilerTypeFromTag(t) class AppliedTypeFromTags(sym: Symbol) { diff --git a/src/compiler/scala/tools/nsc/io/package.scala b/src/compiler/scala/tools/nsc/io/package.scala index 775ad6bde0..ae83a7728b 100644 --- a/src/compiler/scala/tools/nsc/io/package.scala +++ b/src/compiler/scala/tools/nsc/io/package.scala @@ -11,6 +11,23 @@ import java.util.jar.{ Attributes } import scala.language.implicitConversions package object io { + // Forwarders from scala.reflect.io + type AbstractFile = scala.reflect.io.AbstractFile + val AbstractFile = scala.reflect.io.AbstractFile + type Directory = scala.reflect.io.Directory + val Directory = scala.reflect.io.Directory + type File = scala.reflect.io.File + val File = scala.reflect.io.File + type Path = scala.reflect.io.Path + val Path = scala.reflect.io.Path + type PlainFile = scala.reflect.io.PlainFile + val PlainFile = scala.reflect.io.PlainFile + val Streamable = scala.reflect.io.Streamable + type VirtualDirectory = scala.reflect.io.VirtualDirectory + type VirtualFile = scala.reflect.io.VirtualFile + val ZipArchive = scala.reflect.io.ZipArchive + type ZipArchive = scala.reflect.io.ZipArchive + implicit def postfixOps = scala.language.postfixOps // make all postfix ops in this package compile without warning type JManifest = java.util.jar.Manifest diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 903b3095de..a356b70e62 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1273,7 +1273,7 @@ abstract class ClassfileParser { sym.privateWithin = sym.enclosingTopLevelClass.owner } - @inline private def isPrivate(flags: Int) = (flags & JAVA_ACC_PRIVATE) != 0 - @inline private def isStatic(flags: Int) = (flags & JAVA_ACC_STATIC) != 0 - @inline private def hasAnnotation(flags: Int) = (flags & JAVA_ACC_ANNOTATION) != 0 + private def isPrivate(flags: Int) = (flags & JAVA_ACC_PRIVATE) != 0 + private def isStatic(flags: Int) = (flags & JAVA_ACC_STATIC) != 0 + private def hasAnnotation(flags: Int) = (flags & JAVA_ACC_ANNOTATION) != 0 } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index b3b0c82d38..072d823c60 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -167,6 +167,8 @@ abstract class Erasure extends AddInterfaces case tp => tp :: Nil } + private def isErasedValueType(tpe: Type) = tpe.isInstanceOf[ErasedValueType] + /** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return * type for constructors. */ @@ -373,18 +375,18 @@ abstract class Erasure extends AddInterfaces } } - class ComputeBridges(owner: Symbol) { + class ComputeBridges(unit: CompilationUnit, root: Symbol) { assert(phase == currentRun.erasurePhase, phase) var toBeRemoved = immutable.Set[Symbol]() - val site = owner.thisType + val site = root.thisType val bridgesScope = newScope val bridgeTarget = mutable.HashMap[Symbol, Symbol]() var bridges = List[Tree]() val opc = beforeExplicitOuter { - new overridingPairs.Cursor(owner) { - override def parents = List(owner.info.firstParent) + new overridingPairs.Cursor(root) { + override def parents = List(root.info.firstParent) override def exclude(sym: Symbol) = !sym.isMethod || sym.isPrivate || super.exclude(sym) } } @@ -402,8 +404,58 @@ abstract class Erasure extends AddInterfaces (bridges, toBeRemoved) } + /** Check that a bridge only overrides members that are also overridden by the original member. + * This test is necessary only for members that have a value class in their type. + * Such members are special because their types after erasure and after post-erasure differ/. + * This means we generate them after erasure, but the post-erasure transform might introduce + * a name clash. The present method guards against these name clashes. + * + * @param member The original member + * @param other The overidden symbol for which the bridge was generated + * @param bridge The bridge + */ + def checkBridgeOverrides(member: Symbol, other: Symbol, bridge: Symbol): Boolean = { + def fulldef(sym: Symbol) = + if (sym == NoSymbol) sym.toString + else s"$sym: ${sym.tpe} in ${sym.owner}" + var noclash = true + def clashError(what: String) = { + noclash = false + unit.error( + if (member.owner == root) member.pos else root.pos, + s"""bridge generated for member ${fulldef(member)} + |which overrides ${fulldef(other)} + |clashes with definition of $what; + |both have erased type ${afterPostErasure(bridge.tpe)}""".stripMargin) + } + for (bc <- root.baseClasses) { + if (settings.debug.value) + afterPostErasure(println( + s"""check bridge overrides in $bc + ${bc.info.nonPrivateDecl(bridge.name)} + ${site.memberType(bridge)} + ${site.memberType(bc.info.nonPrivateDecl(bridge.name) orElse IntClass)} + ${(bridge.matchingSymbol(bc, site))}""".stripMargin)) + + def overriddenBy(sym: Symbol) = + sym.matchingSymbol(bc, site).alternatives filter (sym => !sym.isBridge) + for (overBridge <- afterPostErasure(overriddenBy(bridge))) { + if (overBridge == member) { + clashError("the member itself") + } else { + val overMembers = overriddenBy(member) + if (!overMembers.exists(overMember => + afterPostErasure(overMember.tpe =:= overBridge.tpe))) { + clashError(fulldef(overBridge)) + } + } + } + } + noclash + } + def checkPair(member: Symbol, other: Symbol) { - val otpe = erasure(owner)(other.tpe) + val otpe = erasure(root)(other.tpe) val bridgeNeeded = afterErasure ( !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && @@ -417,24 +469,29 @@ abstract class Erasure extends AddInterfaces return val newFlags = (member.flags | BRIDGE) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED) - val bridge = other.cloneSymbolImpl(owner, newFlags) setPos owner.pos + val bridge = other.cloneSymbolImpl(root, newFlags) setPos root.pos debuglog("generating bridge from %s (%s): %s to %s: %s".format( other, flagsToString(newFlags), otpe + other.locationString, member, - erasure(owner)(member.tpe) + member.locationString) + erasure(root)(member.tpe) + member.locationString) ) // the parameter symbols need to have the new owner bridge setInfo (otpe cloneInfo bridge) bridgeTarget(bridge) = member - afterErasure(owner.info.decls enter bridge) - if (other.owner == owner) { - afterErasure(owner.info.decls.unlink(other)) - toBeRemoved += other + + if (!(member.tpe exists (_.typeSymbol.isDerivedValueClass)) || + checkBridgeOverrides(member, other, bridge)) { + afterErasure(root.info.decls enter bridge) + if (other.owner == root) { + afterErasure(root.info.decls.unlink(other)) + toBeRemoved += other + } + + bridgesScope enter bridge + bridges ::= makeBridgeDefDef(bridge, member, other) } - bridgesScope enter bridge - bridges ::= makeBridgeDefDef(bridge, member, other) } def makeBridgeDefDef(bridge: Symbol, member: Symbol, other: Symbol) = afterErasure { @@ -466,7 +523,7 @@ abstract class Erasure extends AddInterfaces val rhs = member.tpe match { case MethodType(Nil, ConstantType(c)) => Literal(c) case _ => - val sel: Tree = Select(This(owner), member) + val sel: Tree = Select(This(root), member) val bridgingCall = (sel /: bridge.paramss)((fun, vparams) => Apply(fun, vparams map Ident)) maybeWrap(bridgingCall) @@ -480,8 +537,6 @@ abstract class Erasure extends AddInterfaces private def isPrimitiveValueType(tpe: Type) = isPrimitiveValueClass(tpe.typeSymbol) - private def isErasedValueType(tpe: Type) = tpe.isInstanceOf[ErasedValueType] - private def isDifferentErasedValueType(tpe: Type, other: Type) = isErasedValueType(tpe) && (tpe ne other) @@ -814,7 +869,6 @@ abstract class Erasure extends AddInterfaces * but their erased types are the same. */ private def checkNoDoubleDefs(root: Symbol) { - def afterErasure[T](op: => T): T = atPhase(phase.next.next)(op) def doubleDefError(sym1: Symbol, sym2: Symbol) { // the .toString must also be computed at the earlier phase val tpe1 = afterRefchecks(root.thisType.memberType(sym1)) @@ -830,7 +884,7 @@ abstract class Erasure extends AddInterfaces sym2 + ":" + afterRefchecks(tpe2.toString) + (if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) + "\nhave same type" + - (if (afterRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + afterErasure(sym1.tpe))) + (if (afterRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + afterPostErasure(sym1.tpe))) sym1.setInfo(ErrorType) } @@ -840,7 +894,7 @@ abstract class Erasure extends AddInterfaces if (e.sym.isTerm) { var e1 = decls.lookupNextEntry(e) while (e1 ne null) { - if (afterErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym) + if (afterPostErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym) e1 = decls.lookupNextEntry(e1) } } @@ -854,7 +908,7 @@ abstract class Erasure extends AddInterfaces || !sym.hasTypeAt(currentRun.refchecksPhase.id)) override def matches(sym1: Symbol, sym2: Symbol): Boolean = - afterErasure(sym1.tpe =:= sym2.tpe) + afterPostErasure(sym1.tpe =:= sym2.tpe) } while (opc.hasNext) { if (!afterRefchecks( @@ -902,7 +956,7 @@ abstract class Erasure extends AddInterfaces private def bridgeDefs(owner: Symbol): (List[Tree], immutable.Set[Symbol]) = { assert(phase == currentRun.erasurePhase, phase) debuglog("computing bridges for " + owner) - new ComputeBridges(owner) compute() + new ComputeBridges(unit, owner) compute() } def addBridges(stats: List[Tree], base: Symbol): List[Tree] = @@ -1000,7 +1054,7 @@ abstract class Erasure extends AddInterfaces preEraseIsInstanceOf } else if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) { ApplyDynamic(qualifier, args) setSymbol fn.symbol setPos tree.pos - } else if (fn.symbol.isMethodWithExtension) { + } else if (fn.symbol.isMethodWithExtension && !fn.symbol.tpe.isErroneous) { Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args) } else { tree diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 0820d3e714..8a9d0e58ec 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -70,7 +70,8 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { val companionInfo = imeth.owner.companionModule.info val candidates = extensionNames(imeth) map (companionInfo.decl(_)) val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe) - assert(matching.nonEmpty, "no extension method found for "+imeth+" among "+candidates+"/"+extensionNames(imeth)) + assert(matching.nonEmpty, + s"no extension method found for $imeth:${imeth.tpe}+among ${candidates map (c => c.name+":"+c.tpe)} / ${extensionNames(imeth)}") matching.head } @@ -135,7 +136,9 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { tree match { case Template(_, _, _) => if (currentOwner.isDerivedValueClass) { - checkNonCyclic(currentOwner.pos, Set(), currentOwner) + /* This is currently redundant since value classes may not + wrap over other value classes anyway. + checkNonCyclic(currentOwner.pos, Set(), currentOwner) */ extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] currentOwner.primaryConstructor.makeNotPrivate(NoSymbol) super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala index f9d8d19b10..0b58292f28 100644 --- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala +++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala @@ -104,8 +104,11 @@ abstract class OverridingPairs { /** A map from baseclasses of <base> to ints, with smaller ints meaning lower in * linearization order. + * symbols that are not baseclasses map to -1. */ - private val index = new mutable.HashMap[Symbol, Int] + private val index = new mutable.HashMap[Symbol, Int] { + override def default(key: Symbol) = -1 + } // Note: overridingPairs can be called at odd instances by the Eclipse plugin // Soemtimes symbols are not yet defined and we get missing keys. @@ -133,28 +136,30 @@ abstract class OverridingPairs { { for (i <- List.range(0, size)) subParents(i) = new BitSet(size); for (p <- parents) { - index get p.typeSymbol match { - case Some(pIndex) => - for (bc <- p.baseClasses) - if (p.baseType(bc) =:= self.baseType(bc)) - index get bc match { - case Some(bcIndex) => - include(subParents(bcIndex), pIndex) - case None => - } - else debuglog("SKIPPING "+p+" -> "+p.baseType(bc)+" / "+self.baseType(bc)+" from "+base) - case None => - } + val pIndex = index(p.typeSymbol) + if (pIndex >= 0) + for (bc <- p.baseClasses) + if (p.baseType(bc) =:= self.baseType(bc)) { + val bcIndex = index(bc) + if (bcIndex >= 0) + include(subParents(bcIndex), pIndex) + } } } /** Do `sym1` and `sym2` have a common subclass in `parents`? * In that case we do not follow their overriding pairs */ - private def hasCommonParentAsSubclass(sym1: Symbol, sym2: Symbol) = ( - for (index1 <- index get sym1.owner ; index2 <- index get sym2.owner) yield - intersectionContainsElementLeq(subParents(index1), subParents(index2), index1 min index2) - ).exists(_ == true) + private def hasCommonParentAsSubclass(sym1: Symbol, sym2: Symbol) = { + val index1 = index(sym1.owner) + (index1 >= 0) && { + val index2 = index(sym2.owner) + (index2 >= 0) && { + intersectionContainsElementLeq( + subParents(index1), subParents(index2), index1 min index2) + } + } + } /** The scope entries that have already been visited as overridden * (maybe excluded because of hasCommonParentAsSubclass). diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 144cc841b4..d78efd8280 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -515,9 +515,16 @@ trait ContextErrors { def ApplyWithoutArgsError(tree: Tree, fun: Tree) = NormalTypeError(tree, fun.tpe+" does not take parameters") + // Dynamic def DynamicVarArgUnsupported(tree: Tree, name: String) = issueNormalTypeError(tree, name+ " does not support passing a vararg parameter") + def DynamicRewriteError(tree: Tree, err: AbsTypeError) = { + issueTypeError(PosAndMsgTypeError(err.errPos, err.errMsg + + s"\nerror after rewriting to $tree\npossible cause: maybe a wrong Dynamic method signature?")) + setError(tree) + } + //checkClassType def TypeNotAStablePrefixError(tpt: Tree, pre: Type) = { issueNormalTypeError(tpt, "type "+pre+" is not a stable prefix") @@ -830,7 +837,6 @@ trait ContextErrors { } // side-effect on the tree, break the overloaded type cycle in infer - @inline private def setErrorOnLastTry(lastTry: Boolean, tree: Tree) = if (lastTry) setError(tree) def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type, lastTry: Boolean) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index dbf769c79f..211da044e6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -487,7 +487,7 @@ trait Contexts { self: Analyzer => lastAccessCheckDetails = "" // Console.println("isAccessible(%s, %s, %s)".format(sym, pre, superAccess)) - @inline def accessWithinLinked(ab: Symbol) = { + def accessWithinLinked(ab: Symbol) = { val linked = ab.linkedClassOfClass // don't have access if there is no linked class // (before adding the `ne NoSymbol` check, this was a no-op when linked eq NoSymbol, diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index dd7f26861f..7852ff49e1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1150,9 +1150,9 @@ trait Implicits { private def TagSymbols = TagMaterializers.keySet private val TagMaterializers = Map[Symbol, Symbol]( - ClassTagClass -> MacroInternal_materializeClassTag, - WeakTypeTagClass -> MacroInternal_materializeWeakTypeTag, - TypeTagClass -> MacroInternal_materializeTypeTag + ClassTagClass -> materializeClassTag, + WeakTypeTagClass -> materializeWeakTypeTag, + TypeTagClass -> materializeTypeTag ) /** Creates a tree will produce a tag of the requested flavor. @@ -1183,7 +1183,7 @@ trait Implicits { val prefix = ( // ClassTags are not path-dependent, so their materializer doesn't care about prefixes - if (tagClass eq ClassTagClass) gen.mkBasisUniverseRef + if (tagClass eq ClassTagClass) EmptyTree else pre match { case SingleType(prePre, preSym) => gen.mkAttributedRef(prePre, preSym) setType pre @@ -1205,7 +1205,7 @@ trait Implicits { } ) // todo. migrate hardcoded materialization in Implicits to corresponding implicit macros - var materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), List(prefix))) + var materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), if (prefix != EmptyTree) List(prefix) else List())) if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer)) if (context.macrosEnabled) success(materializer) // don't call `failure` here. if macros are disabled, we just fail silently diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 294470d40e..22077303a4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -77,7 +77,7 @@ trait Infer { val isUnapplySeq = unappSym.name == nme.unapplySeq val booleanExtractor = resTp.typeSymbolDirect == BooleanClass - @inline def seqToRepeatedChecked(tp: Type) = { + def seqToRepeatedChecked(tp: Type) = { val toRepeated = seqToRepeated(tp) if (tp eq toRepeated) throw new TypeError("(the last tuple-component of) the result type of an unapplySeq must be a Seq[_]") else toRepeated @@ -548,9 +548,9 @@ trait Infer { }) } - @inline private def toLists[A1, A2](pxs: (Iterable[A1], Iterable[A2])) = (pxs._1.toList, pxs._2.toList) - @inline private def toLists[A1, A2, A3](pxs: (Iterable[A1], Iterable[A2], Iterable[A3])) = (pxs._1.toList, pxs._2.toList, pxs._3.toList) - @inline private def toLists[A1, A2, A3, A4](pxs: (Iterable[A1], Iterable[A2], Iterable[A3], Iterable[A4])) = (pxs._1.toList, pxs._2.toList, pxs._3.toList, pxs._4.toList) + private def toLists[A1, A2](pxs: (Iterable[A1], Iterable[A2])) = (pxs._1.toList, pxs._2.toList) + private def toLists[A1, A2, A3](pxs: (Iterable[A1], Iterable[A2], Iterable[A3])) = (pxs._1.toList, pxs._2.toList, pxs._3.toList) + private def toLists[A1, A2, A3, A4](pxs: (Iterable[A1], Iterable[A2], Iterable[A3], Iterable[A4])) = (pxs._1.toList, pxs._2.toList, pxs._3.toList, pxs._4.toList) } /** Retract arguments that were inferred to Nothing because inference failed. Correct types for repeated params. diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 9adf86e44b..f9a35ba9a0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -710,7 +710,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { if (isNullaryInvocation(expandee)) expectedTpe = expectedTpe.finalResultType var typechecked = typecheck("macro def return type", expanded, expectedTpe) typechecked = typecheck("expected type", typechecked, pt) - typechecked updateAttachment MacroExpansionAttachment(expandee) + typechecked } finally { popMacroContext() } @@ -776,7 +776,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { macroLogLite("" + expanded.tree + "\n" + showRaw(expanded.tree)) val freeSyms = expanded.tree.freeTerms ++ expanded.tree.freeTypes freeSyms foreach (sym => MacroFreeSymbolError(expandee, sym)) - Success(atPos(enclosingMacroPosition.focus)(expanded.tree)) + Success(atPos(enclosingMacroPosition.focus)(expanded.tree updateAttachment MacroExpansionAttachment(expandee))) case _ => MacroExpansionIsNotExprError(expandee, expanded) } diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 2dc3dc3dbd..d0b715d502 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -387,8 +387,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL def translatePattern(patBinder: Symbol, patTree: Tree): List[TreeMaker] = { // a list of TreeMakers that encode `patTree`, and a list of arguments for recursive invocations of `translatePattern` to encode its subpatterns type TranslationStep = (List[TreeMaker], List[(Symbol, Tree)]) - @inline def withSubPats(treeMakers: List[TreeMaker], subpats: (Symbol, Tree)*): TranslationStep = (treeMakers, subpats.toList) - @inline def noFurtherSubPats(treeMakers: TreeMaker*): TranslationStep = (treeMakers.toList, Nil) + def withSubPats(treeMakers: List[TreeMaker], subpats: (Symbol, Tree)*): TranslationStep = (treeMakers, subpats.toList) + def noFurtherSubPats(treeMakers: TreeMaker*): TranslationStep = (treeMakers.toList, Nil) val pos = patTree.pos @@ -860,7 +860,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // since about half of the typedSubst's end up being no-ops, the check below shaves off 5% of the time spent in typedSubst if (!tree.exists { case i@Ident(_) => from contains i.symbol case _ => false}) tree else (new Transformer { - @inline private def typedIfOrigTyped(to: Tree, origTp: Type): Tree = + private def typedIfOrigTyped(to: Tree, origTp: Type): Tree = if (origTp == null || origTp == NoType) to // important: only type when actually substing and when original tree was typed // (don't need to use origTp as the expected type, though, and can't always do this anyway due to unknown type params stemming from polymorphic extractors) @@ -1208,7 +1208,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL else typeTest(testedBinder, expectedTp) // propagate expected type - @inline def expTp(t: Tree): t.type = t setType expectedTp + def expTp(t: Tree): t.type = t setType expectedTp // true when called to type-test the argument to an extractor // don't do any fancy equality checking, just test the type @@ -1694,8 +1694,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL final def binderToUniqueTree(b: Symbol) = unique(accumSubst(normalize(CODE.REF(b))), b.tpe) - @inline def /\(conds: Iterable[Cond]) = if (conds.isEmpty) TrueCond else conds.reduceLeft(AndCond(_, _)) - @inline def \/(conds: Iterable[Cond]) = if (conds.isEmpty) FalseCond else conds.reduceLeft(OrCond(_, _)) + def /\(conds: Iterable[Cond]) = if (conds.isEmpty) TrueCond else conds.reduceLeft(AndCond(_, _)) + def \/(conds: Iterable[Cond]) = if (conds.isEmpty) FalseCond else conds.reduceLeft(OrCond(_, _)) // note that the sequencing of operations is important: must visit in same order as match execution // binderToUniqueTree uses the type of the first symbol that was encountered as the type for all future binders @@ -1903,8 +1903,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL private def nextSymId = {_symId += 1; _symId}; private var _symId = 0 - @inline def /\(props: Iterable[Prop]) = if (props.isEmpty) True else props.reduceLeft(And(_, _)) - @inline def \/(props: Iterable[Prop]) = if (props.isEmpty) False else props.reduceLeft(Or(_, _)) + def /\(props: Iterable[Prop]) = if (props.isEmpty) True else props.reduceLeft(And(_, _)) + def \/(props: Iterable[Prop]) = if (props.isEmpty) False else props.reduceLeft(Or(_, _)) trait PropTraverser { @@ -1980,7 +1980,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL val pure = props map rewriteEqualsToProp.apply var eqAxioms: Prop = True - @inline def addAxiom(p: Prop) = eqAxioms = And(eqAxioms, p) + def addAxiom(p: Prop) = eqAxioms = And(eqAxioms, p) patmatDebug("removeVarEq vars: "+ vars) vars.foreach { v => @@ -2051,7 +2051,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // a clause is a disjunction of distinct literals type Clause = Set[Lit] def clause(l: Lit*): Clause = l.toSet - @inline private def merge(a: Clause, b: Clause) = a ++ b + private def merge(a: Clause, b: Clause) = a ++ b type Lit def Lit(sym: Sym, pos: Boolean = true): Lit @@ -2189,8 +2189,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL findAllModels(f, Nil) } - @inline private def withLit(res: Model, l: Lit): Model = if (res eq NoModel) NoModel else res + (l.sym -> l.pos) - @inline private def dropUnit(f: Formula, unitLit: Lit) = { + private def withLit(res: Model, l: Lit): Model = if (res eq NoModel) NoModel else res + (l.sym -> l.pos) + private def dropUnit(f: Formula, unitLit: Lit) = { val negated = -unitLit // drop entire clauses that are trivially true // (i.e., disjunctions that contain the literal we're making true in the returned model), @@ -2268,9 +2268,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL private[this] val id: Int = Var.nextId // private[this] var canModify: Option[Array[StackTraceElement]] = None - @inline private[this] def ensureCanModify = {} //if (canModify.nonEmpty) patmatDebug("BUG!"+ this +" modified after having been observed: "+ canModify.get.mkString("\n")) + private[this] def ensureCanModify = {} //if (canModify.nonEmpty) patmatDebug("BUG!"+ this +" modified after having been observed: "+ canModify.get.mkString("\n")) - @inline private[this] def observed = {} //canModify = Some(Thread.currentThread.getStackTrace) + private[this] def observed = {} //canModify = Some(Thread.currentThread.getStackTrace) // don't access until all potential equalities have been registered using registerEquality private[this] val symForEqualsTo = new scala.collection.mutable.HashMap[Const, Sym] @@ -2735,7 +2735,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // a type is "uncheckable" (for exhaustivity) if we don't statically know its subtypes (i.e., it's unsealed) // we consider tuple types with at least one component of a checkable type as a checkable type def uncheckableType(tp: Type): Boolean = { - @inline def tupleComponents(tp: Type) = tp.normalize.typeArgs + def tupleComponents(tp: Type) = tp.normalize.typeArgs val checkable = ( (isTupleType(tp) && tupleComponents(tp).exists(tp => !uncheckableType(tp))) || enumerateSubtypes(tp).nonEmpty) @@ -2868,7 +2868,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL case object WildcardExample extends CounterExample { override def toString = "_" } case object NoExample extends CounterExample { override def toString = "??" } - @inline def modelToVarAssignment(model: Model): Map[Var, (Seq[Const], Seq[Const])] = + def modelToVarAssignment(model: Model): Map[Var, (Seq[Const], Seq[Const])] = model.toSeq.groupBy{f => f match {case (sym, value) => sym.variable} }.mapValues{ xs => val (trues, falses) = xs.partition(_._2) (trues map (_._1.const), falses map (_._1.const)) @@ -2974,7 +2974,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL ( uniqueEqualTo.nonEmpty || (fields.nonEmpty && prunedEqualTo.isEmpty && notEqualTo.isEmpty)) => - @inline def args(brevity: Boolean = beBrief) = { + def args(brevity: Boolean = beBrief) = { // figure out the constructor arguments from the field assignment val argLen = (caseFieldAccs.length min ctorParams.length) diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index 167bf5c857..d82fbd7c77 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -48,8 +48,8 @@ trait Tags { * @param pos Position for error reporting. Please, provide meaningful value. * @param pre Prefix that represents a universe this type tag will be bound to. * If `pre` is set to `NoType`, then any type tag in scope will do, regardless of its affiliation. - * If `pre` is set to `NoType`, and tag resolution involves materialization, then `mkBasisPrefix` will be used. - * @param tp Type we're looking a TypeTag for, e.g. resolveTypeTag(pos, reflectBasisPrefix, IntClass.tpe, false) will look for scala.reflect.basis.TypeTag[Int]. + * If `pre` is set to `NoType`, and tag resolution involves materialization, then `mkRuntimeUniverseRef` will be used. + * @param tp Type we're looking a TypeTag for, e.g. resolveTypeTag(pos, mkRuntimeUniverseRef, IntClass.tpe, false) will look for scala.reflect.runtime.universe.TypeTag[Int]. * @param concrete If true then the result must not contain unresolved (i.e. not spliced) type parameters and abstract type members. * If false then the function will always succeed (abstract types will be reified as free types). * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no type tag in scope. @@ -59,11 +59,14 @@ trait Tags { * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members. * EmptyTree if `allowMaterialization` is false, and there is no array tag in scope. */ - def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = { - val tagSym = if (concrete) TypeTagClass else WeakTypeTagClass - val tagTp = if (pre == NoType) TypeRef(BaseUniverseClass.toTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) - val taggedTp = appliedType(tagTp, List(tp)) - resolveTag(pos, taggedTp, allowMaterialization) - } + def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = + // if someone requests a type tag, but scala-reflect.jar isn't on the library classpath, then bail + if (pre == NoType && ApiUniverseClass == NoSymbol) EmptyTree + else { + val tagSym = if (concrete) TypeTagClass else WeakTypeTagClass + val tagTp = if (pre == NoType) TypeRef(ApiUniverseClass.toTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) + val taggedTp = appliedType(tagTp, List(tp)) + resolveTag(pos, taggedTp, allowMaterialization) + } } }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 089245e124..af89af74d0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -91,7 +91,7 @@ trait Typers extends Modes with Adaptations with Tags { // - we may virtualize matches (if -Xexperimental and there's a suitable __match in scope) // - we synthesize PartialFunction implementations for `x => x match {...}` and `match {...}` when the expected type is PartialFunction // this is disabled by: -Xoldpatmat or interactive compilation (we run it for scaladoc due to SI-5933) - @inline private def newPatternMatching = opt.virtPatmat && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id) + private def newPatternMatching = opt.virtPatmat && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id) abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with TyperContextErrors { import context0.unit @@ -478,7 +478,6 @@ trait Typers extends Modes with Adaptations with Tags { /** The typer for an expression, depending on where we are. If we are before a superclass * call, this is a typer over a constructor context; otherwise it is the current typer. */ - @inline final def constrTyperIf(inConstr: Boolean): Typer = if (inConstr) { assert(context.undetparams.isEmpty, context.undetparams) @@ -1198,7 +1197,7 @@ trait Typers extends Modes with Adaptations with Tags { val found = tree.tpe if (!found.isErroneous && !pt.isErroneous) { - if (!context.reportErrors && isPastTyper) { + if ((!context.reportErrors && isPastTyper) || tree.attachments.get[MacroExpansionAttachment].isDefined) { val (bound, req) = pt match { case ExistentialType(qs, tpe) => (qs, tpe) case _ => (Nil, pt) @@ -1231,6 +1230,17 @@ trait Typers extends Modes with Adaptations with Tags { // to consistently transform skolems and fix 6029), I'd like to // investigate ways to avoid skolems completely. // + // upd. The same problem happens when we try to typecheck the result of macro expansion against its expected type + // (which is the return type of the macro definition instantiated in the context of expandee): + // + // Test.scala:2: error: type mismatch; + // found : $u.Expr[Class[_ <: Object]] + // required: reflect.runtime.universe.Expr[Class[?0(in value <local Test>)]] where type ?0(in value <local Test>) <: Object + // scala.reflect.runtime.universe.reify(new Object().getClass) + // ^ + // Therefore following Martin's advice I use this logic to recover from skolem errors after macro expansions + // (by adding the ` || tree.attachments.get[MacroExpansionAttachment].isDefined` clause to the conditional above). + // log("recovering from existential or skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree) return adapt(tree, mode, deriveTypeWithWildcards(boundOrSkolems)(pt)) } @@ -1395,8 +1405,10 @@ trait Typers extends Modes with Adaptations with Tags { case List(acc) => def isUnderlyingAcc(sym: Symbol) = sym == acc || acc.hasAccessorFlag && sym == acc.accessed - if (acc.accessBoundary(clazz) != rootMirror.RootClass) + if (acc.accessBoundary(clazz) != rootMirror.RootClass) unit.error(acc.pos, "value class needs to have a publicly accessible val parameter") + else if (acc.tpe.typeSymbol.isDerivedValueClass) + unit.error(acc.pos, "value class may not wrap another user-defined value class") for (stat <- body) if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol)) unit.error(stat.pos, @@ -1557,7 +1569,7 @@ trait Typers extends Modes with Adaptations with Tags { */ def validateParentClasses(parents: List[Tree], selfType: Type) { val pending = ListBuffer[AbsTypeError]() - @inline def validateDynamicParent(parent: Symbol) = + def validateDynamicParent(parent: Symbol) = if (parent == DynamicClass) checkFeature(parent.pos, DynamicsFeature) def validateParentClass(parent: Tree, superclazz: Symbol) = @@ -1977,32 +1989,44 @@ trait Typers extends Modes with Adaptations with Tags { * - the self-type of the refinement * - a type member of the refinement * - an abstract type declared outside of the refinement. + * - an instance of a value class + * Furthermore, the result type may not be a value class either */ - def checkMethodStructuralCompatible(meth: Symbol): Unit = { - def fail(msg: String) = unit.error(meth.pos, msg) + def checkMethodStructuralCompatible(ddef: DefDef): Unit = { + val meth = ddef.symbol + def fail(pos: Position, msg: String) = unit.error(pos, msg) val tp: Type = meth.tpe match { case mt @ MethodType(_, _) => mt case NullaryMethodType(restpe) => restpe // TODO_NMT: drop NullaryMethodType from resultType? case PolyType(_, restpe) => restpe case _ => NoType } - def failStruct(what: String) = - fail(s"Parameter type in structural refinement may not refer to $what") - for (paramType <- tp.paramTypes) { + def nthParamPos(n: Int) = ddef.vparamss match { + case xs :: _ if xs.length > n => xs(n).pos + case _ => meth.pos + } + def failStruct(pos: Position, what: String, where: String = "Parameter") = + fail(pos, s"$where type in structural refinement may not refer to $what") + + foreachWithIndex(tp.paramTypes) { (paramType, idx) => val sym = paramType.typeSymbol + def paramPos = nthParamPos(idx) if (sym.isAbstractType) { if (!sym.hasTransOwner(meth.owner)) - failStruct("an abstract type defined outside that refinement") + failStruct(paramPos, "an abstract type defined outside that refinement") else if (!sym.hasTransOwner(meth)) - failStruct("a type member of that refinement") + failStruct(paramPos, "a type member of that refinement") } if (sym.isDerivedValueClass) - failStruct("a user-defined value class") + failStruct(paramPos, "a user-defined value class") if (paramType.isInstanceOf[ThisType] && sym == meth.owner) - failStruct("the type of that refinement (self type)") + failStruct(paramPos, "the type of that refinement (self type)") } + if (tp.resultType.typeSymbol.isDerivedValueClass) + failStruct(ddef.tpt.pos, "a user-defined value class", where = "Result") } + def typedUseCase(useCase: UseCase) { def stringParser(str: String): syntaxAnalyzer.Parser = { val file = new BatchSourceFile(context.unit.source.file, str) { @@ -2119,7 +2143,7 @@ trait Typers extends Modes with Adaptations with Tags { } } if (meth.isStructuralRefinementMember) - checkMethodStructuralCompatible(meth) + checkMethodStructuralCompatible(ddef) if (meth.isImplicit && !meth.isSynthetic) meth.info.paramss match { case List(param) :: _ if !param.isImplicit => @@ -3806,7 +3830,8 @@ trait Typers extends Modes with Adaptations with Tags { case AssignOrNamedArg(Ident(name), rhs) => gen.mkTuple(List(CODE.LIT(name.toString), rhs)) case _ => gen.mkTuple(List(CODE.LIT(""), arg)) } - typed(treeCopy.Apply(orig, fun, args map argToBinding), mode, pt) + val t = treeCopy.Apply(orig, fun, args map argToBinding) + wrapErrors(t, _.typed(t, mode, pt)) } /** Translate selection that does not typecheck according to the normal rules into a selectDynamic/applyDynamic. @@ -3845,7 +3870,7 @@ trait Typers extends Modes with Adaptations with Tags { case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs) case t => (t, Nil) } - @inline def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty + def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty def desugaredApply = tree match { case Select(`qual`, nme.apply) => true @@ -3874,10 +3899,17 @@ trait Typers extends Modes with Adaptations with Tags { atPos(qual.pos)(Apply(tappSel, List(Literal(Constant(name.decode))))) } } + + def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = { + silent(typeTree) match { + case SilentResultValue(r) => r + case SilentTypeError(err) => DynamicRewriteError(tree, err) + } + } } - @inline final def deindentTyping() = context.typingIndentLevel -= 2 - @inline final def indentTyping() = context.typingIndentLevel += 2 + final def deindentTyping() = context.typingIndentLevel -= 2 + final def indentTyping() = context.typingIndentLevel += 2 @inline final def printTyping(s: => String) = { if (printTypings) println(context.typingIndent + s.replaceAll("\n", "\n" + context.typingIndent)) @@ -4067,7 +4099,8 @@ trait Typers extends Modes with Adaptations with Tags { } else if(dyna.isDynamicallyUpdatable(lhs1)) { val rhs1 = typed(rhs, EXPRmode | BYVALmode, WildcardType) - typed1(Apply(lhs1, List(rhs1)), mode, pt) + val t = Apply(lhs1, List(rhs1)) + dyna.wrapErrors(t, _.typed1(t, mode, pt)) } else fail() } @@ -4535,7 +4568,9 @@ trait Typers extends Modes with Adaptations with Tags { * @return ... */ def typedSelect(tree: Tree, qual: Tree, name: Name): Tree = { - def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map (typed1(_, mode, pt)) + def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map { t => + dyna.wrapErrors(t, (_.typed1(t, mode, pt))) + } val sym = tree.symbol orElse member(qual, name) orElse { // symbol not found? --> try to convert implicitly to a type that does have the required @@ -4696,12 +4731,10 @@ trait Typers extends Modes with Adaptations with Tags { */ def typedIdent(tree: Tree, name: Name): Tree = { var errorContainer: AbsTypeError = null - @inline def ambiguousError(msg: String) = { assert(errorContainer == null, "Cannot set ambiguous error twice for identifier") errorContainer = AmbiguousIdentError(tree, name, msg) } - @inline def identError(tree: AbsTypeError) = { assert(errorContainer == null, "Cannot set ambiguous error twice for identifier") errorContainer = tree diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 1c7a723f7f..65aba2b721 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -160,9 +160,9 @@ object ClassPath { override def isValidName(name: String) = !isTraitImplementation(name) } - @inline private def endsClass(s: String) = s.length > 6 && s.substring(s.length - 6) == ".class" - @inline private def endsScala(s: String) = s.length > 6 && s.substring(s.length - 6) == ".scala" - @inline private def endsJava(s: String) = s.length > 5 && s.substring(s.length - 5) == ".java" + private def endsClass(s: String) = s.length > 6 && s.substring(s.length - 6) == ".class" + private def endsScala(s: String) = s.length > 6 && s.substring(s.length - 6) == ".scala" + private def endsJava(s: String) = s.length > 5 && s.substring(s.length - 5) == ".java" /** From the source file to its identifier. */ diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala index 38e4e3c9f1..d35ac43424 100644 --- a/src/compiler/scala/tools/reflect/FastTrack.scala +++ b/src/compiler/scala/tools/reflect/FastTrack.scala @@ -30,10 +30,10 @@ trait FastTrack { lazy val fastTrack: Map[Symbol, FastTrackEntry] = { var registry = Map[Symbol, FastTrackEntry]() implicit class BindTo(sym: Symbol) { def bindTo(expander: FastTrackExpander): Unit = if (sym != NoSymbol) registry += sym -> FastTrackEntry(sym, expander) } - MacroInternal_materializeClassTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeClassTag(u, tt.tpe) } - MacroInternal_materializeWeakTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = false) } - MacroInternal_materializeTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = true) } - BaseUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) } + materializeClassTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List())) => c.materializeClassTag(tt.tpe) } + materializeWeakTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = false) } + materializeTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = true) } + ApiUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) } ReflectRuntimeCurrentMirror bindTo { case (c, _) => scala.reflect.runtime.Macros.currentMirror(c).tree } StringContext_f bindTo { case (c, app@Apply(Select(Apply(_, parts), _), args)) => c.macro_StringInterpolation_f(parts, args, app.pos) } registry diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala index 0704189ddc..94fd8e1fe8 100644 --- a/src/compiler/scala/tools/reflect/StdTags.scala +++ b/src/compiler/scala/tools/reflect/StdTags.scala @@ -3,21 +3,21 @@ package reflect import java.lang.{Class => jClass} import scala.reflect.{ClassTag, classTag} -import scala.reflect.base.{MirrorOf, TypeCreator, Universe => BaseUniverse} +import scala.reflect.api.{MirrorOf, TypeCreator, Universe => ApiUniverse} // [Eugene++] Before 2.10 is released, I suggest we don't rely on automated type tag generation // sure, it's convenient, but then refactoring reflection / reification becomes a pain // `ClassTag` tags are fine, because they don't need a reifier to be generated trait StdTags { - val u: BaseUniverse with Singleton + val u: ApiUniverse with Singleton val m: MirrorOf[u.type] lazy val tagOfListOfString: u.TypeTag[List[String]] = u.TypeTag[List[String]]( m, new TypeCreator { - def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = { + def apply[U <: ApiUniverse with Singleton](m: MirrorOf[U]): U # Type = { val u = m.universe val pre = u.ThisType(m.staticPackage("scala.collection.immutable").moduleClass.asInstanceOf[u.Symbol]) u.TypeRef(pre, u.definitions.ListClass, List(u.definitions.StringClass.toTypeConstructor)) @@ -28,7 +28,7 @@ trait StdTags { u.TypeTag[T]( m, new TypeCreator { - def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = + def apply[U <: ApiUniverse with Singleton](m: MirrorOf[U]): U # Type = m.staticClass(classTag[T].runtimeClass.getName).toTypeConstructor.asInstanceOf[U # Type] }) lazy val tagOfInt = u.TypeTag.Int diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index 9e7d230a6a..f627699597 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -1,10 +1,7 @@ package scala.tools package reflect -import scala.reflect.api.Universe -import scala.reflect.base.MirrorOf - -trait ToolBox[U <: Universe] { +trait ToolBox[U <: scala.reflect.api.Universe] { /** Underlying universe of a ToolBox */ diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index d941519958..f985eedf99 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -14,7 +14,6 @@ import java.lang.{Class => jClass} import scala.compat.Platform.EOL import scala.reflect.NameTransformer import scala.reflect.api.JavaUniverse -import scala.reflect.base.MirrorOf abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => @@ -70,6 +69,14 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } } + def wrapIntoTerm(tree: Tree): Tree = + if (!tree.isTerm) Block(List(tree), Literal(Constant(()))) else tree + + def unwrapFromTerm(tree: Tree): Tree = tree match { + case Block(List(tree), Literal(Constant(()))) => tree + case tree => tree + } + def extractFreeTerms(expr0: Tree, wrapFreeTermRefs: Boolean): (Tree, scala.collection.mutable.LinkedHashMap[FreeTermSymbol, TermName]) = { val freeTerms = expr0.freeTerms val freeTermNames = scala.collection.mutable.LinkedHashMap[FreeTermSymbol, TermName]() @@ -102,7 +109,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => // need to wrap the expr, because otherwise you won't be able to typecheck macros against something that contains free vars var (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = false) val dummies = freeTerms.map{ case (freeTerm, name) => ValDef(NoMods, name, TypeTree(freeTerm.info), Select(Ident(PredefModule), newTermName("$qmark$qmark$qmark"))) }.toList - expr = Block(dummies, expr) + expr = Block(dummies, wrapIntoTerm(expr)) // [Eugene] how can we implement that? // !!! Why is this is in the empty package? If it's only to make @@ -111,7 +118,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val ownerClass = rootMirror.EmptyPackageClass.newClassSymbol(newTypeName("<expression-owner>")) build.setTypeSignature(ownerClass, ClassInfoType(List(ObjectClass.tpe), newScope, ownerClass)) val owner = ownerClass.newLocalDummy(expr.pos) - var currentTyper = typer.atOwner(expr, owner) + var currentTyper = analyzer.newTyper(analyzer.rootContext(NoCompilationUnit, EmptyTree).make(expr, owner)) val wrapper1 = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _) val wrapper2 = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _) def wrapper (tree: => Tree) = wrapper1(wrapper2(tree)) @@ -137,6 +144,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } }.transform(unwrapped) new TreeTypeSubstituter(dummies1 map (_.symbol), dummies1 map (dummy => SingleType(NoPrefix, invertedIndex(dummy.symbol.name)))).traverse(unwrapped) + unwrapped = if (expr0.isTerm) unwrapped else unwrapFromTerm(unwrapped) unwrapped } @@ -170,12 +178,14 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } }) - def compile(expr: Tree): () => Any = { + def compile(expr0: Tree): () => Any = { + val expr = wrapIntoTerm(expr0) + val freeTerms = expr.freeTerms // need to calculate them here, because later on they will be erased val thunks = freeTerms map (fte => () => fte.value) // need to be lazy in order not to distort evaluation order verify(expr) - def wrap(expr0: Tree): Tree = { + def wrap(expr0: Tree): ModuleDef = { val (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = true) val (obj, mclazz) = rootMirror.EmptyPackageClass.newModuleAndClassSymbol( @@ -213,11 +223,11 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => var cleanedUp = resetLocalAttrs(moduledef) trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value)) - cleanedUp + cleanedUp.asInstanceOf[ModuleDef] } val mdef = wrap(expr) - val pdef = PackageDef(Ident(nme.EMPTY_PACKAGE_NAME), List(mdef)) + val pdef = PackageDef(Ident(mdef.name), List(mdef)) val unit = new CompilationUnit(NoSourceFile) unit.body = pdef diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 945b0a0c3b..880f3f4623 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -196,7 +196,7 @@ sealed abstract class Option[+A] extends Product with Serializable { /** Necessary to keep $option from being implicitly converted to * [[scala.collection.Iterable]] in `for` comprehensions. */ - def withFilter(p: A => Boolean): WithFilter = new WithFilter(p) + @inline final def withFilter(p: A => Boolean): WithFilter = new WithFilter(p) /** We need a whole WithFilter class to honor the "doesn't create a new * collection" contract even though it seems unlikely to matter much in a @@ -246,7 +246,7 @@ sealed abstract class Option[+A] extends Product with Serializable { * @return the result of applying `pf` to this $option's * value (if possible), or $none. */ - def collect[B](pf: PartialFunction[A, B]): Option[B] = + @inline final def collect[B](pf: PartialFunction[A, B]): Option[B] = if (!isEmpty && pf.isDefinedAt(this.get)) Some(pf(this.get)) else None /** Returns this $option if it is nonempty, diff --git a/src/library/scala/PartialFunction.scala b/src/library/scala/PartialFunction.scala index 7c6e2d2e3e..ce109626cc 100644 --- a/src/library/scala/PartialFunction.scala +++ b/src/library/scala/PartialFunction.scala @@ -156,7 +156,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => object PartialFunction { /** Composite function produced by `PartialFunction#orElse` method */ - private final class OrElse[-A, +B] (f1: PartialFunction[A, B], f2: PartialFunction[A, B]) extends PartialFunction[A, B] { + private class OrElse[-A, +B] (f1: PartialFunction[A, B], f2: PartialFunction[A, B]) extends PartialFunction[A, B] { def isDefinedAt(x: A) = f1.isDefinedAt(x) || f2.isDefinedAt(x) def apply(x: A): B = f1.applyOrElse(x, f2) @@ -175,7 +175,7 @@ object PartialFunction { /** Composite function produced by `PartialFunction#andThen` method */ - private final class AndThen[-A, B, +C] (pf: PartialFunction[A, B], k: B => C) extends PartialFunction[A, C] { + private class AndThen[-A, B, +C] (pf: PartialFunction[A, B], k: B => C) extends PartialFunction[A, C] { def isDefinedAt(x: A) = pf.isDefinedAt(x) def apply(x: A): C = k(pf(x)) @@ -207,11 +207,11 @@ object PartialFunction { * * Here `fallback_pf` is used as both unique marker object and special fallback function that returns it. */ - private[this] final val fallback_pf: PartialFunction[Any, Any] = { case _ => fallback_pf } - @inline private final def checkFallback[B] = fallback_pf.asInstanceOf[PartialFunction[Any, B]] - @inline private final def fallbackOccurred[B](x: B) = (fallback_pf eq x.asInstanceOf[AnyRef]) + private[this] val fallback_pf: PartialFunction[Any, Any] = { case _ => fallback_pf } + private def checkFallback[B] = fallback_pf.asInstanceOf[PartialFunction[Any, B]] + private def fallbackOccurred[B](x: B) = (fallback_pf eq x.asInstanceOf[AnyRef]) - private final class Lifted[-A, +B] (val pf: PartialFunction[A, B]) + private class Lifted[-A, +B] (val pf: PartialFunction[A, B]) extends scala.runtime.AbstractFunction1[A, Option[B]] { def apply(x: A): Option[B] = { @@ -220,7 +220,7 @@ object PartialFunction { } } - private final class Unlifted[A, B] (f: A => Option[B]) extends scala.runtime.AbstractPartialFunction[A, B] { + private class Unlifted[A, B] (f: A => Option[B]) extends scala.runtime.AbstractPartialFunction[A, B] { def isDefinedAt(x: A): Boolean = f(x).isDefined override def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = { @@ -241,9 +241,9 @@ object PartialFunction { */ def apply[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) } - private[this] final val constFalse: Any => Boolean = { _ => false} + private[this] val constFalse: Any => Boolean = { _ => false} - private[this] final val empty_pf: PartialFunction[Any, Nothing] = new PartialFunction[Any, Nothing] { + private[this] val empty_pf: PartialFunction[Any, Nothing] = new PartialFunction[Any, Nothing] { def isDefinedAt(x: Any) = false def apply(x: Any) = throw new MatchError(x) override def orElse[A1, B1](that: PartialFunction[A1, B1]) = that diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index a3ff812024..cda8b1a0e4 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -735,8 +735,8 @@ object SeqLike { */ private def kmpSearch[B](S: Seq[B], m0: Int, m1: Int, W: Seq[B], n0: Int, n1: Int, forward: Boolean): Int = { // Check for redundant case when target has single valid element - @inline def clipR(x: Int, y: Int) = if (x<y) x else -1 - @inline def clipL(x: Int, y: Int) = if (x>y) x else -1 + def clipR(x: Int, y: Int) = if (x < y) x else -1 + def clipL(x: Int, y: Int) = if (x > y) x else -1 if (n1 == n0+1) { if (forward) diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index 070497c19e..4f9f13c794 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -25,13 +25,13 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends def this(g: Gen) = this(null, g) - @inline final def WRITE(nval: MainNode[K, V]) = INodeBase.updater.set(this, nval) + def WRITE(nval: MainNode[K, V]) = INodeBase.updater.set(this, nval) - @inline final def CAS(old: MainNode[K, V], n: MainNode[K, V]) = INodeBase.updater.compareAndSet(this, old, n) + def CAS(old: MainNode[K, V], n: MainNode[K, V]) = INodeBase.updater.compareAndSet(this, old, n) - final def gcasRead(ct: TrieMap[K, V]): MainNode[K, V] = GCAS_READ(ct) + def gcasRead(ct: TrieMap[K, V]): MainNode[K, V] = GCAS_READ(ct) - @inline final def GCAS_READ(ct: TrieMap[K, V]): MainNode[K, V] = { + def GCAS_READ(ct: TrieMap[K, V]): MainNode[K, V] = { val m = /*READ*/mainnode val prevval = /*READ*/m.prev if (prevval eq null) m @@ -70,7 +70,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends } } - @inline final def GCAS(old: MainNode[K, V], n: MainNode[K, V], ct: TrieMap[K, V]): Boolean = { + def GCAS(old: MainNode[K, V], n: MainNode[K, V], ct: TrieMap[K, V]): Boolean = { n.WRITE_PREV(old) if (CAS(old, n)) { GCAS_Complete(n, ct) @@ -78,16 +78,15 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends } else false } - @inline private def equal(k1: K, k2: K, ct: TrieMap[K, V]) = ct.equality.equiv(k1, k2) - @inline private def inode(cn: MainNode[K, V]) = { + private def inode(cn: MainNode[K, V]) = { val nin = new INode[K, V](gen) nin.WRITE(cn) nin } - final def copyToGen(ngen: Gen, ct: TrieMap[K, V]) = { + def copyToGen(ngen: Gen, ct: TrieMap[K, V]) = { val nin = new INode[K, V](ngen) val main = GCAS_READ(ct) nin.WRITE(main) @@ -98,7 +97,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * * @return true if successful, false otherwise */ - @tailrec final def rec_insert(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): Boolean = { + @tailrec def rec_insert(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): Boolean = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -144,7 +143,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * @param cond null - don't care if the key was there; KEY_ABSENT - key wasn't there; KEY_PRESENT - key was there; other value `v` - key must be bound to `v` * @return null if unsuccessful, Option[V] otherwise (indicating previous value bound to the key) */ - @tailrec final def rec_insertif(k: K, v: V, hc: Int, cond: AnyRef, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): Option[V] = { + @tailrec def rec_insertif(k: K, v: V, hc: Int, cond: AnyRef, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): Option[V] = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -203,7 +202,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends clean(parent, ct, lev - 5) null case ln: LNode[K, V] => // 3) an l-node - @inline def insertln() = { + def insertln() = { val nn = ln.inserted(k, v) GCAS(ln, nn, ct) } @@ -234,7 +233,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * * @return null if no value has been found, RESTART if the operation wasn't successful, or any other value otherwise */ - @tailrec final def rec_lookup(k: K, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): AnyRef = { + @tailrec def rec_lookup(k: K, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): AnyRef = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -277,7 +276,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * @param v if null, will remove the key irregardless of the value; otherwise removes only if binding contains that exact key and value * @return null if not successful, an Option[V] indicating the previous value otherwise */ - final def rec_remove(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): Option[V] = { + def rec_remove(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: TrieMap[K, V]): Option[V] = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -361,9 +360,9 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends } } - final def isNullInode(ct: TrieMap[K, V]) = GCAS_READ(ct) eq null + def isNullInode(ct: TrieMap[K, V]) = GCAS_READ(ct) eq null - final def cachedSize(ct: TrieMap[K, V]): Int = { + def cachedSize(ct: TrieMap[K, V]): Int = { val m = GCAS_READ(ct) m.cachedSize(ct) } @@ -448,11 +447,9 @@ extends MainNode[K, V] { } -private[collection] final class CNode[K, V](final val bitmap: Int, final val array: Array[BasicNode], final val gen: Gen) -extends CNodeBase[K, V] { - +private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[BasicNode], val gen: Gen) extends CNodeBase[K, V] { // this should only be called from within read-only snapshots - final def cachedSize(ct: AnyRef) = { + def cachedSize(ct: AnyRef) = { val currsz = READ_SIZE() if (currsz != -1) currsz else { @@ -486,7 +483,7 @@ extends CNodeBase[K, V] { sz } - final def updatedAt(pos: Int, nn: BasicNode, gen: Gen) = { + def updatedAt(pos: Int, nn: BasicNode, gen: Gen) = { val len = array.length val narr = new Array[BasicNode](len) Array.copy(array, 0, narr, 0, len) @@ -494,7 +491,7 @@ extends CNodeBase[K, V] { new CNode[K, V](bitmap, narr, gen) } - final def removedAt(pos: Int, flag: Int, gen: Gen) = { + def removedAt(pos: Int, flag: Int, gen: Gen) = { val arr = array val len = arr.length val narr = new Array[BasicNode](len - 1) @@ -503,7 +500,7 @@ extends CNodeBase[K, V] { new CNode[K, V](bitmap ^ flag, narr, gen) } - final def insertedAt(pos: Int, flag: Int, nn: BasicNode, gen: Gen) = { + def insertedAt(pos: Int, flag: Int, nn: BasicNode, gen: Gen) = { val len = array.length val bmp = bitmap val narr = new Array[BasicNode](len + 1) @@ -516,7 +513,7 @@ extends CNodeBase[K, V] { /** Returns a copy of this cnode such that all the i-nodes below it are copied * to the specified generation `ngen`. */ - final def renewed(ngen: Gen, ct: TrieMap[K, V]) = { + def renewed(ngen: Gen, ct: TrieMap[K, V]) = { var i = 0 val arr = array val len = arr.length @@ -536,7 +533,7 @@ extends CNodeBase[K, V] { case _ => inode } - final def toContracted(lev: Int): MainNode[K, V] = if (array.length == 1 && lev > 0) array(0) match { + def toContracted(lev: Int): MainNode[K, V] = if (array.length == 1 && lev > 0) array(0) match { case sn: SNode[K, V] => sn.copyTombed case _ => this } else this @@ -547,7 +544,7 @@ extends CNodeBase[K, V] { // returns the version of this node with at least some null-inodes // removed (those existing when the op began) // - if there are only null-i-nodes below, returns null - final def toCompressed(ct: TrieMap[K, V], lev: Int, gen: Gen) = { + def toCompressed(ct: TrieMap[K, V], lev: Int, gen: Gen) = { var bmp = bitmap var i = 0 val arr = array @@ -571,7 +568,7 @@ extends CNodeBase[K, V] { private[concurrent] def string(lev: Int): String = "CNode %x\n%s".format(bitmap, array.map(_.string(lev + 1)).mkString("\n")) /* quiescently consistent - don't call concurrently to anything involving a GCAS!! */ - protected def collectElems: Seq[(K, V)] = array flatMap { + private def collectElems: Seq[(K, V)] = array flatMap { case sn: SNode[K, V] => Some(sn.kvPair) case in: INode[K, V] => in.mainnode match { case tn: TNode[K, V] => Some(tn.kvPair) @@ -580,7 +577,7 @@ extends CNodeBase[K, V] { } } - protected def collectLocalElems: Seq[String] = array flatMap { + private def collectLocalElems: Seq[String] = array flatMap { case sn: SNode[K, V] => Some(sn.kvPair._2.toString) case in: INode[K, V] => Some(in.toString.drop(14) + "(" + in.gen + ")") } @@ -687,11 +684,11 @@ extends scala.collection.concurrent.Map[K, V] } while (obj != TrieMapSerializationEnd) } - @inline final def CAS_ROOT(ov: AnyRef, nv: AnyRef) = rootupdater.compareAndSet(this, ov, nv) + def CAS_ROOT(ov: AnyRef, nv: AnyRef) = rootupdater.compareAndSet(this, ov, nv) - final def readRoot(abort: Boolean = false): INode[K, V] = RDCSS_READ_ROOT(abort) + def readRoot(abort: Boolean = false): INode[K, V] = RDCSS_READ_ROOT(abort) - @inline final def RDCSS_READ_ROOT(abort: Boolean = false): INode[K, V] = { + def RDCSS_READ_ROOT(abort: Boolean = false): INode[K, V] = { val r = /*READ*/root r match { case in: INode[K, V] => in @@ -781,9 +778,9 @@ extends scala.collection.concurrent.Map[K, V] override def empty: TrieMap[K, V] = new TrieMap[K, V] - final def isReadOnly = rootupdater eq null + def isReadOnly = rootupdater eq null - final def nonReadOnly = rootupdater ne null + def nonReadOnly = rootupdater ne null /** Returns a snapshot of this TrieMap. * This operation is lock-free and linearizable. @@ -794,7 +791,7 @@ extends scala.collection.concurrent.Map[K, V] * TrieMap is distributed across all the threads doing updates or accesses * subsequent to the snapshot creation. */ - @tailrec final def snapshot(): TrieMap[K, V] = { + @tailrec def snapshot(): TrieMap[K, V] = { val r = RDCSS_READ_ROOT() val expmain = r.gcasRead(this) if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new TrieMap(r.copyToGen(new Gen, this), rootupdater, hashing, equality) @@ -813,34 +810,34 @@ extends scala.collection.concurrent.Map[K, V] * * This method is used by other methods such as `size` and `iterator`. */ - @tailrec final def readOnlySnapshot(): scala.collection.Map[K, V] = { + @tailrec def readOnlySnapshot(): scala.collection.Map[K, V] = { val r = RDCSS_READ_ROOT() val expmain = r.gcasRead(this) if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new TrieMap(r, null, hashing, equality) else readOnlySnapshot() } - @tailrec final override def clear() { + @tailrec override def clear() { val r = RDCSS_READ_ROOT() if (!RDCSS_ROOT(r, r.gcasRead(this), INode.newRootNode[K, V])) clear() } - @inline + def computeHash(k: K) = hashingobj.hash(k) - final def lookup(k: K): V = { + def lookup(k: K): V = { val hc = computeHash(k) lookuphc(k, hc).asInstanceOf[V] } - final override def apply(k: K): V = { + override def apply(k: K): V = { val hc = computeHash(k) val res = lookuphc(k, hc) if (res eq null) throw new NoSuchElementException else res.asInstanceOf[V] } - final def get(k: K): Option[V] = { + def get(k: K): Option[V] = { val hc = computeHash(k) Option(lookuphc(k, hc)).asInstanceOf[Option[V]] } @@ -850,22 +847,22 @@ extends scala.collection.concurrent.Map[K, V] insertifhc(key, hc, value, null) } - final override def update(k: K, v: V) { + override def update(k: K, v: V) { val hc = computeHash(k) inserthc(k, hc, v) } - final def +=(kv: (K, V)) = { + def +=(kv: (K, V)) = { update(kv._1, kv._2) this } - final override def remove(k: K): Option[V] = { + override def remove(k: K): Option[V] = { val hc = computeHash(k) removehc(k, null.asInstanceOf[V], hc) } - final def -=(k: K) = { + def -=(k: K) = { remove(k) this } @@ -960,12 +957,12 @@ private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: current = null } - @inline private def checkSubiter() = if (!subiter.hasNext) { + private def checkSubiter() = if (!subiter.hasNext) { subiter = null advance() } - @inline private def initialize() { + private def initialize() { assert(ct.isReadOnly) val r = ct.RDCSS_READ_ROOT() diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index a2875ec3fb..92ea5d3f04 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -127,7 +127,7 @@ extends scala.collection.AbstractSeq[Int] } } - @inline final def apply(idx: Int): Int = { + final def apply(idx: Int): Int = { validateMaxLength() if (idx < 0 || idx >= numRangeElements) throw new IndexOutOfBoundsException(idx.toString) else start + (step * idx) @@ -346,11 +346,11 @@ object Range { /** Make an inclusive range from `start` to `end` with given step value. * @note step != 0 */ - @inline def inclusive(start: Int, end: Int, step: Int): Range.Inclusive = new Inclusive(start, end, step) + def inclusive(start: Int, end: Int, step: Int): Range.Inclusive = new Inclusive(start, end, step) /** Make an inclusive range from `start` to `end` with step value 1. */ - @inline def inclusive(start: Int, end: Int): Range.Inclusive = new Inclusive(start, end, 1) + def inclusive(start: Int, end: Int): Range.Inclusive = new Inclusive(start, end, 1) // BigInt and Long are straightforward generic ranges. object BigInt { diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala index 5bdba26d02..bb489dd80a 100644 --- a/src/library/scala/collection/immutable/RedBlackTree.scala +++ b/src/library/scala/collection/immutable/RedBlackTree.scala @@ -132,6 +132,15 @@ object RedBlackTree { else if (overwrite || k != tree.key) mkTree(isBlackTree(tree), k, v, tree.left, tree.right) else tree } + private[this] def updNth[A, B, B1 >: B](tree: Tree[A, B], idx: Int, k: A, v: B1, overwrite: Boolean): Tree[A, B1] = if (tree eq null) { + RedTree(k, v, null, null) + } else { + val rank = count(tree.left) + 1 + if (idx < rank) balanceLeft(isBlackTree(tree), tree.key, tree.value, updNth(tree.left, idx, k, v, overwrite), tree.right) + else if (idx > rank) balanceRight(isBlackTree(tree), tree.key, tree.value, tree.left, updNth(tree.right, idx - rank, k, v, overwrite)) + else if (overwrite) mkTree(isBlackTree(tree), k, v, tree.left, tree.right) + else tree + } /* Based on Stefan Kahrs' Haskell version of Okasaki's Red&Black Trees * http://www.cse.unsw.edu.au/~dons/data/RedBlackTree.html */ @@ -249,27 +258,27 @@ object RedBlackTree { else rebalance(tree, newLeft, newRight) } - private[this] def doDrop[A: Ordering, B](tree: Tree[A, B], n: Int): Tree[A, B] = { + private[this] def doDrop[A, B](tree: Tree[A, B], n: Int): Tree[A, B] = { if (n <= 0) return tree if (n >= this.count(tree)) return null val count = this.count(tree.left) if (n > count) return doDrop(tree.right, n - count - 1) val newLeft = doDrop(tree.left, n) if (newLeft eq tree.left) tree - else if (newLeft eq null) upd(tree.right, tree.key, tree.value, false) + else if (newLeft eq null) updNth(tree.right, n - count - 1, tree.key, tree.value, false) else rebalance(tree, newLeft, tree.right) } - private[this] def doTake[A: Ordering, B](tree: Tree[A, B], n: Int): Tree[A, B] = { + private[this] def doTake[A, B](tree: Tree[A, B], n: Int): Tree[A, B] = { if (n <= 0) return null if (n >= this.count(tree)) return tree val count = this.count(tree.left) if (n <= count) return doTake(tree.left, n) val newRight = doTake(tree.right, n - count - 1) if (newRight eq tree.right) tree - else if (newRight eq null) upd(tree.left, tree.key, tree.value, false) + else if (newRight eq null) updNth(tree.left, n, tree.key, tree.value, false) else rebalance(tree, tree.left, newRight) } - private[this] def doSlice[A: Ordering, B](tree: Tree[A, B], from: Int, until: Int): Tree[A, B] = { + private[this] def doSlice[A, B](tree: Tree[A, B], from: Int, until: Int): Tree[A, B] = { if (tree eq null) return null val count = this.count(tree.left) if (from > count) return doSlice(tree.right, from - count - 1, until - count - 1) @@ -277,8 +286,8 @@ object RedBlackTree { val newLeft = doDrop(tree.left, from) val newRight = doTake(tree.right, until - count - 1) if ((newLeft eq tree.left) && (newRight eq tree.right)) tree - else if (newLeft eq null) upd(newRight, tree.key, tree.value, false) - else if (newRight eq null) upd(newLeft, tree.key, tree.value, false) + else if (newLeft eq null) updNth(newRight, from - count - 1, tree.key, tree.value, false) + else if (newRight eq null) updNth(newLeft, until, tree.key, tree.value, false) else rebalance(tree, newLeft, newRight) } @@ -380,7 +389,7 @@ object RedBlackTree { @(inline @getter) final val left: Tree[A, B], @(inline @getter) final val right: Tree[A, B]) extends Serializable { - final val count: Int = 1 + RedBlackTree.count(left) + RedBlackTree.count(right) + @(inline @getter) final val count: Int = 1 + RedBlackTree.count(left) + RedBlackTree.count(right) def black: Tree[A, B] def red: Tree[A, B] } diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index 98b5aa6d9f..a33bf2c9c5 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -25,11 +25,11 @@ object Vector extends SeqFactory[Vector] { private val VectorReusableCBF: GenericCanBuildFrom[Nothing] = new VectorReusableCBF - @inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] = + implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] = VectorReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]] def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A] private[immutable] val NIL = new Vector[Nothing](0, 0, 0) - @inline override def empty[A]: Vector[A] = NIL + override def empty[A]: Vector[A] = NIL } // in principle, most members should be private. however, access privileges must @@ -94,7 +94,7 @@ override def companion: GenericCompanion[Vector] = Vector if (s.depth > 1) s.gotoPos(startIndex, startIndex ^ focus) } - @inline override def iterator: VectorIterator[A] = { + override def iterator: VectorIterator[A] = { val s = new VectorIterator[A](startIndex, endIndex) initIterator(s) s @@ -120,16 +120,6 @@ override def companion: GenericCompanion[Vector] = Vector // In principle, escape analysis could even remove the iterator/builder allocations and do it // with local variables exclusively. But we're not quite there yet ... - @deprecated("this method is experimental and will be removed in a future release", "2.8.0") - @inline def foreachFast[U](f: A => U): Unit = iterator.foreachFast(f) - @deprecated("this method is experimental and will be removed in a future release", "2.8.0") - @inline def mapFast[B, That](f: A => B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = { - val b = bf(repr) - foreachFast(x => b += f(x)) - b.result - } - - def apply(index: Int): A = { val idx = checkRangeConvert(index) //println("get elem: "+index + "/"+idx + "(focus:" +focus+" xor:"+(idx^focus)+" depth:"+depth+")") @@ -147,17 +137,17 @@ override def companion: GenericCompanion[Vector] = Vector // SeqLike api - @inline override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match { + override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match { case _: Vector.VectorReusableCBF => updateAt(index, elem).asInstanceOf[That] // just ignore bf case _ => super.updated(index, elem)(bf) } - @inline override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match { + override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match { case _: Vector.VectorReusableCBF => appendFront(elem).asInstanceOf[That] // just ignore bf case _ => super.+:(elem)(bf) } - @inline override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match { + override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match { case _: Vector.VectorReusableCBF => appendBack(elem).asInstanceOf[That] // just ignore bf case _ => super.:+(elem)(bf) } @@ -696,9 +686,6 @@ extends AbstractIterator[A] v.initFrom(this) v } - - @deprecated("this method is experimental and will be removed in a future release", "2.8.0") - @inline def foreachFast[U](f: A => U) { while (hasNext) f(next()) } } diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index abd8c1cdff..1fc3928531 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -43,12 +43,12 @@ class PriorityQueue[A](implicit val ord: Ordering[A]) { import ord._ - private final class ResizableArrayAccess[A] extends AbstractSeq[A] with ResizableArray[A] { - @inline def p_size0 = size0 - @inline def p_size0_=(s: Int) = size0 = s - @inline def p_array = array - @inline def p_ensureSize(n: Int) = super.ensureSize(n) - @inline def p_swap(a: Int, b: Int) = super.swap(a, b) + private class ResizableArrayAccess[A] extends AbstractSeq[A] with ResizableArray[A] { + def p_size0 = size0 + def p_size0_=(s: Int) = size0 = s + def p_array = array + def p_ensureSize(n: Int) = super.ensureSize(n) + def p_swap(a: Int, b: Int) = super.swap(a, b) } protected[this] override def newBuilder = new PriorityQueue[A] diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala index 655115349a..3bd7617bce 100644 --- a/src/library/scala/concurrent/Awaitable.scala +++ b/src/library/scala/concurrent/Awaitable.scala @@ -10,7 +10,7 @@ package scala.concurrent -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration diff --git a/src/library/scala/concurrent/duration/Deadline.scala b/src/library/scala/concurrent/duration/Deadline.scala new file mode 100644 index 0000000000..50e9a75ff7 --- /dev/null +++ b/src/library/scala/concurrent/duration/Deadline.scala @@ -0,0 +1,81 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent.duration + +/** + * This class stores a deadline, as obtained via `Deadline.now` or the + * duration DSL: + * + * {{{ + * import scala.concurrent.duration._ + * 3.seconds.fromNow + * }}} + * + * Its main purpose is to manage repeated attempts to achieve something (like + * awaiting a condition) by offering the methods `hasTimeLeft` and `timeLeft`. All + * durations are measured according to `System.nanoTime` aka wall-time; this + * does not take into account changes to the system clock (such as leap + * seconds). + */ +case class Deadline private (time: FiniteDuration) extends Ordered[Deadline] { + /** + * Return a deadline advanced (i.e. moved into the future) by the given duration. + */ + def +(other: FiniteDuration): Deadline = copy(time = time + other) + /** + * Return a deadline moved backwards (i.e. towards the past) by the given duration. + */ + def -(other: FiniteDuration): Deadline = copy(time = time - other) + /** + * Calculate time difference between this and the other deadline, where the result is directed (i.e. may be negative). + */ + def -(other: Deadline): FiniteDuration = time - other.time + /** + * Calculate time difference between this duration and now; the result is negative if the deadline has passed. + * + * '''''Note that on some systems this operation is costly because it entails a system call.''''' + * Check `System.nanoTime` for your platform. + */ + def timeLeft: FiniteDuration = this - Deadline.now + /** + * Determine whether the deadline still lies in the future at the point where this method is called. + * + * '''''Note that on some systems this operation is costly because it entails a system call.''''' + * Check `System.nanoTime` for your platform. + */ + def hasTimeLeft(): Boolean = !isOverdue() + /** + * Determine whether the deadline lies in the past at the point where this method is called. + * + * '''''Note that on some systems this operation is costly because it entails a system call.''''' + * Check `System.nanoTime` for your platform. + */ + def isOverdue(): Boolean = (time.toNanos - System.nanoTime()) < 0 + /** + * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. + */ + def compare(other: Deadline) = time compare other.time +} + +object Deadline { + /** + * Construct a deadline due exactly at the point where this method is called. Useful for then + * advancing it to obtain a future deadline, or for sampling the current time exactly once and + * then comparing it to multiple deadlines (using subtraction). + */ + def now: Deadline = Deadline(Duration(System.nanoTime, NANOSECONDS)) + + /** + * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. + */ + implicit object DeadlineIsOrdered extends Ordering[Deadline] { + def compare(a: Deadline, b: Deadline) = a compare b + } + +} diff --git a/src/library/scala/concurrent/util/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala index 3f8b98831e..79f9b4db86 100644 --- a/src/library/scala/concurrent/util/Duration.scala +++ b/src/library/scala/concurrent/duration/Duration.scala @@ -6,90 +6,12 @@ ** |/ ** \* */ -package scala.concurrent.util +package scala.concurrent.duration -import java.util.concurrent.TimeUnit -import TimeUnit._ import java.lang.{ Double => JDouble, Long => JLong } import scala.language.implicitConversions -/** - * This class stores a deadline, as obtained via `Deadline.now` or the - * duration DSL: - * - * {{{ - * import scala.concurrent.util.duration._ - * 3.seconds.fromNow - * }}} - * - * Its main purpose is to manage repeated attempts to achieve something (like - * awaiting a condition) by offering the methods `hasTimeLeft` and `timeLeft`. All - * durations are measured according to `System.nanoTime` aka wall-time; this - * does not take into account changes to the system clock (such as leap - * seconds). - */ -case class Deadline private (time: FiniteDuration) extends Ordered[Deadline] { - /** - * Return a deadline advanced (i.e. moved into the future) by the given duration. - */ - def +(other: FiniteDuration): Deadline = copy(time = time + other) - /** - * Return a deadline moved backwards (i.e. towards the past) by the given duration. - */ - def -(other: FiniteDuration): Deadline = copy(time = time - other) - /** - * Calculate time difference between this and the other deadline, where the result is directed (i.e. may be negative). - */ - def -(other: Deadline): FiniteDuration = time - other.time - /** - * Calculate time difference between this duration and now; the result is negative if the deadline has passed. - * - * '''''Note that on some systems this operation is costly because it entails a system call.''''' - * Check `System.nanoTime` for your platform. - */ - def timeLeft: FiniteDuration = this - Deadline.now - /** - * Determine whether the deadline still lies in the future at the point where this method is called. - * - * '''''Note that on some systems this operation is costly because it entails a system call.''''' - * Check `System.nanoTime` for your platform. - */ - def hasTimeLeft(): Boolean = !isOverdue() - /** - * Determine whether the deadline lies in the past at the point where this method is called. - * - * '''''Note that on some systems this operation is costly because it entails a system call.''''' - * Check `System.nanoTime` for your platform. - */ - def isOverdue(): Boolean = (time.toNanos - System.nanoTime()) < 0 - /** - * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. - */ - def compare(other: Deadline) = time compare other.time -} - -object Deadline { - /** - * Construct a deadline due exactly at the point where this method is called. Useful for then - * advancing it to obtain a future deadline, or for sampling the current time exactly once and - * then comparing it to multiple deadlines (using subtraction). - */ - def now: Deadline = Deadline(Duration(System.nanoTime, NANOSECONDS)) - - /** - * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. - */ - implicit object DeadlineIsOrdered extends Ordering[Deadline] { - def compare(a: Deadline, b: Deadline) = a compare b - } -} - object Duration { - /** - * This implicit conversion allows the use of a Deadline in place of a Duration, which will - * insert the time left until the deadline in its place. - */ - implicit def timeLeft(implicit d: Deadline): Duration = d.timeLeft /** * Construct a Duration from the given length and unit. Observe that nanosecond precision may be lost if @@ -102,11 +24,13 @@ object Duration { * @throws IllegalArgumentException if the length was finite but the resulting duration cannot be expressed as a [[FiniteDuration]] */ def apply(length: Double, unit: TimeUnit): Duration = fromNanos(unit.toNanos(1) * length) + /** * Construct a finite duration from the given length and time unit. The unit given is retained * throughout calculations as long as possible, so that it can be retrieved later. */ def apply(length: Long, unit: TimeUnit): FiniteDuration = new FiniteDuration(length, unit) + /** * Construct a finite duration from the given length and time unit, where the latter is * looked up in a list of string representation. Valid choices are: @@ -117,7 +41,7 @@ object Duration { def apply(length: Long, unit: String): FiniteDuration = new FiniteDuration(length, Duration.timeUnit(unit)) // Double stores 52 bits mantissa, but there is an implied '1' in front, making the limit 2^53 - final val maxPreciseDouble = 9007199254740992d + private[this] final val maxPreciseDouble = 9007199254740992d /** * Parse String into Duration. Format is `"<length><unit>"`, where @@ -161,11 +85,11 @@ object Duration { ) // TimeUnit => standard label - protected[util] val timeUnitName: Map[TimeUnit, String] = + protected[duration] val timeUnitName: Map[TimeUnit, String] = timeUnitLabels.toMap mapValues (s => words(s).last) toMap // Label => TimeUnit - protected[util] val timeUnit: Map[String, TimeUnit] = + protected[duration] val timeUnit: Map[String, TimeUnit] = timeUnitLabels flatMap { case (unit, names) => expandLabels(names) map (_ -> unit) } toMap /** @@ -275,13 +199,13 @@ object Duration { if (factor == 0d || factor.isNaN) Undefined else if (factor < 0d) -this else this - def /(factor: Double): Duration = - if (factor.isNaN || factor.isInfinite) Undefined - else if ((factor compare 0d) < 0) -this + def /(divisor: Double): Duration = + if (divisor.isNaN || divisor.isInfinite) Undefined + else if ((divisor compare 0d) < 0) -this else this - def /(other: Duration): Double = other match { + def /(divisor: Duration): Double = divisor match { case _: Infinite => Double.NaN - case x => Double.PositiveInfinity * (if ((this > Zero) ^ (other >= Zero)) -1 else 1) + case x => Double.PositiveInfinity * (if ((this > Zero) ^ (divisor >= Zero)) -1 else 1) } final def isFinite() = false @@ -380,8 +304,7 @@ object Duration { * <p/> * Examples: * {{{ - * import scala.concurrent.util.Duration - * import java.util.concurrent.TimeUnit + * import scala.concurrent.duration._ * * val duration = Duration(100, MILLISECONDS) * val duration = Duration(100, "millis") @@ -396,7 +319,7 @@ object Duration { * <p/> * Implicits are also provided for Int, Long and Double. Example usage: * {{{ - * import scala.concurrent.util.Duration._ + * import scala.concurrent.duration._ * * val duration = 100 millis * }}} @@ -529,12 +452,12 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { * * $ovf */ - def /(factor: Double): Duration + def /(divisor: Double): Duration /** * Return the quotient of this and that duration as floating-point number. The semantics are * determined by Double as if calculating the quotient of the nanosecond lengths of both factors. */ - def /(other: Duration): Double + def /(divisor: Duration): Double /** * Negate this duration. The only two values which are mapped to themselves are [[Duration.Zero]] and [[Duration.Undefined]]. */ @@ -561,7 +484,7 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { * * $ovf */ - def div(factor: Double) = this / factor + def div(divisor: Double) = this / divisor /** * Return the quotient of this and that duration as floating-point number. The semantics are * determined by Double as if calculating the quotient of the nanosecond lengths of both factors. @@ -599,6 +522,7 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { } object FiniteDuration { + implicit object FiniteDurationIsOrdered extends Ordering[FiniteDuration] { def compare(a: FiniteDuration, b: FiniteDuration) = a compare b } @@ -691,29 +615,77 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio else if ((factor > 0) ^ (this < Zero)) Inf else MinusInf - def /(factor: Double) = - if (!factor.isInfinite) fromNanos(toNanos / factor) - else if (factor.isNaN) Undefined + def /(divisor: Double) = + if (!divisor.isInfinite) fromNanos(toNanos / divisor) + else if (divisor.isNaN) Undefined else Zero // if this is made a constant, then scalac will elide the conditional and always return +0.0, SI-6331 private[this] def minusZero = -0d - def /(other: Duration): Double = - if (other.isFinite) toNanos.toDouble / other.toNanos - else if (other eq Undefined) Double.NaN - else if ((length < 0) ^ (other > Zero)) 0d + def /(divisor: Duration): Double = + if (divisor.isFinite) toNanos.toDouble / divisor.toNanos + else if (divisor eq Undefined) Double.NaN + else if ((length < 0) ^ (divisor > Zero)) 0d else minusZero - // overridden methods taking FiniteDurations, so that you can calculate while statically staying finite + // overloaded methods taking FiniteDurations, so that you can calculate while statically staying finite def +(other: FiniteDuration) = add(other.length, other.unit) def -(other: FiniteDuration) = add(-other.length, other.unit) def plus(other: FiniteDuration) = this + other def minus(other: FiniteDuration) = this - other - override def div(factor: Double) = this / factor - override def mul(factor: Double) = this * factor def min(other: FiniteDuration) = if (this < other) this else other def max(other: FiniteDuration) = if (this > other) this else other + // overloaded methods taking Long so that you can calculate while statically staying finite + + /** + * Return the quotient of this duration and the given integer factor. + * + * @throws ArithmeticException if the factor is 0 + */ + def /(divisor: Long) = fromNanos(toNanos / divisor) + + /** + * Return the product of this duration and the given integer factor. + * + * @throws IllegalArgumentException if the result would overflow the range of FiniteDuration + */ + def *(factor: Long) = new FiniteDuration(safeMul(length, factor), unit) + + /* + * This method avoids the use of Long division, which saves 95% of the time spent, + * by checking that there are enough leading zeros so that the result has a chance + * to fit into a Long again; the remaining edge cases are caught by using the sign + * of the product for overflow detection. + * + * This method is not general purpose because it disallows the (otherwise legal) + * case of Long.MinValue * 1, but that is okay for use in FiniteDuration, since + * Long.MinValue is not a legal `length` anyway. + */ + private def safeMul(_a: Long, _b: Long): Long = { + val a = math.abs(_a) + val b = math.abs(_b) + import java.lang.Long.{ numberOfLeadingZeros => leading } + if (leading(a) + leading(b) < 64) throw new IllegalArgumentException("multiplication overflow") + val product = a * b + if (product < 0) throw new IllegalArgumentException("multiplication overflow") + if (a == _a ^ b == _b) -product else product + } + + /** + * Return the quotient of this duration and the given integer factor. + * + * @throws ArithmeticException if the factor is 0 + */ + def div(divisor: Long) = this / divisor + + /** + * Return the product of this duration and the given integer factor. + * + * @throws IllegalArgumentException if the result would overflow the range of FiniteDuration + */ + def mul(factor: Long) = this * factor + def unary_- = Duration(-length, unit) final def isFinite() = true @@ -724,78 +696,3 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio } override def hashCode = toNanos.toInt } - -trait DurationConversions extends Any { - import duration.Classifier - protected def durationIn(unit: TimeUnit): FiniteDuration - - def nanoseconds = durationIn(NANOSECONDS) - def nanos = nanoseconds - def nanosecond = nanoseconds - def nano = nanoseconds - - def microseconds = durationIn(MICROSECONDS) - def micros = microseconds - def microsecond = microseconds - def micro = microseconds - - def milliseconds = durationIn(MILLISECONDS) - def millis = milliseconds - def millisecond = milliseconds - def milli = milliseconds - - def seconds = durationIn(SECONDS) - def second = seconds - - def minutes = durationIn(MINUTES) - def minute = minutes - - def hours = durationIn(HOURS) - def hour = hours - - def days = durationIn(DAYS) - def day = days - - def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(nanoseconds) - def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = nanoseconds(c) - def nanosecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = nanoseconds(c) - def nano[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = nanoseconds(c) - - def microseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(microseconds) - def micros[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = microseconds(c) - def microsecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = microseconds(c) - def micro[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = microseconds(c) - - def milliseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(milliseconds) - def millis[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = milliseconds(c) - def millisecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = milliseconds(c) - def milli[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = milliseconds(c) - - def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(seconds) - def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = seconds(c) - - def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(minutes) - def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = minutes(c) - - def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(hours) - def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = hours(c) - - def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(days) - def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = days(c) -} - -final class DurationInt(val n: Int) extends AnyVal with DurationConversions { - override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) -} - -final class DurationLong(val n: Long) extends AnyVal with DurationConversions { - override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) -} - -final class DurationDouble(val d: Double) extends AnyVal with DurationConversions { - override protected def durationIn(unit: TimeUnit): FiniteDuration = - Duration(d, unit) match { - case f: FiniteDuration => f - case _ => throw new IllegalArgumentException("Duration DSL not applicable to " + d) - } -} diff --git a/src/library/scala/concurrent/duration/DurationConversions.scala b/src/library/scala/concurrent/duration/DurationConversions.scala new file mode 100644 index 0000000000..2c7e192a0e --- /dev/null +++ b/src/library/scala/concurrent/duration/DurationConversions.scala @@ -0,0 +1,92 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent.duration + +import DurationConversions._ + +// Would be nice to limit the visibility of this trait a little bit, +// but it crashes scalac to do so. +trait DurationConversions extends Any { + protected def durationIn(unit: TimeUnit): FiniteDuration + + def nanoseconds = durationIn(NANOSECONDS) + def nanos = nanoseconds + def nanosecond = nanoseconds + def nano = nanoseconds + + def microseconds = durationIn(MICROSECONDS) + def micros = microseconds + def microsecond = microseconds + def micro = microseconds + + def milliseconds = durationIn(MILLISECONDS) + def millis = milliseconds + def millisecond = milliseconds + def milli = milliseconds + + def seconds = durationIn(SECONDS) + def second = seconds + + def minutes = durationIn(MINUTES) + def minute = minutes + + def hours = durationIn(HOURS) + def hour = hours + + def days = durationIn(DAYS) + def day = days + + def nanoseconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(nanoseconds) + def nanos[C](c: C)(implicit ev: Classifier[C]): ev.R = nanoseconds(c) + def nanosecond[C](c: C)(implicit ev: Classifier[C]): ev.R = nanoseconds(c) + def nano[C](c: C)(implicit ev: Classifier[C]): ev.R = nanoseconds(c) + + def microseconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(microseconds) + def micros[C](c: C)(implicit ev: Classifier[C]): ev.R = microseconds(c) + def microsecond[C](c: C)(implicit ev: Classifier[C]): ev.R = microseconds(c) + def micro[C](c: C)(implicit ev: Classifier[C]): ev.R = microseconds(c) + + def milliseconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(milliseconds) + def millis[C](c: C)(implicit ev: Classifier[C]): ev.R = milliseconds(c) + def millisecond[C](c: C)(implicit ev: Classifier[C]): ev.R = milliseconds(c) + def milli[C](c: C)(implicit ev: Classifier[C]): ev.R = milliseconds(c) + + def seconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(seconds) + def second[C](c: C)(implicit ev: Classifier[C]): ev.R = seconds(c) + + def minutes[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(minutes) + def minute[C](c: C)(implicit ev: Classifier[C]): ev.R = minutes(c) + + def hours[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(hours) + def hour[C](c: C)(implicit ev: Classifier[C]): ev.R = hours(c) + + def days[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(days) + def day[C](c: C)(implicit ev: Classifier[C]): ev.R = days(c) +} + +/** + * This object just holds some cogs which make the DSL machine work, not for direct consumption. + */ +object DurationConversions { + trait Classifier[C] { + type R + def convert(d: FiniteDuration): R + } + + implicit object spanConvert extends Classifier[span.type] { + type R = FiniteDuration + def convert(d: FiniteDuration) = d + } + + implicit object fromNowConvert extends Classifier[fromNow.type] { + type R = Deadline + def convert(d: FiniteDuration) = Deadline.now + d + } + +} diff --git a/src/library/scala/concurrent/duration/package.scala b/src/library/scala/concurrent/duration/package.scala new file mode 100644 index 0000000000..2fd735f19e --- /dev/null +++ b/src/library/scala/concurrent/duration/package.scala @@ -0,0 +1,75 @@ +package scala.concurrent + +import scala.language.implicitConversions + +package object duration { + /** + * This object can be used as closing token if you prefer dot-less style but do not want + * to enable language.postfixOps: + * + * {{{ + * import scala.concurrent.duration._ + * + * val duration = 2 seconds span + * }}} + */ + object span + + /** + * This object can be used as closing token for declaring a deadline at some future point + * in time: + * + * {{{ + * import scala.concurrent.duration._ + * + * val deadline = 3 seconds fromNow + * }}} + */ + object fromNow + + type TimeUnit = java.util.concurrent.TimeUnit + final val DAYS = java.util.concurrent.TimeUnit.DAYS + final val HOURS = java.util.concurrent.TimeUnit.HOURS + final val MICROSECONDS = java.util.concurrent.TimeUnit.MICROSECONDS + final val MILLISECONDS = java.util.concurrent.TimeUnit.MILLISECONDS + final val MINUTES = java.util.concurrent.TimeUnit.MINUTES + final val NANOSECONDS = java.util.concurrent.TimeUnit.NANOSECONDS + final val SECONDS = java.util.concurrent.TimeUnit.SECONDS + + implicit def pairIntToDuration(p: (Int, TimeUnit)): Duration = Duration(p._1, p._2) + implicit def pairLongToDuration(p: (Long, TimeUnit)): FiniteDuration = Duration(p._1, p._2) + implicit def durationToPair(d: Duration): (Long, TimeUnit) = (d.length, d.unit) + + implicit final class DurationInt(val n: Int) extends AnyVal with DurationConversions { + override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) + } + + implicit final class DurationLong(val n: Long) extends AnyVal with DurationConversions { + override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) + } + + implicit final class DurationDouble(val d: Double) extends AnyVal with DurationConversions { + override protected def durationIn(unit: TimeUnit): FiniteDuration = + Duration(d, unit) match { + case f: FiniteDuration => f + case _ => throw new IllegalArgumentException("Duration DSL not applicable to " + d) + } + } + + /* + * Avoid reflection based invocation by using non-duck type + */ + implicit final class IntMult(val i: Int) extends AnyVal { + def *(d: Duration) = d * i + def *(d: FiniteDuration) = d * i + } + + implicit final class LongMult(val i: Long) extends AnyVal { + def *(d: Duration) = d * i + def *(d: FiniteDuration) = d * i + } + + implicit final class DoubleMult(val f: Double) extends AnyVal { + def *(d: Duration) = d * f + } +} diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index 9228872f2b..a1a3305db0 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -8,16 +8,12 @@ package scala.concurrent.impl - - -import java.util.concurrent.TimeUnit.NANOSECONDS import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException } -import scala.concurrent.util.{ Duration, Deadline, FiniteDuration } +import scala.concurrent.duration.{ Duration, Deadline, FiniteDuration, NANOSECONDS } import scala.annotation.tailrec import scala.util.control.NonFatal import scala.util.{ Try, Success, Failure } - private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] { def future: this.type = this } @@ -48,7 +44,7 @@ private[concurrent] object Promise { case Failure(t) => resolver(t) case _ => source } - + private def resolver[T](throwable: Throwable): Try[T] = throwable match { case t: scala.runtime.NonLocalReturnControl[_] => Success(t.value.asInstanceOf[T]) case t: scala.util.control.ControlThrowable => Failure(new ExecutionException("Boxed ControlThrowable", t)) @@ -56,12 +52,12 @@ private[concurrent] object Promise { case e: Error => Failure(new ExecutionException("Boxed Error", e)) case t => Failure(t) } - + /** Default promise implementation. */ class DefaultPromise[T] extends AbstractPromise with Promise[T] { self => updateState(null, Nil) // Start at "No callbacks" - + protected final def tryAwait(atMost: Duration): Boolean = { @tailrec def awaitUnsafe(deadline: Deadline, nextWait: FiniteDuration): Boolean = { diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index 1d06341d4d..e683732e41 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -8,7 +8,7 @@ package scala -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import scala.annotation.implicitNotFound /** This package object contains primitives for concurrent and parallel programming. diff --git a/src/library/scala/concurrent/util/duration/Classifier.scala b/src/library/scala/concurrent/util/duration/Classifier.scala deleted file mode 100644 index 10faf0a5ce..0000000000 --- a/src/library/scala/concurrent/util/duration/Classifier.scala +++ /dev/null @@ -1,9 +0,0 @@ -package scala.concurrent.util.duration - -import scala.concurrent.util.{ FiniteDuration } - -trait Classifier[C] { - type R - def convert(d: FiniteDuration): R -} - diff --git a/src/library/scala/concurrent/util/duration/IntMult.scala b/src/library/scala/concurrent/util/duration/IntMult.scala deleted file mode 100644 index 94c58fb8c2..0000000000 --- a/src/library/scala/concurrent/util/duration/IntMult.scala +++ /dev/null @@ -1,18 +0,0 @@ -package scala.concurrent.util.duration - -import scala.concurrent.util.{ Duration } - -/* - * Avoid reflection based invocation by using non-duck type - */ -protected[duration] class IntMult(i: Int) { - def *(d: Duration) = d * i -} - -protected[duration] class LongMult(i: Long) { - def *(d: Duration) = d * i -} - -protected[duration] class DoubleMult(f: Double) { - def *(d: Duration) = d * f -} diff --git a/src/library/scala/concurrent/util/duration/package.scala b/src/library/scala/concurrent/util/duration/package.scala deleted file mode 100644 index d5ae3f1544..0000000000 --- a/src/library/scala/concurrent/util/duration/package.scala +++ /dev/null @@ -1,31 +0,0 @@ -package scala.concurrent.util - -import java.util.concurrent.TimeUnit -import scala.language.implicitConversions - -package object duration { - - object span - implicit object spanConvert extends Classifier[span.type] { - type R = FiniteDuration - def convert(d: FiniteDuration) = d - } - - object fromNow - implicit object fromNowConvert extends Classifier[fromNow.type] { - type R = Deadline - def convert(d: FiniteDuration) = Deadline.now + d - } - - implicit def intToDurationInt(n: Int) = new DurationInt(n) - implicit def longToDurationLong(n: Long) = new DurationLong(n) - implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d) - - implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2) - implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2) - implicit def durationToPair(d: Duration) = (d.length, d.unit) - - implicit def intMult(i: Int) = new IntMult(i) - implicit def longMult(l: Long) = new LongMult(l) - implicit def doubleMult(f: Double) = new DoubleMult(f) -} diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 8a595473cc..5c2067a548 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -5,19 +5,19 @@ import java.lang.{ Class => jClass } import scala.language.{implicitConversions, existentials} import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass } -/** A `ClassTag[T]` wraps a runtime class, which can be accessed via the `runtimeClass` method. +/** A `ClassTag[T]` wraps a runtime class (the erasure) and can create array instances. * - * This is useful in itself, but also enables very important use case. - * Having this knowledge ClassTag can instantiate `Arrays` - * in those cases where the element type is unknown at compile time. + * If an implicit value of type ClassTag[T] is requested, the compiler will create one. + * The runtime class (i.e. the erasure, a java.lang.Class on the JVM) of T can be accessed + * via the `runtimeClass` field. References to type parameters or abstract type members are + * replaced by the concrete types if ClassTags are available for them. * - * If an implicit value of type u.ClassTag[T] is required, the compiler will make one up on demand. - * The implicitly created value contains in its `runtimeClass` field the runtime class that is the result of erasing type T. - * In that value, any occurrences of type parameters or abstract types U which come themselves with a ClassTag - * are represented by the type referenced by that tag. - * If the type T contains unresolved references to type parameters or abstract types, a static error results. + * Besides accessing the erasure, a ClassTag knows how to instantiate single- and multi- + * dimensional `Arrays` where the element type is unknown at compile time. * - * @see [[scala.reflect.base.TypeTags]] + * [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]]. + * + * @see [[scala.reflect.api.TypeTags]] */ @scala.annotation.implicitNotFound(msg = "No ClassTag available for ${T}") trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serializable { @@ -76,7 +76,7 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial if (conforms) Some(x.asInstanceOf[T]) else None } - /** case class accessories */ + // case class accessories override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]] override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass override def hashCode = scala.runtime.ScalaRunTime.hash(runtimeClass) @@ -88,6 +88,9 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial } } +/** + * Class tags corresponding to primitive types and constructor/extractor for ClassTags. + */ object ClassTag { private val ObjectTYPE = classOf[java.lang.Object] private val NothingTYPE = classOf[scala.runtime.Nothing$] diff --git a/src/library/scala/reflect/base/Annotations.scala b/src/library/scala/reflect/base/Annotations.scala deleted file mode 100644 index e3453b1cdf..0000000000 --- a/src/library/scala/reflect/base/Annotations.scala +++ /dev/null @@ -1,46 +0,0 @@ -package scala.reflect -package base - -import scala.collection.immutable.ListMap - -trait Annotations { self: Universe => - - type Annotation >: Null <: AnyRef - implicit val AnnotationTag: ClassTag[Annotation] - val Annotation: AnnotationExtractor - - abstract class AnnotationExtractor { - def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation - def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])] - } - - type JavaArgument >: Null <: AnyRef - implicit val JavaArgumentTag: ClassTag[JavaArgument] - - type LiteralArgument >: Null <: AnyRef with JavaArgument - implicit val LiteralArgumentTag: ClassTag[LiteralArgument] - val LiteralArgument: LiteralArgumentExtractor - - abstract class LiteralArgumentExtractor { - def apply(value: Constant): LiteralArgument - def unapply(arg: LiteralArgument): Option[Constant] - } - - type ArrayArgument >: Null <: AnyRef with JavaArgument - implicit val ArrayArgumentTag: ClassTag[ArrayArgument] - val ArrayArgument: ArrayArgumentExtractor - - abstract class ArrayArgumentExtractor { - def apply(args: Array[JavaArgument]): ArrayArgument - def unapply(arg: ArrayArgument): Option[Array[JavaArgument]] - } - - type NestedArgument >: Null <: AnyRef with JavaArgument - implicit val NestedArgumentTag: ClassTag[NestedArgument] - val NestedArgument: NestedArgumentExtractor - - abstract class NestedArgumentExtractor { - def apply(annotation: Annotation): NestedArgument - def unapply(arg: NestedArgument): Option[Annotation] - } -}
\ No newline at end of file diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala deleted file mode 100644 index 29bf2df656..0000000000 --- a/src/library/scala/reflect/base/Base.scala +++ /dev/null @@ -1,769 +0,0 @@ -package scala.reflect -package base - -import java.io.PrintWriter -import scala.annotation.switch -import scala.ref.WeakReference -import scala.collection.mutable -import scala.collection.immutable.ListMap - -class Base extends Universe { self => - - private var nextId = 0 - - abstract class Symbol(val name: Name, val flags: FlagSet) extends SymbolBase { - val id = { nextId += 1; nextId } - def owner: Symbol - def fullName: String = - if (isEffectiveRoot || owner.isEffectiveRoot) name.toString else owner.fullName + "." + name - private def isEffectiveRoot = - this == NoSymbol || this == rootMirror.RootClass || this == rootMirror.EmptyPackageClass - - def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol = - new TermSymbol(this, name, flags) - - def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol) = { - val c = new ModuleClassSymbol(this, name.toTypeName, flags) - val m = new ModuleSymbol(this, name.toTermName, flags, c) - (m, c) - } - - def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol - = new MethodSymbol(this, name, flags) - - def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol = - new TypeSymbol(this, name, flags) - - def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol = - new ClassSymbol(this, name, flags) - - def newFreeTermSymbol(name: TermName, value: => Any, flags: FlagSet = NoFlags, origin: String = null) = - new FreeTermSymbol(this, name, flags) - - def newFreeTypeSymbol(name: TypeName, flags: FlagSet = NoFlags, origin: String = null) = - new FreeTypeSymbol(this, name, flags) - - private def kindString: String = - if (isModule) "module" - else if (isClass) "class" - else if (isFreeType) "free type" - else if (isType) "type" - else if (isMethod) "method" - else if (isFreeTerm) "free term" - else if (isTerm) "value" - else "symbol" - override def toString() = s"$kindString $name" - } - implicit val SymbolTag = ClassTag[Symbol](classOf[Symbol]) - - class TermSymbol(val owner: Symbol, override val name: TermName, flags: FlagSet) - extends Symbol(name, flags) with TermSymbolBase - implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol]) - - class TypeSymbol(val owner: Symbol, override val name: TypeName, flags: FlagSet) - extends Symbol(name, flags) with TypeSymbolBase { - override def toTypeConstructor = TypeRef(ThisType(owner), this, Nil) - override def toType = TypeRef(ThisType(owner), this, Nil) - override def toTypeIn(site: Type) = TypeRef(ThisType(owner), this, Nil) - } - implicit val TypeSymbolTag = ClassTag[TypeSymbol](classOf[TypeSymbol]) - - class MethodSymbol(owner: Symbol, name: TermName, flags: FlagSet) - extends TermSymbol(owner, name, flags) with MethodSymbolBase - implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol]) - - class ModuleSymbol(owner: Symbol, name: TermName, flags: FlagSet, override val moduleClass: Symbol) - extends TermSymbol(owner, name, flags) with ModuleSymbolBase - implicit val ModuleSymbolTag = ClassTag[ModuleSymbol](classOf[ModuleSymbol]) - - class ClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet) - extends TypeSymbol(owner, name, flags) with ClassSymbolBase - class ModuleClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet) - extends ClassSymbol(owner, name, flags) { override def isModuleClass = true } - implicit val ClassSymbolTag = ClassTag[ClassSymbol](classOf[ClassSymbol]) - - class FreeTermSymbol(owner: Symbol, name: TermName, flags: FlagSet) - extends TermSymbol(owner, name, flags) with FreeTermSymbolBase - implicit val FreeTermSymbolTag = ClassTag[FreeTermSymbol](classOf[FreeTermSymbol]) - - class FreeTypeSymbol(owner: Symbol, name: TypeName, flags: FlagSet) - extends TypeSymbol(owner, name, flags) with FreeTypeSymbolBase - implicit val FreeTypeSymbolTag = ClassTag[FreeTypeSymbol](classOf[FreeTypeSymbol]) - - - object NoSymbol extends Symbol(nme.NO_NAME, NoFlags) { - override def owner = throw new UnsupportedOperationException("NoSymbol.owner") - } - - // todo. write a decent toString that doesn't crash on recursive types - class Type extends TypeBase { - def termSymbol: Symbol = NoSymbol - def typeSymbol: Symbol = NoSymbol - } - implicit val TypeTagg = ClassTag[Type](classOf[Type]) - - val NoType = new Type { override def toString = "NoType" } - val NoPrefix = new Type { override def toString = "NoPrefix" } - - class SingletonType extends Type - implicit val SingletonTypeTag = ClassTag[SingletonType](classOf[SingletonType]) - - case class ThisType(sym: Symbol) extends SingletonType { override val typeSymbol = sym } - object ThisType extends ThisTypeExtractor - implicit val ThisTypeTag = ClassTag[ThisType](classOf[ThisType]) - - case class SingleType(pre: Type, sym: Symbol) extends SingletonType { override val termSymbol = sym } - object SingleType extends SingleTypeExtractor - implicit val SingleTypeTag = ClassTag[SingleType](classOf[SingleType]) - - case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType - object SuperType extends SuperTypeExtractor - implicit val SuperTypeTag = ClassTag[SuperType](classOf[SuperType]) - - case class ConstantType(value: Constant) extends SingletonType - object ConstantType extends ConstantTypeExtractor - implicit val ConstantTypeTag = ClassTag[ConstantType](classOf[ConstantType]) - - case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type { override val typeSymbol = sym } - object TypeRef extends TypeRefExtractor - implicit val TypeRefTag = ClassTag[TypeRef](classOf[TypeRef]) - - abstract class CompoundType extends Type - implicit val CompoundTypeTag = ClassTag[CompoundType](classOf[CompoundType]) - - case class RefinedType(parents: List[Type], decls: Scope) extends CompoundType - object RefinedType extends RefinedTypeExtractor { - def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType = - RefinedType(parents, decls) - } - implicit val RefinedTypeTag = ClassTag[RefinedType](classOf[RefinedType]) - - case class ClassInfoType(parents: List[Type], decls: Scope, override val typeSymbol: Symbol) extends CompoundType - object ClassInfoType extends ClassInfoTypeExtractor - implicit val ClassInfoTypeTag = ClassTag[ClassInfoType](classOf[ClassInfoType]) - - case class MethodType(params: List[Symbol], resultType: Type) extends Type - object MethodType extends MethodTypeExtractor - implicit val MethodTypeTag = ClassTag[MethodType](classOf[MethodType]) - - case class NullaryMethodType(resultType: Type) extends Type - object NullaryMethodType extends NullaryMethodTypeExtractor - implicit val NullaryMethodTypeTag = ClassTag[NullaryMethodType](classOf[NullaryMethodType]) - - case class PolyType(typeParams: List[Symbol], resultType: Type) extends Type - object PolyType extends PolyTypeExtractor - implicit val PolyTypeTag = ClassTag[PolyType](classOf[PolyType]) - - case class ExistentialType(quantified: List[Symbol], underlying: Type) extends Type { override def typeSymbol = underlying.typeSymbol } - object ExistentialType extends ExistentialTypeExtractor - implicit val ExistentialTypeTag = ClassTag[ExistentialType](classOf[ExistentialType]) - - case class AnnotatedType(annotations: List[Annotation], underlying: Type, selfsym: Symbol) extends Type { override def typeSymbol = underlying.typeSymbol } - object AnnotatedType extends AnnotatedTypeExtractor - implicit val AnnotatedTypeTag = ClassTag[AnnotatedType](classOf[AnnotatedType]) - - case class TypeBounds(lo: Type, hi: Type) extends Type - object TypeBounds extends TypeBoundsExtractor - implicit val TypeBoundsTag = ClassTag[TypeBounds](classOf[TypeBounds]) - - val WildcardType = new Type - - case class BoundedWildcardType(bounds: TypeBounds) extends Type - object BoundedWildcardType extends BoundedWildcardTypeExtractor - implicit val BoundedWildcardTypeTag = ClassTag[BoundedWildcardType](classOf[BoundedWildcardType]) - - class Scope(elems: Iterable[Symbol]) extends ScopeBase with MemberScopeBase { - def iterator = elems.iterator - def sorted = elems.toList - } - type MemberScope = Scope - implicit val ScopeTag = ClassTag[Scope](classOf[Scope]) - implicit val MemberScopeTag = ClassTag[MemberScope](classOf[MemberScope]) - - def newScope: Scope = newScopeWith() - def newNestedScope(outer: Scope): Scope = newScope - def newScopeWith(elems: Symbol*): Scope = new Scope(elems) - - abstract class Name(str: String) extends NameBase { - override def toString = str - } - implicit val NameTag = ClassTag[Name](classOf[Name]) - - class TermName(str: String) extends Name(str) { - def isTermName = true - def isTypeName = false - def toTermName = this - def toTypeName = new TypeName(str) - } - implicit val TermNameTag = ClassTag[TermName](classOf[TermName]) - - class TypeName(str: String) extends Name(str) { - def isTermName = false - def isTypeName = true - def toTermName = new TermName(str) - def toTypeName = this - } - implicit val TypeNameTag = ClassTag[TypeName](classOf[TypeName]) - - def newTermName(str: String) = new TermName(str) - def newTypeName(str: String) = new TypeName(str) - - object nme extends TermNamesBase { - type NameType = TermName - val WILDCARD = newTermName("_") - val CONSTRUCTOR = newTermName("<init>") - val ROOTPKG = newTermName("_root_") - val EMPTY = newTermName("") - val EMPTY_PACKAGE_NAME = newTermName("<empty>") - val ROOT = newTermName("<root>") - val NO_NAME = newTermName("<none>") - } - - object tpnme extends TypeNamesBase { - type NameType = TypeName - val WILDCARD = nme.WILDCARD.toTypeName - val EMPTY = nme.EMPTY.toTypeName - val WILDCARD_STAR = newTypeName("_*") - val EMPTY_PACKAGE_NAME = nme.EMPTY_PACKAGE_NAME.toTypeName - val ROOT = nme.ROOT.toTypeName - } - - type FlagSet = Long - val NoFlags = 0L - implicit val FlagSetTag = ClassTag[FlagSet](classOf[FlagSet]) - - class Modifiers(override val flags: FlagSet, - override val privateWithin: Name, - override val annotations: List[Tree]) extends ModifiersBase { - def hasFlag(flags: FlagSet) = (this.flags & flags) != 0 - } - - implicit val ModifiersTag = ClassTag[Modifiers](classOf[Modifiers]) - - object Modifiers extends ModifiersCreator { - def apply(flags: Long, - privateWithin: Name, - annotations: List[Tree]) = new Modifiers(flags, privateWithin, annotations) - } - - case class Constant(value: Any) - object Constant extends ConstantExtractor - implicit val ConstantTag = ClassTag[Constant](classOf[Constant]) - - case class Annotation(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]) - object Annotation extends AnnotationExtractor - implicit val AnnotationTag = ClassTag[Annotation](classOf[Annotation]) - - abstract class JavaArgument - implicit val JavaArgumentTag = ClassTag[JavaArgument](classOf[JavaArgument]) - - case class LiteralArgument(value: Constant) extends JavaArgument - object LiteralArgument extends LiteralArgumentExtractor - implicit val LiteralArgumentTag = ClassTag[LiteralArgument](classOf[LiteralArgument]) - - case class ArrayArgument(args: Array[JavaArgument]) extends JavaArgument - object ArrayArgument extends ArrayArgumentExtractor - implicit val ArrayArgumentTag = ClassTag[ArrayArgument](classOf[ArrayArgument]) - - case class NestedArgument(annotation: Annotation) extends JavaArgument - object NestedArgument extends NestedArgumentExtractor - implicit val NestedArgumentTag = ClassTag[NestedArgument](classOf[NestedArgument]) - - class Position extends Attachments { - override type Pos = Position - def pos = this - def withPos(newPos: Position) = newPos - def isRange = false - def focus = this - } - implicit val PositionTag = ClassTag[Position](classOf[Position]) - - val NoPosition = new Position - - private val generated = new mutable.HashMap[String, WeakReference[Symbol]] - - private def cached(name: String)(symExpr: => Symbol): Symbol = - generated get name match { - case Some(WeakReference(sym)) => - sym - case _ => - val sym = symExpr - generated(name) = WeakReference(sym) - sym - } - - object build extends BuildBase { - def selectType(owner: Symbol, name: String): TypeSymbol = { - val clazz = new ClassSymbol(owner, newTypeName(name), NoFlags) - cached(clazz.fullName)(clazz).asType - } - - def selectTerm(owner: Symbol, name: String): TermSymbol = { - val valu = new MethodSymbol(owner, newTermName(name), NoFlags) - cached(valu.fullName)(valu).asTerm - } - - def selectOverloadedMethod(owner: Symbol, name: String, index: Int): MethodSymbol = - selectTerm(owner, name).asMethod - - def newNestedSymbol(owner: Symbol, name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol = - if (name.isTypeName) - if (isClass) new ClassSymbol(owner, name.toTypeName, flags) - else new TypeSymbol(owner, name.toTypeName, flags) - else new TermSymbol(owner, name.toTermName, flags) - - def newFreeTerm(name: String, value: => Any, flags: Long = 0L, origin: String = null): FreeTermSymbol = - new FreeTermSymbol(rootMirror.RootClass, newTermName(name), flags) - - def newFreeType(name: String, flags: Long = 0L, origin: String = null): FreeTypeSymbol = - new FreeTypeSymbol(rootMirror.RootClass, newTypeName(name), flags) - - def setTypeSignature[S <: Symbol](sym: S, tpe: Type): S = sym - - def setAnnotations[S <: Symbol](sym: S, annots: List[Annotation]): S = sym - - def flagsFromBits(bits: Long): FlagSet = bits - - object emptyValDef extends ValDef(NoMods, nme.WILDCARD, TypeTree(NoType), EmptyTree) { - override def isEmpty = true - } - - def This(sym: Symbol): Tree = self.This(sym.name.toTypeName) - - def Select(qualifier: Tree, sym: Symbol): Select = self.Select(qualifier, sym.name) - - def Ident(sym: Symbol): Ident = self.Ident(sym.name) - - def TypeTree(tp: Type): TypeTree = self.TypeTree() - - def thisPrefix(sym: Symbol): Type = SingleType(NoPrefix, sym) - - def setType[T <: Tree](tree: T, tpe: Type): T = tree - - def setSymbol[T <: Tree](tree: T, sym: Symbol): T = tree - } - - import build._ - - class Mirror extends MirrorOf[self.type] { - val universe: self.type = self - - lazy val RootClass = new ClassSymbol(NoSymbol, tpnme.ROOT, NoFlags) { override def isModuleClass = true } - lazy val RootPackage = new ModuleSymbol(NoSymbol, nme.ROOT, NoFlags, RootClass) - lazy val EmptyPackageClass = new ClassSymbol(RootClass, tpnme.EMPTY_PACKAGE_NAME, NoFlags) { override def isModuleClass = true } - lazy val EmptyPackage = new ModuleSymbol(RootClass, nme.EMPTY_PACKAGE_NAME, NoFlags, EmptyPackageClass) - - def staticClass(fullName: String): ClassSymbol = - mkStatic[ClassSymbol](fullName) - - def staticModule(fullName: String): ModuleSymbol = - mkStatic[ModuleSymbol](fullName) - - def staticPackage(fullName: String): ModuleSymbol = - staticModule(fullName) // this toy universe doesn't care about the distinction between packages and modules - - private def mkStatic[S <: Symbol : ClassTag](fullName: String): S = - cached(fullName) { - val point = fullName lastIndexOf '.' - val owner = - if (point > 0) staticModule(fullName take point).moduleClass - else rootMirror.RootClass - val name = fullName drop point + 1 - val symtag = implicitly[ClassTag[S]] - if (symtag == ClassSymbolTag) new ClassSymbol(owner, newTypeName(name), NoFlags) - else owner.newModuleAndClassSymbol(newTermName(name))._1 - }.asInstanceOf[S] - } - - lazy val rootMirror = new Mirror - - import rootMirror._ - - object definitions extends DefinitionsBase { - lazy val ScalaPackage = staticModule("scala") - lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClass - - lazy val AnyClass = staticClass("scala.Any") - lazy val AnyValClass = staticClass("scala.Any") - lazy val ObjectClass = staticClass("java.lang.Object") - lazy val AnyRefClass = ObjectClass - - lazy val NullClass = staticClass("scala.Null") - lazy val NothingClass = staticClass("scala.Nothing") - - lazy val UnitClass = staticClass("scala.Unit") - lazy val ByteClass = staticClass("scala.Byte") - lazy val ShortClass = staticClass("scala.Short") - lazy val CharClass = staticClass("scala.Char") - lazy val IntClass = staticClass("scala.Int") - lazy val LongClass = staticClass("scala.Long") - lazy val FloatClass = staticClass("scala.Float") - lazy val DoubleClass = staticClass("scala.Double") - lazy val BooleanClass = staticClass("scala.Boolean") - - lazy val StringClass = staticClass("java.lang.String") - lazy val ClassClass = staticClass("java.lang.Class") - lazy val ArrayClass = staticClass("scala.Array") - lazy val ListClass = staticClass("scala.List") - - lazy val PredefModule = staticModule("scala.Predef") - - lazy val ByteTpe = TypeRef(ScalaPrefix, ByteClass, Nil) - lazy val ShortTpe = TypeRef(ScalaPrefix, ShortClass, Nil) - lazy val CharTpe = TypeRef(ScalaPrefix, CharClass, Nil) - lazy val IntTpe = TypeRef(ScalaPrefix, IntClass, Nil) - lazy val LongTpe = TypeRef(ScalaPrefix, LongClass, Nil) - lazy val FloatTpe = TypeRef(ScalaPrefix, FloatClass, Nil) - lazy val DoubleTpe = TypeRef(ScalaPrefix, DoubleClass, Nil) - lazy val BooleanTpe = TypeRef(ScalaPrefix, BooleanClass, Nil) - lazy val UnitTpe = TypeRef(ScalaPrefix, UnitClass, Nil) - lazy val AnyTpe = TypeRef(ScalaPrefix, AnyClass, Nil) - lazy val AnyValTpe = TypeRef(ScalaPrefix, AnyValClass, Nil) - lazy val NothingTpe = TypeRef(ScalaPrefix, NothingClass, Nil) - lazy val NullTpe = TypeRef(ScalaPrefix, NullClass, Nil) - lazy val ObjectTpe = TypeRef(JavaLangPrefix, ObjectClass, Nil) - lazy val AnyRefTpe = ObjectTpe - } - - import definitions._ - - private def thisModuleType(fullName: String): Type = ThisType(staticModule(fullName).moduleClass) - private lazy val ScalaPrefix = thisModuleType("scala") - private lazy val JavaLangPrefix = thisModuleType("java.lang") - - private var nodeCount = 0 // not synchronized - - abstract class Tree extends TreeBase with Product { - def isDef: Boolean = false - def isEmpty: Boolean = false - - /** The canonical way to test if a Tree represents a term. - */ - def isTerm: Boolean = this match { - case _: TermTree => true - case Bind(name, _) => name.isTermName - case Select(_, name) => name.isTermName - case Ident(name) => name.isTermName - case Annotated(_, arg) => arg.isTerm - case _ => false - } - - /** The canonical way to test if a Tree represents a type. - */ - def isType: Boolean = this match { - case _: TypTree => true - case Bind(name, _) => name.isTypeName - case Select(_, name) => name.isTypeName - case Ident(name) => name.isTypeName - case Annotated(_, arg) => arg.isType - case _ => false - } - } - - def treeToString(tree: Tree) = s"<tree ${tree.getClass}>" - - def treeType(tree: Tree) = NoType - - trait TermTree extends Tree - - trait TypTree extends Tree - - trait SymTree extends Tree - - trait NameTree extends Tree { - def name: Name - } - - trait RefTree extends SymTree with NameTree { - def qualifier: Tree // empty for Idents - def name: Name - } - - abstract class DefTree extends SymTree with NameTree { - def name: Name - override def isDef = true - } - - case object EmptyTree extends TermTree { - val asList = List(this) - override def isEmpty = true - } - - abstract class MemberDef extends DefTree { - def mods: Modifiers - } - - case class PackageDef(pid: RefTree, stats: List[Tree]) - extends MemberDef { - def name = pid.name - def mods = NoMods - } - object PackageDef extends PackageDefExtractor - - abstract class ImplDef extends MemberDef { - def impl: Template - } - - case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template) - extends ImplDef - object ClassDef extends ClassDefExtractor - - case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) - extends ImplDef - object ModuleDef extends ModuleDefExtractor - - abstract class ValOrDefDef extends MemberDef { - val name: Name - val tpt: Tree - val rhs: Tree - } - - case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef - object ValDef extends ValDefExtractor - - case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef], - vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef - object DefDef extends DefDefExtractor - - case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) - extends MemberDef - object TypeDef extends TypeDefExtractor - - case class LabelDef(name: TermName, params: List[Ident], rhs: Tree) - extends DefTree with TermTree - object LabelDef extends LabelDefExtractor - - case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) - object ImportSelector extends ImportSelectorExtractor - - case class Import(expr: Tree, selectors: List[ImportSelector]) - extends SymTree - object Import extends ImportExtractor - - case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) - extends SymTree - object Template extends TemplateExtractor - - case class Block(stats: List[Tree], expr: Tree) - extends TermTree - object Block extends BlockExtractor - - case class CaseDef(pat: Tree, guard: Tree, body: Tree) - extends Tree - object CaseDef extends CaseDefExtractor - - case class Alternative(trees: List[Tree]) - extends TermTree - object Alternative extends AlternativeExtractor - - case class Star(elem: Tree) - extends TermTree - object Star extends StarExtractor - - case class Bind(name: Name, body: Tree) - extends DefTree - object Bind extends BindExtractor - - case class UnApply(fun: Tree, args: List[Tree]) - extends TermTree - object UnApply extends UnApplyExtractor - - case class ArrayValue(elemtpt: Tree, elems: List[Tree]) - extends TermTree - object ArrayValue extends ArrayValueExtractor - - case class Function(vparams: List[ValDef], body: Tree) - extends TermTree with SymTree - object Function extends FunctionExtractor - - case class Assign(lhs: Tree, rhs: Tree) - extends TermTree - object Assign extends AssignExtractor - - case class AssignOrNamedArg(lhs: Tree, rhs: Tree) - extends TermTree - object AssignOrNamedArg extends AssignOrNamedArgExtractor - - case class If(cond: Tree, thenp: Tree, elsep: Tree) - extends TermTree - object If extends IfExtractor - - case class Match(selector: Tree, cases: List[CaseDef]) - extends TermTree - object Match extends MatchExtractor - - case class Return(expr: Tree) - extends TermTree with SymTree - object Return extends ReturnExtractor - - case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) - extends TermTree - object Try extends TryExtractor - - case class Throw(expr: Tree) - extends TermTree - object Throw extends ThrowExtractor - - case class New(tpt: Tree) extends TermTree - object New extends NewExtractor - - case class Typed(expr: Tree, tpt: Tree) - extends TermTree - object Typed extends TypedExtractor - - abstract class GenericApply extends TermTree { - val fun: Tree - val args: List[Tree] - } - - case class TypeApply(fun: Tree, args: List[Tree]) - extends GenericApply - object TypeApply extends TypeApplyExtractor - - case class Apply(fun: Tree, args: List[Tree]) - extends GenericApply - object Apply extends ApplyExtractor - - case class Super(qual: Tree, mix: TypeName) extends TermTree - object Super extends SuperExtractor - - case class This(qual: TypeName) - extends TermTree with SymTree - object This extends ThisExtractor - - case class Select(qualifier: Tree, name: Name) - extends RefTree - object Select extends SelectExtractor - - case class Ident(name: Name) extends RefTree { - def qualifier: Tree = EmptyTree - } - object Ident extends IdentExtractor - - case class ReferenceToBoxed(ident: Ident) extends TermTree - object ReferenceToBoxed extends ReferenceToBoxedExtractor - - case class Literal(value: Constant) - extends TermTree { - assert(value ne null) - } - object Literal extends LiteralExtractor - - case class Annotated(annot: Tree, arg: Tree) extends Tree - object Annotated extends AnnotatedExtractor - - case class SingletonTypeTree(ref: Tree) - extends TypTree - object SingletonTypeTree extends SingletonTypeTreeExtractor - - case class SelectFromTypeTree(qualifier: Tree, name: TypeName) - extends TypTree with RefTree - object SelectFromTypeTree extends SelectFromTypeTreeExtractor - - case class CompoundTypeTree(templ: Template) - extends TypTree - object CompoundTypeTree extends CompoundTypeTreeExtractor - - case class AppliedTypeTree(tpt: Tree, args: List[Tree]) - extends TypTree - object AppliedTypeTree extends AppliedTypeTreeExtractor - - case class TypeBoundsTree(lo: Tree, hi: Tree) - extends TypTree - object TypeBoundsTree extends TypeBoundsTreeExtractor - - case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) - extends TypTree - object ExistentialTypeTree extends ExistentialTypeTreeExtractor - - case class TypeTree() extends TypTree { - val original: Tree = null - override def isEmpty = true - } - object TypeTree extends TypeTreeExtractor - - implicit val TreeTag = ClassTag[Tree](classOf[Tree]) - implicit val TermTreeTag = ClassTag[TermTree](classOf[TermTree]) - implicit val TypTreeTag = ClassTag[TypTree](classOf[TypTree]) - implicit val SymTreeTag = ClassTag[SymTree](classOf[SymTree]) - implicit val NameTreeTag = ClassTag[NameTree](classOf[NameTree]) - implicit val RefTreeTag = ClassTag[RefTree](classOf[RefTree]) - implicit val DefTreeTag = ClassTag[DefTree](classOf[DefTree]) - implicit val MemberDefTag = ClassTag[MemberDef](classOf[MemberDef]) - implicit val PackageDefTag = ClassTag[PackageDef](classOf[PackageDef]) - implicit val ImplDefTag = ClassTag[ImplDef](classOf[ImplDef]) - implicit val ClassDefTag = ClassTag[ClassDef](classOf[ClassDef]) - implicit val ModuleDefTag = ClassTag[ModuleDef](classOf[ModuleDef]) - implicit val ValOrDefDefTag = ClassTag[ValOrDefDef](classOf[ValOrDefDef]) - implicit val ValDefTag = ClassTag[ValDef](classOf[ValDef]) - implicit val DefDefTag = ClassTag[DefDef](classOf[DefDef]) - implicit val TypeDefTag = ClassTag[TypeDef](classOf[TypeDef]) - implicit val LabelDefTag = ClassTag[LabelDef](classOf[LabelDef]) - implicit val ImportSelectorTag = ClassTag[ImportSelector](classOf[ImportSelector]) - implicit val ImportTag = ClassTag[Import](classOf[Import]) - implicit val TemplateTag = ClassTag[Template](classOf[Template]) - implicit val BlockTag = ClassTag[Block](classOf[Block]) - implicit val CaseDefTag = ClassTag[CaseDef](classOf[CaseDef]) - implicit val AlternativeTag = ClassTag[Alternative](classOf[Alternative]) - implicit val StarTag = ClassTag[Star](classOf[Star]) - implicit val BindTag = ClassTag[Bind](classOf[Bind]) - implicit val UnApplyTag = ClassTag[UnApply](classOf[UnApply]) - implicit val ArrayValueTag = ClassTag[ArrayValue](classOf[ArrayValue]) - implicit val FunctionTag = ClassTag[Function](classOf[Function]) - implicit val AssignTag = ClassTag[Assign](classOf[Assign]) - implicit val AssignOrNamedArgTag = ClassTag[AssignOrNamedArg](classOf[AssignOrNamedArg]) - implicit val IfTag = ClassTag[If](classOf[If]) - implicit val MatchTag = ClassTag[Match](classOf[Match]) - implicit val ReturnTag = ClassTag[Return](classOf[Return]) - implicit val TryTag = ClassTag[Try](classOf[Try]) - implicit val ThrowTag = ClassTag[Throw](classOf[Throw]) - implicit val NewTag = ClassTag[New](classOf[New]) - implicit val TypedTag = ClassTag[Typed](classOf[Typed]) - implicit val GenericApplyTag = ClassTag[GenericApply](classOf[GenericApply]) - implicit val TypeApplyTag = ClassTag[TypeApply](classOf[TypeApply]) - implicit val ApplyTag = ClassTag[Apply](classOf[Apply]) - implicit val SuperTag = ClassTag[Super](classOf[Super]) - implicit val ThisTag = ClassTag[This](classOf[This]) - implicit val SelectTag = ClassTag[Select](classOf[Select]) - implicit val IdentTag = ClassTag[Ident](classOf[Ident]) - implicit val ReferenceToBoxedTag = ClassTag[ReferenceToBoxed](classOf[ReferenceToBoxed]) - implicit val LiteralTag = ClassTag[Literal](classOf[Literal]) - implicit val AnnotatedTag = ClassTag[Annotated](classOf[Annotated]) - implicit val SingletonTypeTreeTag = ClassTag[SingletonTypeTree](classOf[SingletonTypeTree]) - implicit val SelectFromTypeTreeTag = ClassTag[SelectFromTypeTree](classOf[SelectFromTypeTree]) - implicit val CompoundTypeTreeTag = ClassTag[CompoundTypeTree](classOf[CompoundTypeTree]) - implicit val AppliedTypeTreeTag = ClassTag[AppliedTypeTree](classOf[AppliedTypeTree]) - implicit val TypeBoundsTreeTag = ClassTag[TypeBoundsTree](classOf[TypeBoundsTree]) - implicit val ExistentialTypeTreeTag = ClassTag[ExistentialTypeTree](classOf[ExistentialTypeTree]) - implicit val TypeTreeTag = ClassTag[TypeTree](classOf[TypeTree]) - - def ClassDef(sym: Symbol, impl: Template): ClassDef = ??? - def ModuleDef(sym: Symbol, impl: Template): ModuleDef = ??? - def ValDef(sym: Symbol, rhs: Tree): ValDef = ??? - def ValDef(sym: Symbol): ValDef = ??? - def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef = ??? - def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef = ??? - def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef = ??? - def DefDef(sym: Symbol, rhs: Tree): DefDef = ??? - def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = ??? - def TypeDef(sym: Symbol, rhs: Tree): TypeDef = ??? - def TypeDef(sym: Symbol): TypeDef = ??? - def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = ??? - def CaseDef(pat: Tree, body: Tree): CaseDef = ??? - def Bind(sym: Symbol, body: Tree): Bind = ??? - def Try(body: Tree, cases: (Tree, Tree)*): Try = ??? - def Throw(tpe: Type, args: Tree*): Throw = ??? - def Apply(sym: Symbol, args: Tree*): Tree = ??? - def New(tpt: Tree, argss: List[List[Tree]]): Tree = ??? - def New(tpe: Type, args: Tree*): Tree = ??? - def New(sym: Symbol, args: Tree*): Tree = ??? - def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree = ??? - def Super(sym: Symbol, mix: TypeName): Tree = ??? - def This(sym: Symbol): Tree = ??? - def Select(qualifier: Tree, name: String): Select = ??? - def Select(qualifier: Tree, sym: Symbol): Select = ??? - def Ident(name: String): Ident = ??? - def Ident(sym: Symbol): Ident = ??? - def Block(stats: Tree*): Block = ??? - def TypeTree(tp: Type): TypeTree = ??? -} diff --git a/src/library/scala/reflect/base/Constants.scala b/src/library/scala/reflect/base/Constants.scala deleted file mode 100644 index ba12b02e92..0000000000 --- a/src/library/scala/reflect/base/Constants.scala +++ /dev/null @@ -1,20 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2012 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.reflect -package base - -trait Constants { - self: Universe => - - type Constant >: Null <: AnyRef - implicit val ConstantTag: ClassTag[Constant] - val Constant: ConstantExtractor - - abstract class ConstantExtractor { - def apply(value: Any): Constant - def unapply(arg: Constant): Option[Any] - } -} diff --git a/src/library/scala/reflect/base/FlagSets.scala b/src/library/scala/reflect/base/FlagSets.scala deleted file mode 100644 index 96cdbe894c..0000000000 --- a/src/library/scala/reflect/base/FlagSets.scala +++ /dev/null @@ -1,16 +0,0 @@ -package scala.reflect -package base - -trait FlagSets { self: Universe => - - /** An abstract type representing sets of flags that apply to definition trees and symbols */ - type FlagSet - - /** A tag that preserves the identity of the `FlagSet` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val FlagSetTag: ClassTag[FlagSet] - - /** The empty set of flags */ - val NoFlags: FlagSet -} diff --git a/src/library/scala/reflect/base/Mirrors.scala b/src/library/scala/reflect/base/Mirrors.scala deleted file mode 100644 index 50866ef000..0000000000 --- a/src/library/scala/reflect/base/Mirrors.scala +++ /dev/null @@ -1,12 +0,0 @@ -package scala.reflect -package base - -trait Mirrors { - self: Universe => - - /** .. */ - type Mirror >: Null <: MirrorOf[self.type] - - /** .. */ - val rootMirror: Mirror -} diff --git a/src/library/scala/reflect/base/Names.scala b/src/library/scala/reflect/base/Names.scala deleted file mode 100644 index ad99f54fb3..0000000000 --- a/src/library/scala/reflect/base/Names.scala +++ /dev/null @@ -1,58 +0,0 @@ -package scala.reflect -package base - -import scala.language.implicitConversions - -/** A trait that manages names. - * A name is a string in one of two name universes: terms and types. - * The same string can be a name in both universes. - * Two names are equal if they represent the same string and they are - * members of the same universe. - * - * Names are interned. That is, for two names `name11 and `name2`, - * `name1 == name2` implies `name1 eq name2`. - */ -trait Names { - /** Intentionally no implicit from String => Name. */ - implicit def stringToTermName(s: String): TermName = newTermName(s) - implicit def stringToTypeName(s: String): TypeName = newTypeName(s) - - /** The abstract type of names */ - type Name >: Null <: NameBase - implicit val NameTag: ClassTag[Name] - - /** The abstract type of names representing terms */ - type TypeName >: Null <: Name - implicit val TypeNameTag: ClassTag[TypeName] - - /** The abstract type of names representing types */ - type TermName >: Null <: Name - implicit val TermNameTag: ClassTag[TermName] - - /** The base API that all names support */ - abstract class NameBase { - /** Is this name a term name? */ - def isTermName: Boolean - - /** Is this name a type name? */ - def isTypeName: Boolean - - /** Returns a term name that represents the same string as this name */ - def toTermName: TermName - - /** Returns a type name that represents the same string as this name */ - def toTypeName: TypeName - } - - /** Create a new term name. - */ - def newTermName(s: String): TermName - - /** Creates a new type name. - */ - def newTypeName(s: String): TypeName - - def EmptyTermName: TermName = newTermName("") - - def EmptyTypeName: TypeName = EmptyTermName.toTypeName -} diff --git a/src/library/scala/reflect/base/Positions.scala b/src/library/scala/reflect/base/Positions.scala deleted file mode 100644 index 76a7382e9e..0000000000 --- a/src/library/scala/reflect/base/Positions.scala +++ /dev/null @@ -1,17 +0,0 @@ -package scala.reflect -package base - -trait Positions { - self: Universe => - - /** .. */ - type Position >: Null <: Attachments { type Pos = Position } - - /** A tag that preserves the identity of the `FlagSet` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val PositionTag: ClassTag[Position] - - /** .. */ - val NoPosition: Position -} diff --git a/src/library/scala/reflect/base/StandardDefinitions.scala b/src/library/scala/reflect/base/StandardDefinitions.scala deleted file mode 100644 index 8f1c96ea3f..0000000000 --- a/src/library/scala/reflect/base/StandardDefinitions.scala +++ /dev/null @@ -1,72 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2012 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.reflect -package base - -trait StandardDefinitions { - self: Universe => - - val definitions: DefinitionsBase - - trait DefinitionsBase extends StandardTypes { - // packages - def ScalaPackageClass: ClassSymbol - def ScalaPackage: ModuleSymbol - - // top types - def AnyClass : ClassSymbol - def AnyValClass: ClassSymbol - def ObjectClass: ClassSymbol - def AnyRefClass: TypeSymbol - - // bottom types - def NullClass : ClassSymbol - def NothingClass: ClassSymbol - - // the scala value classes - def UnitClass : ClassSymbol - def ByteClass : ClassSymbol - def ShortClass : ClassSymbol - def CharClass : ClassSymbol - def IntClass : ClassSymbol - def LongClass : ClassSymbol - def FloatClass : ClassSymbol - def DoubleClass : ClassSymbol - def BooleanClass: ClassSymbol - - // some special classes - def StringClass : ClassSymbol - def ClassClass : ClassSymbol - def ArrayClass : ClassSymbol - def ListClass : ClassSymbol - - // the Predef object - def PredefModule: ModuleSymbol - } - - trait StandardTypes { - // the scala value classes - val UnitTpe: Type - val ByteTpe: Type - val ShortTpe: Type - val CharTpe: Type - val IntTpe: Type - val LongTpe: Type - val FloatTpe: Type - val DoubleTpe: Type - val BooleanTpe: Type - - // top types - val AnyTpe: Type - val AnyValTpe: Type - val AnyRefTpe: Type - val ObjectTpe: Type - - // bottom types - val NothingTpe: Type - val NullTpe: Type - } -} diff --git a/src/library/scala/reflect/base/StandardNames.scala b/src/library/scala/reflect/base/StandardNames.scala deleted file mode 100644 index 3e569cd523..0000000000 --- a/src/library/scala/reflect/base/StandardNames.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* NSC -- new Scala compiler -* Copyright 2005-2012 LAMP/EPFL -* @author Martin Odersky -*/ - -package scala.reflect -package base - -// Q: I have a pretty name. Where do I put it - into base.StandardNames or into api.StandardNames? -// A: Is it necessary to construct trees (like EMPTY or WILDCARD_STAR)? If yes, then it goes to base.StandardNames. -// Is it necessary to perform reflection (like ERROR or LOCAL_SUFFIX_STRING)? If yes, then it goes to api.StandardNames. -// Otherwise it goes nowhere - reflection API should stay minimalistic. - -trait StandardNames { - self: Universe => - - val nme: TermNamesBase - val tpnme: TypeNamesBase - - trait NamesBase { - type NameType >: Null <: Name - val WILDCARD: NameType - } - - trait TermNamesBase extends NamesBase { - val CONSTRUCTOR: TermName - val ROOTPKG: TermName - } - - trait TypeNamesBase extends NamesBase { - val EMPTY: NameType - val WILDCARD_STAR: NameType - } -} diff --git a/src/library/scala/reflect/base/Symbols.scala b/src/library/scala/reflect/base/Symbols.scala deleted file mode 100644 index 3830264425..0000000000 --- a/src/library/scala/reflect/base/Symbols.scala +++ /dev/null @@ -1,289 +0,0 @@ -package scala.reflect -package base - -trait Symbols { self: Universe => - - /** The abstract type of symbols representing declarations */ - type Symbol >: Null <: SymbolBase - - /** A tag that preserves the identity of the `Symbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SymbolTag: ClassTag[Symbol] - - /** The abstract type of type symbols representing type, class, and trait declarations, - * as well as type parameters - */ - type TypeSymbol >: Null <: Symbol with TypeSymbolBase - - /** A tag that preserves the identity of the `TypeSymbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeSymbolTag: ClassTag[TypeSymbol] - - /** The abstract type of term symbols representing val, var, def, and object declarations as - * well as packages and value parameters. - */ - type TermSymbol >: Null <: Symbol with TermSymbolBase - - /** A tag that preserves the identity of the `TermSymbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TermSymbolTag: ClassTag[TermSymbol] - - /** The abstract type of method symbols representing def declarations */ - type MethodSymbol >: Null <: TermSymbol with MethodSymbolBase - - /** A tag that preserves the identity of the `MethodSymbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val MethodSymbolTag: ClassTag[MethodSymbol] - - /** The abstract type of module symbols representing object declarations */ - type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolBase - - /** A tag that preserves the identity of the `ModuleSymbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ModuleSymbolTag: ClassTag[ModuleSymbol] - - /** The abstract type of class symbols representing class and trait definitions */ - type ClassSymbol >: Null <: TypeSymbol with ClassSymbolBase - - /** A tag that preserves the identity of the `ClassSymbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ClassSymbolTag: ClassTag[ClassSymbol] - - /** The abstract type of free terms introduced by reification */ - type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolBase - - /** A tag that preserves the identity of the `FreeTermSymbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol] - - /** The abstract type of free types introduced by reification */ - type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolBase - - /** A tag that preserves the identity of the `FreeTypeSymbol` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val FreeTypeSymbolTag: ClassTag[FreeTypeSymbol] - - /** A special "missing" symbol */ - val NoSymbol: Symbol - - /** The base API that all symbols support */ - trait SymbolBase { this: Symbol => - - /** The owner of this symbol. This is the symbol - * that directly contains the current symbol's definition. - * The `NoSymbol` symbol does not have an owner, and calling this method - * on one causes an internal error. - * The owner of the Scala root class [[scala.reflect.api.mirror.RootClass]] - * and the Scala root object [[scala.reflect.api.mirror.RootPackage]] is `NoSymbol`. - * Every other symbol has a chain of owners that ends in - * [[scala.reflect.api.mirror.RootClass]]. - */ - def owner: Symbol - - /** The type of the symbol name. - * Can be either `TermName` or `TypeName` depending on whether this is a `TermSymbol` or a `TypeSymbol`. - * - * Type name namespaces do not intersect with term name namespaces. - * This fact is reflected in different types for names of `TermSymbol` and `TypeSymbol`. - */ - type NameType >: Null <: Name - - /** The name of the symbol as a member of the `Name` type. - */ - def name: Name - - /** The encoded full path name of this symbol, where outer names and inner names - * are separated by periods. - */ - def fullName: String - - /** Does this symbol represent the definition of a type? - * Note that every symbol is either a term or a type. - * So for every symbol `sym` (except for `NoSymbol`), - * either `sym.isTerm` is true or `sym.isType` is true. - */ - def isType: Boolean = false - - /** This symbol cast to a TypeSymbol. - * @throws ScalaReflectionException if `isType` is false. - */ - def asType: TypeSymbol = throw new ScalaReflectionException(s"$this is not a type") - - /** Does this symbol represent the definition of a term? - * Note that every symbol is either a term or a type. - * So for every symbol `sym` (except for `NoSymbol`), - * either `sym.isTerm` is true or `sym.isTerm` is true. - */ - def isTerm: Boolean = false - - /** This symbol cast to a TermSymbol. - * @throws ScalaReflectionException if `isTerm` is false. - */ - def asTerm: TermSymbol = throw new ScalaReflectionException(s"$this is not a term") - - /** Does this symbol represent the definition of a method? - * If yes, `isTerm` is also guaranteed to be true. - */ - def isMethod: Boolean = false - - /** This symbol cast to a MethodSymbol. - * @throws ScalaReflectionException if `isMethod` is false. - */ - def asMethod: MethodSymbol = { - def overloadedMsg = - "encapsulates multiple overloaded alternatives and cannot be treated as a method. "+ - "Consider invoking `<offending symbol>.asTerm.alternatives` and manually picking the required method" - def vanillaMsg = "is not a method" - val msg = if (isOverloadedMethod) overloadedMsg else vanillaMsg - throw new ScalaReflectionException(s"$this $msg") - } - - /** Used to provide a better error message for `asMethod` */ - protected def isOverloadedMethod = false - - /** Does this symbol represent the definition of a module (i.e. it - * results from an object definition?). - * If yes, `isTerm` is also guaranteed to be true. - */ - def isModule: Boolean = false - - /** This symbol cast to a ModuleSymbol defined by an object definition. - * @throws ScalaReflectionException if `isModule` is false. - */ - def asModule: ModuleSymbol = throw new ScalaReflectionException(s"$this is not a module") - - /** Does this symbol represent the definition of a class or trait? - * If yes, `isType` is also guaranteed to be true. - */ - def isClass: Boolean = false - - /** Does this symbol represent the definition of a class implicitly associated - * with an object definition (module class in scala compiler parlance). - * If yes, `isType` is also guaranteed to be true. - */ - def isModuleClass: Boolean = false - - /** This symbol cast to a ClassSymbol representing a class or trait. - * @throws ScalaReflectionException if `isClass` is false. - */ - def asClass: ClassSymbol = throw new ScalaReflectionException(s"$this is not a class") - - /** Does this symbol represent a free term captured by reification? - * If yes, `isTerm` is also guaranteed to be true. - */ - def isFreeTerm: Boolean = false - - /** This symbol cast to a free term symbol. - * @throws ScalaReflectionException if `isFreeTerm` is false. - */ - def asFreeTerm: FreeTermSymbol = throw new ScalaReflectionException(s"$this is not a free term") - - /** Does this symbol represent a free type captured by reification? - * If yes, `isType` is also guaranteed to be true. - */ - def isFreeType: Boolean = false - - /** This symbol cast to a free type symbol. - * @throws ScalaReflectionException if `isFreeType` is false. - */ - def asFreeType: FreeTypeSymbol = throw new ScalaReflectionException(s"$this is not a free type") - - def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol - def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol) - def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol - def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol - def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol - } - - /** The base API that all type symbols support */ - trait TypeSymbolBase extends SymbolBase { this: TypeSymbol => - /** Type symbols have their names of type `TypeName`. - */ - final type NameType = TypeName - - /** The type constructor corresponding to this type symbol. - * This is different from `toType` in that type parameters - * are part of results of `toType`, but not of `toTypeConstructor`. - * - * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol - * `C`. Then `C.toType` is the type `C[T]`, but `C.toTypeConstructor` is `C`. - */ - def toTypeConstructor: Type - - /** A type reference that refers to this type symbol seen - * as a member of given type `site`. - */ - def toTypeIn(site: Type): Type - - /** A type reference that refers to this type symbol - * Note if symbol is a member of a class, one almost always is interested - * in `asTypeIn` with a site type instead. - * - * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol - * `C`. Then `C.toType` is the type `C[T]`. - * - * By contrast, `C.typeSignature` would be a type signature of form - * `PolyType(ClassInfoType(...))` that describes type parameters, value - * parameters, parent types, and members of `C`. - */ - def toType: Type - - final override def isType = true - final override def asType = this - } - - /** The base API that all term symbols support */ - trait TermSymbolBase extends SymbolBase { this: TermSymbol => - /** Term symbols have their names of type `TermName`. - */ - final type NameType = TermName - - final override def isTerm = true - final override def asTerm = this - } - - /** The base API that all method symbols support */ - trait MethodSymbolBase extends TermSymbolBase { this: MethodSymbol => - final override def isMethod = true - final override def asMethod = this - } - - /** The base API that all module symbols support */ - trait ModuleSymbolBase extends TermSymbolBase { this: ModuleSymbol => - /** The class implicitly associated with the object definition. - * One can go back from a module class to the associated module symbol - * by inspecting its `selfType.termSymbol`. - */ - def moduleClass: Symbol // needed for tree traversals - // when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life - - final override def isModule = true - final override def asModule = this - } - - /** The base API that all class symbols support */ - trait ClassSymbolBase extends TypeSymbolBase { this: ClassSymbol => - final override def isClass = true - final override def asClass = this - } - - /** The base API that all free type symbols support */ - trait FreeTypeSymbolBase extends TypeSymbolBase { this: FreeTypeSymbol => - final override def isFreeType = true - final override def asFreeType = this - } - - /** The base API that all free term symbols support */ - trait FreeTermSymbolBase extends TermSymbolBase { this: FreeTermSymbol => - final override def isFreeTerm = true - final override def asFreeTerm = this - } -} diff --git a/src/library/scala/reflect/base/TagInterop.scala b/src/library/scala/reflect/base/TagInterop.scala deleted file mode 100644 index ec054106eb..0000000000 --- a/src/library/scala/reflect/base/TagInterop.scala +++ /dev/null @@ -1,15 +0,0 @@ -package scala.reflect -package base - -import scala.runtime.ScalaRunTime._ - -trait TagInterop { self: Universe => - // todo. `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work - // if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala - - def typeTagToManifest[T: ClassTag](mirror: Any, tag: base.Universe # TypeTag[T]): Manifest[T] = - throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.") - - def manifestToTypeTag[T](mirror: Any, manifest: Manifest[T]): base.Universe # TypeTag[T] = - throw new UnsupportedOperationException("This universe does not support manifest -> tag conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.") -} diff --git a/src/library/scala/reflect/base/TreeCreator.scala b/src/library/scala/reflect/base/TreeCreator.scala deleted file mode 100644 index c9c8de2307..0000000000 --- a/src/library/scala/reflect/base/TreeCreator.scala +++ /dev/null @@ -1,6 +0,0 @@ -package scala.reflect -package base - -abstract class TreeCreator { - def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Tree -} diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala deleted file mode 100644 index 78174f354c..0000000000 --- a/src/library/scala/reflect/base/Trees.scala +++ /dev/null @@ -1,1445 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2012 LAMP/EPFL - * @author Martin Odersky - */ -package scala.reflect -package base - -trait Trees { self: Universe => - - /** The base API that all trees support */ - abstract class TreeBase extends Product { this: Tree => - /** ... */ - def isDef: Boolean - - /** ... */ - def isEmpty: Boolean - - /** The canonical way to test if a Tree represents a term. - */ - def isTerm: Boolean - - /** The canonical way to test if a Tree represents a type. - */ - def isType: Boolean - - /** Obtains string representation of a tree */ - override def toString: String = treeToString(this) - } - - /** Obtains string representation of a tree */ - protected def treeToString(tree: Tree): String - - /** Obtains the type of the tree (we intentionally don't expose `tree.tpe` in base) */ - protected def treeType(tree: Tree): Type - - /** Tree is the basis for scala's abstract syntax. The nodes are - * implemented as case classes, and the parameters which initialize - * a given tree are immutable: however Trees have several mutable - * fields which are manipulated in the course of typechecking, - * including pos, symbol, and tpe. - * - * Newly instantiated trees have tpe set to null (though it - * may be set immediately thereafter depending on how it is - * constructed.) When a tree is passed to the typer, typically via - * `typer.typed(tree)`, under normal circumstances the tpe must be - * null or the typer will ignore it. Furthermore, the typer is not - * required to return the same tree it was passed. - * - * Trees can be easily traversed with e.g. foreach on the root node; - * for a more nuanced traversal, subclass Traverser. Transformations - * can be considerably trickier: see the numerous subclasses of - * Transformer found around the compiler. - * - * Copying Trees should be done with care depending on whether - * it need be done lazily or strictly (see LazyTreeCopier and - * StrictTreeCopier) and on whether the contents of the mutable - * fields should be copied. The tree copiers will copy the mutable - * attributes to the new tree; calling Tree#duplicate will copy - * symbol and tpe, but all the positions will be focused. - * - * Trees can be coarsely divided into four mutually exclusive categories: - * - * - TermTrees, representing terms - * - TypTrees, representing types. Note that is `TypTree`, not `TypeTree`. - * - SymTrees, which may represent types or terms. - * - Other Trees, which have none of those as parents. - * - * SymTrees include important nodes Ident and Select, which are - * used as both terms and types; they are distinguishable based on - * whether the Name is a TermName or TypeName. The correct way for - * to test for a type or a term (on any Tree) are the isTerm/isType - * methods on Tree. - * - * "Others" are mostly syntactic or short-lived constructs. Examples - * include CaseDef, which wraps individual match cases: they are - * neither terms nor types, nor do they carry a symbol. Another - * example is Parens, which is eliminated during parsing. - */ - type Tree >: Null <: TreeBase - - /** A tag that preserves the identity of the `Tree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TreeTag: ClassTag[Tree] - - /** The empty tree */ - val EmptyTree: Tree - - /** A tree for a term. Not all terms are TermTrees; use isTerm - * to reliably identify terms. - */ - type TermTree >: Null <: AnyRef with Tree - - /** A tag that preserves the identity of the `TermTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TermTreeTag: ClassTag[TermTree] - - /** A tree for a type. Not all types are TypTrees; use isType - * to reliably identify types. - */ - type TypTree >: Null <: AnyRef with Tree - - /** A tag that preserves the identity of the `TypTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypTreeTag: ClassTag[TypTree] - - /** A tree with a mutable symbol field, initialized to NoSymbol. - */ - type SymTree >: Null <: AnyRef with Tree - - /** A tag that preserves the identity of the `SymTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SymTreeTag: ClassTag[SymTree] - - /** A tree with a name - effectively, a DefTree or RefTree. - */ - type NameTree >: Null <: AnyRef with Tree - - /** A tag that preserves the identity of the `NameTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val NameTreeTag: ClassTag[NameTree] - - /** A tree which references a symbol-carrying entity. - * References one, as opposed to defining one; definitions - * are in DefTrees. - */ - type RefTree >: Null <: SymTree with NameTree - - /** A tag that preserves the identity of the `RefTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val RefTreeTag: ClassTag[RefTree] - - /** A tree which defines a symbol-carrying entity. - */ - type DefTree >: Null <: SymTree with NameTree - - /** A tag that preserves the identity of the `DefTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val DefTreeTag: ClassTag[DefTree] - - /** Common base class for all member definitions: types, classes, - * objects, packages, vals and vars, defs. - */ - type MemberDef >: Null <: DefTree - - /** A tag that preserves the identity of the `MemberDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val MemberDefTag: ClassTag[MemberDef] - - /** A packaging, such as `package pid { stats }` - */ - type PackageDef >: Null <: MemberDef - - /** A tag that preserves the identity of the `PackageDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val PackageDefTag: ClassTag[PackageDef] - - /** The constructor/deconstructor for `PackageDef` instances. */ - val PackageDef: PackageDefExtractor - - /** An extractor class to create and pattern match with syntax `PackageDef(pid, stats)`. - * This AST node corresponds to the following Scala code: - * - * `package` pid { stats } - */ - abstract class PackageDefExtractor { - def apply(pid: RefTree, stats: List[Tree]): PackageDef - def unapply(packageDef: PackageDef): Option[(RefTree, List[Tree])] - } - - /** A common base class for class and object definitions. - */ - type ImplDef >: Null <: MemberDef - - /** A tag that preserves the identity of the `ImplDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ImplDefTag: ClassTag[ImplDef] - - /** A class definition. - */ - type ClassDef >: Null <: ImplDef - - /** A tag that preserves the identity of the `ClassDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ClassDefTag: ClassTag[ClassDef] - - /** The constructor/deconstructor for `ClassDef` instances. */ - val ClassDef: ClassDefExtractor - - /** An extractor class to create and pattern match with syntax `ClassDef(mods, name, tparams, impl)`. - * This AST node corresponds to the following Scala code: - * - * mods `class` name [tparams] impl - * - * Where impl stands for: - * - * `extends` parents { defs } - */ - abstract class ClassDefExtractor { - def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template): ClassDef - def unapply(classDef: ClassDef): Option[(Modifiers, TypeName, List[TypeDef], Template)] - } - - /** An object definition, e.g. `object Foo`. Internally, objects are - * quite frequently called modules to reduce ambiguity. - * Eliminated by refcheck. - */ - type ModuleDef >: Null <: ImplDef - - /** A tag that preserves the identity of the `ModuleDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ModuleDefTag: ClassTag[ModuleDef] - - /** The constructor/deconstructor for `ModuleDef` instances. */ - val ModuleDef: ModuleDefExtractor - - /** An extractor class to create and pattern match with syntax `ModuleDef(mods, name, impl)`. - * This AST node corresponds to the following Scala code: - * - * mods `object` name impl - * - * Where impl stands for: - * - * `extends` parents { defs } - */ - abstract class ModuleDefExtractor { - def apply(mods: Modifiers, name: TermName, impl: Template): ModuleDef - def unapply(moduleDef: ModuleDef): Option[(Modifiers, TermName, Template)] - } - - /** A common base class for ValDefs and DefDefs. - */ - type ValOrDefDef >: Null <: MemberDef - - /** A tag that preserves the identity of the `ValOrDefDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ValOrDefDefTag: ClassTag[ValOrDefDef] - - /** Broadly speaking, a value definition. All these are encoded as ValDefs: - * - * - immutable values, e.g. "val x" - * - mutable values, e.g. "var x" - the MUTABLE flag set in mods - * - lazy values, e.g. "lazy val x" - the LAZY flag set in mods - * - method parameters, see vparamss in DefDef - the PARAM flag is set in mods - * - explicit self-types, e.g. class A { self: Bar => } - !!! not sure what is set. - */ - type ValDef >: Null <: ValOrDefDef - - /** A tag that preserves the identity of the `ValDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ValDefTag: ClassTag[ValDef] - - /** The constructor/deconstructor for `ValDef` instances. */ - val ValDef: ValDefExtractor - - /** An extractor class to create and pattern match with syntax `ValDef(mods, name, tpt, rhs)`. - * This AST node corresponds to the following Scala code: - * - * mods `val` name: tpt = rhs - * - * mods `var` name: tpt = rhs - * - * mods name: tpt = rhs // in signatures of function and method definitions - * - * self: Bar => // self-types (!!! not sure what is set) - * - * If the type of a value is not specified explicitly (i.e. is meant to be inferred), - * this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!). - */ - abstract class ValDefExtractor { - def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef - def unapply(valDef: ValDef): Option[(Modifiers, TermName, Tree, Tree)] - } - - /** A method or macro definition. - * @param name The name of the method or macro. Can be a type name in case this is a type macro - */ - type DefDef >: Null <: ValOrDefDef - - /** A tag that preserves the identity of the `DefDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val DefDefTag: ClassTag[DefDef] - - /** The constructor/deconstructor for `DefDef` instances. */ - val DefDef: DefDefExtractor - - /** An extractor class to create and pattern match with syntax `DefDef(mods, name, tparams, vparamss, tpt, rhs)`. - * This AST node corresponds to the following Scala code: - * - * mods `def` name[tparams](vparams_1)...(vparams_n): tpt = rhs - * - * If the return type is not specified explicitly (i.e. is meant to be inferred), - * this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!). - */ - abstract class DefDefExtractor { - def apply(mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef - def unapply(defDef: DefDef): Option[(Modifiers, Name, List[TypeDef], List[List[ValDef]], Tree, Tree)] - } - - /** An abstract type, a type parameter, or a type alias. - * Eliminated by erasure. - */ - type TypeDef >: Null <: MemberDef - - /** A tag that preserves the identity of the `TypeDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeDefTag: ClassTag[TypeDef] - - /** The constructor/deconstructor for `TypeDef` instances. */ - val TypeDef: TypeDefExtractor - - /** An extractor class to create and pattern match with syntax `TypeDef(mods, name, tparams, rhs)`. - * This AST node corresponds to the following Scala code: - * - * mods `type` name[tparams] = rhs - * - * mods `type` name[tparams] >: lo <: hi - * - * First usage illustrates `TypeDefs` representing type aliases and type parameters. - * Second usage illustrates `TypeDefs` representing abstract types, - * where lo and hi are both `TypeBoundsTrees` and `Modifier.deferred` is set in mods. - */ - abstract class TypeDefExtractor { - def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef - def unapply(typeDef: TypeDef): Option[(Modifiers, TypeName, List[TypeDef], Tree)] - } - - /** A labelled expression. Not expressible in language syntax, but - * generated by the compiler to simulate while/do-while loops, and - * also by the pattern matcher. - * - * The label acts much like a nested function, where `params` represents - * the incoming parameters. The symbol given to the LabelDef should have - * a MethodType, as if it were a nested function. - * - * Jumps are apply nodes attributed with a label's symbol. The - * arguments from the apply node will be passed to the label and - * assigned to the Idents. - * - * Forward jumps within a block are allowed. - */ - type LabelDef >: Null <: DefTree with TermTree - - /** A tag that preserves the identity of the `LabelDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val LabelDefTag: ClassTag[LabelDef] - - /** The constructor/deconstructor for `LabelDef` instances. */ - val LabelDef: LabelDefExtractor - - /** An extractor class to create and pattern match with syntax `LabelDef(name, params, rhs)`. - * - * This AST node does not have direct correspondence to Scala code. - * It is used for tailcalls and like. - * For example, while/do are desugared to label defs as follows: - * - * while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) - * do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) - */ - abstract class LabelDefExtractor { - def apply(name: TermName, params: List[Ident], rhs: Tree): LabelDef - def unapply(labelDef: LabelDef): Option[(TermName, List[Ident], Tree)] - } - - /** Import selector - * - * Representation of an imported name its optional rename and their optional positions - * - * Eliminated by typecheck. - * - * @param name the imported name - * @param namePos its position or -1 if undefined - * @param rename the name the import is renamed to (== name if no renaming) - * @param renamePos the position of the rename or -1 if undefined - */ - type ImportSelector >: Null <: AnyRef - - /** A tag that preserves the identity of the `ImportSelector` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ImportSelectorTag: ClassTag[ImportSelector] - - /** The constructor/deconstructor for `ImportSelector` instances. */ - val ImportSelector: ImportSelectorExtractor - - /** An extractor class to create and pattern match with syntax `ImportSelector(name:, namePos, rename, renamePos)`. - * This is not an AST node, it is used as a part of the `Import` node. - */ - abstract class ImportSelectorExtractor { - def apply(name: Name, namePos: Int, rename: Name, renamePos: Int): ImportSelector - def unapply(importSelector: ImportSelector): Option[(Name, Int, Name, Int)] - } - - /** Import clause - * - * @param expr - * @param selectors - */ - type Import >: Null <: SymTree - - /** A tag that preserves the identity of the `Import` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ImportTag: ClassTag[Import] - - /** The constructor/deconstructor for `Import` instances. */ - val Import: ImportExtractor - - /** An extractor class to create and pattern match with syntax `Import(expr, selectors)`. - * This AST node corresponds to the following Scala code: - * - * import expr.{selectors} - * - * Selectors are a list of pairs of names (from, to). // [Eugene++] obviously, they no longer are. please, document! - * The last (and maybe only name) may be a nme.WILDCARD. For instance: - * - * import qual.{x, y => z, _} - * - * Would be represented as: - * - * Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) - * - * The symbol of an `Import` is an import symbol @see Symbol.newImport. - * It's used primarily as a marker to check that the import has been typechecked. - */ - abstract class ImportExtractor { - def apply(expr: Tree, selectors: List[ImportSelector]): Import - def unapply(import_ : Import): Option[(Tree, List[ImportSelector])] - } - - /** Instantiation template of a class or trait - * - * @param parents - * @param body - */ - type Template >: Null <: SymTree - - /** A tag that preserves the identity of the `Template` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TemplateTag: ClassTag[Template] - - /** The constructor/deconstructor for `Template` instances. */ - val Template: TemplateExtractor - - /** An extractor class to create and pattern match with syntax `Template(parents, self, body)`. - * This AST node corresponds to the following Scala code: - * - * `extends` parents { self => body } - * - * In case when the self-type annotation is missing, it is represented as - * an empty value definition with nme.WILDCARD as name and NoType as type. - * - * The symbol of a template is a local dummy. @see Symbol.newLocalDummy - * The owner of the local dummy is the enclosing trait or class. - * The local dummy is itself the owner of any local blocks. For example: - * - * class C { - * def foo { // owner is C - * def bar // owner is local dummy - * } - * } - */ - abstract class TemplateExtractor { - def apply(parents: List[Tree], self: ValDef, body: List[Tree]): Template - def unapply(template: Template): Option[(List[Tree], ValDef, List[Tree])] - } - - /** Block of expressions (semicolon separated expressions) */ - type Block >: Null <: TermTree - - /** A tag that preserves the identity of the `Block` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val BlockTag: ClassTag[Block] - - /** The constructor/deconstructor for `Block` instances. */ - val Block: BlockExtractor - - /** An extractor class to create and pattern match with syntax `Block(stats, expr)`. - * This AST node corresponds to the following Scala code: - * - * { stats; expr } - * - * If the block is empty, the `expr` is set to `Literal(Constant(()))`. // [Eugene++] check this - */ - abstract class BlockExtractor { - def apply(stats: List[Tree], expr: Tree): Block - def unapply(block: Block): Option[(List[Tree], Tree)] - } - - /** Case clause in a pattern match, eliminated during explicitouter - * (except for occurrences in switch statements). - * Eliminated by patmat/explicitouter. - */ - type CaseDef >: Null <: AnyRef with Tree - - /** A tag that preserves the identity of the `CaseDef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val CaseDefTag: ClassTag[CaseDef] - - /** The constructor/deconstructor for `CaseDef` instances. */ - val CaseDef: CaseDefExtractor - - /** An extractor class to create and pattern match with syntax `CaseDef(pat, guard, body)`. - * This AST node corresponds to the following Scala code: - * - * `case` pat `if` guard => body - * - * If the guard is not present, the `guard` is set to `EmptyTree`. // [Eugene++] check this - * If the body is not specified, the `body` is set to `EmptyTree`. // [Eugene++] check this - */ - abstract class CaseDefExtractor { - def apply(pat: Tree, guard: Tree, body: Tree): CaseDef - def unapply(caseDef: CaseDef): Option[(Tree, Tree, Tree)] - } - - /** Alternatives of patterns, eliminated by explicitouter, except for - * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...))) - * Eliminated by patmat/explicitouter. - */ - type Alternative >: Null <: TermTree - - /** A tag that preserves the identity of the `Alternative` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val AlternativeTag: ClassTag[Alternative] - - /** The constructor/deconstructor for `Alternative` instances. */ - val Alternative: AlternativeExtractor - - /** An extractor class to create and pattern match with syntax `Alternative(trees)`. - * This AST node corresponds to the following Scala code: - * - * pat1 | ... | patn - */ - abstract class AlternativeExtractor { - def apply(trees: List[Tree]): Alternative - def unapply(alternative: Alternative): Option[List[Tree]] - } - - /** Repetition of pattern. - * Eliminated by patmat/explicitouter. - */ - type Star >: Null <: TermTree - - /** A tag that preserves the identity of the `Star` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val StarTag: ClassTag[Star] - - /** The constructor/deconstructor for `Star` instances. */ - val Star: StarExtractor - - /** An extractor class to create and pattern match with syntax `Star(elem)`. - * This AST node corresponds to the following Scala code: - * - * pat* - */ - abstract class StarExtractor { - def apply(elem: Tree): Star - def unapply(star: Star): Option[Tree] - } - - /** Bind of a variable to a rhs pattern, eliminated by explicitouter - * Eliminated by patmat/explicitouter. - * - * @param name - * @param body - */ - type Bind >: Null <: DefTree - - /** A tag that preserves the identity of the `Bind` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val BindTag: ClassTag[Bind] - - /** The constructor/deconstructor for `Bind` instances. */ - val Bind: BindExtractor - - /** An extractor class to create and pattern match with syntax `Bind(name, body)`. - * This AST node corresponds to the following Scala code: - * - * pat* - */ - abstract class BindExtractor { - def apply(name: Name, body: Tree): Bind - def unapply(bind: Bind): Option[(Name, Tree)] - } - - /** Used to represent `unapply` methods in pattern matching. - * Introduced by typer, eliminated by patmat/explicitouter. - * - * For example: - * {{{ - * 2 match { case Foo(x) => x } - * }}} - * - * Is represented as: - * {{{ - * Match( - * Literal(Constant(2)), - * List( - * CaseDef( - * UnApply( - * // a dummy node that carries the type of unapplication to patmat - * // the <unapply-selector> here doesn't have an underlying symbol - * // it only has a type assigned, therefore after `resetAllAttrs` this tree is no longer typeable - * Apply(Select(Ident(Foo), newTermName("unapply")), List(Ident(newTermName("<unapply-selector>")))), - * // arguments of the unapply => nothing synthetic here - * List(Bind(newTermName("x"), Ident(nme.WILDCARD)))), - * EmptyTree, - * Ident(newTermName("x"))))) - * }}} - */ - type UnApply >: Null <: TermTree - - /** A tag that preserves the identity of the `UnApply` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val UnApplyTag: ClassTag[UnApply] - - /** The constructor/deconstructor for `UnApply` instances. */ - val UnApply: UnApplyExtractor - - /** An extractor class to create and pattern match with syntax `UnApply(fun, args)`. - * This AST node does not have direct correspondence to Scala code, - * and is introduced when typechecking pattern matches and `try` blocks. - */ - abstract class UnApplyExtractor { - def apply(fun: Tree, args: List[Tree]): UnApply - def unapply(unApply: UnApply): Option[(Tree, List[Tree])] - } - - /** Array of expressions, needs to be translated in backend. - * This AST node is used to pass arguments to vararg arguments. - * Introduced by uncurry. - */ - type ArrayValue >: Null <: TermTree - - /** A tag that preserves the identity of the `ArrayValue` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ArrayValueTag: ClassTag[ArrayValue] - - /** The constructor/deconstructor for `ArrayValue` instances. */ - val ArrayValue: ArrayValueExtractor - - /** An extractor class to create and pattern match with syntax `ArrayValue(elemtpt, elems)`. - * This AST node does not have direct correspondence to Scala code, - * and is used to pass arguments to vararg arguments. For instance: - * - * printf("%s%d", foo, 42) - * - * Is translated to after uncurry to: - * - * Apply( - * Ident("printf"), - * Literal("%s%d"), - * ArrayValue(<Any>, List(Ident("foo"), Literal(42)))) - */ - abstract class ArrayValueExtractor { - def apply(elemtpt: Tree, elems: List[Tree]): ArrayValue - def unapply(arrayValue: ArrayValue): Option[(Tree, List[Tree])] - } - - /** Anonymous function, eliminated by lambdalift */ - type Function >: Null <: TermTree with SymTree - - /** A tag that preserves the identity of the `Function` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val FunctionTag: ClassTag[Function] - - /** The constructor/deconstructor for `Function` instances. */ - val Function: FunctionExtractor - - /** An extractor class to create and pattern match with syntax `Function(vparams, body)`. - * This AST node corresponds to the following Scala code: - * - * vparams => body - * - * The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME - * It is the owner of the function's parameters. - */ - abstract class FunctionExtractor { - def apply(vparams: List[ValDef], body: Tree): Function - def unapply(function: Function): Option[(List[ValDef], Tree)] - } - - /** Assignment */ - type Assign >: Null <: TermTree - - /** A tag that preserves the identity of the `Assign` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val AssignTag: ClassTag[Assign] - - /** The constructor/deconstructor for `Assign` instances. */ - val Assign: AssignExtractor - - /** An extractor class to create and pattern match with syntax `Assign(lhs, rhs)`. - * This AST node corresponds to the following Scala code: - * - * lhs = rhs - */ - abstract class AssignExtractor { - def apply(lhs: Tree, rhs: Tree): Assign - def unapply(assign: Assign): Option[(Tree, Tree)] - } - - /** Either an assignment or a named argument. Only appears in argument lists, - * eliminated by typecheck (doTypedApply), resurrected by reifier. - */ - type AssignOrNamedArg >: Null <: TermTree - - /** A tag that preserves the identity of the `AssignOrNamedArg` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val AssignOrNamedArgTag: ClassTag[AssignOrNamedArg] - - /** The constructor/deconstructor for `AssignOrNamedArg` instances. */ - val AssignOrNamedArg: AssignOrNamedArgExtractor - - /** An extractor class to create and pattern match with syntax `AssignOrNamedArg(lhs, rhs)`. - * This AST node corresponds to the following Scala code: - * - * @annotation(lhs = rhs) - * - * m.f(lhs = rhs) - */ - abstract class AssignOrNamedArgExtractor { - def apply(lhs: Tree, rhs: Tree): AssignOrNamedArg - def unapply(assignOrNamedArg: AssignOrNamedArg): Option[(Tree, Tree)] - } - - /** Conditional expression */ - type If >: Null <: TermTree - - /** A tag that preserves the identity of the `If` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val IfTag: ClassTag[If] - - /** The constructor/deconstructor for `If` instances. */ - val If: IfExtractor - - /** An extractor class to create and pattern match with syntax `If(cond, thenp, elsep)`. - * This AST node corresponds to the following Scala code: - * - * `if` (cond) thenp `else` elsep - * - * If the alternative is not present, the `elsep` is set to `EmptyTree`. // [Eugene++] check this - */ - abstract class IfExtractor { - def apply(cond: Tree, thenp: Tree, elsep: Tree): If - def unapply(if_ : If): Option[(Tree, Tree, Tree)] - } - - /** - Pattern matching expression (before explicitouter) - * - Switch statements (after explicitouter) - * - * After explicitouter, cases will satisfy the following constraints: - * - * - all guards are `EmptyTree`, - * - all patterns will be either `Literal(Constant(x:Int))` - * or `Alternative(lit|...|lit)` - * - except for an "otherwise" branch, which has pattern - * `Ident(nme.WILDCARD)` - */ - type Match >: Null <: TermTree - - /** A tag that preserves the identity of the `Match` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val MatchTag: ClassTag[Match] - - /** The constructor/deconstructor for `Match` instances. */ - val Match: MatchExtractor - - /** An extractor class to create and pattern match with syntax `Match(selector, cases)`. - * This AST node corresponds to the following Scala code: - * - * selector `match` { cases } - * - * // [Eugene++] say something about `val (foo, bar) = baz` and likes. - */ - abstract class MatchExtractor { - def apply(selector: Tree, cases: List[CaseDef]): Match - def unapply(match_ : Match): Option[(Tree, List[CaseDef])] - } - - /** Return expression */ - type Return >: Null <: TermTree with SymTree - - /** A tag that preserves the identity of the `Return` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ReturnTag: ClassTag[Return] - - /** The constructor/deconstructor for `Return` instances. */ - val Return: ReturnExtractor - - /** An extractor class to create and pattern match with syntax `Return(expr)`. - * This AST node corresponds to the following Scala code: - * - * `return` expr - * - * The symbol of a Return node is the enclosing method - */ - abstract class ReturnExtractor { - def apply(expr: Tree): Return - def unapply(return_ : Return): Option[Tree] - } - - /** [Eugene++] comment me! */ - type Try >: Null <: TermTree - - /** A tag that preserves the identity of the `Try` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TryTag: ClassTag[Try] - - /** The constructor/deconstructor for `Try` instances. */ - val Try: TryExtractor - - /** An extractor class to create and pattern match with syntax `Try(block, catches, finalizer)`. - * This AST node corresponds to the following Scala code: - * - * `try` block `catch` { catches } `finally` finalizer - * - * If the finalizer is not present, the `finalizer` is set to `EmptyTree`. // [Eugene++] check this - */ - abstract class TryExtractor { - def apply(block: Tree, catches: List[CaseDef], finalizer: Tree): Try - def unapply(try_ : Try): Option[(Tree, List[CaseDef], Tree)] - } - - /** Throw expression */ - type Throw >: Null <: TermTree - - /** A tag that preserves the identity of the `Throw` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ThrowTag: ClassTag[Throw] - - /** The constructor/deconstructor for `Throw` instances. */ - val Throw: ThrowExtractor - - /** An extractor class to create and pattern match with syntax `Throw(expr)`. - * This AST node corresponds to the following Scala code: - * - * `throw` expr - */ - abstract class ThrowExtractor { - def apply(expr: Tree): Throw - def unapply(throw_ : Throw): Option[Tree] - } - - /** Object instantiation - * One should always use factory method below to build a user level new. - * - * @param tpt a class type - */ - type New >: Null <: TermTree - - /** A tag that preserves the identity of the `New` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val NewTag: ClassTag[New] - - /** The constructor/deconstructor for `New` instances. */ - val New: NewExtractor - - /** An extractor class to create and pattern match with syntax `New(tpt)`. - * This AST node corresponds to the following Scala code: - * - * `new` T - * - * This node always occurs in the following context: - * - * (`new` tpt).<init>[targs](args) - */ - abstract class NewExtractor { - def apply(tpt: Tree): New - def unapply(new_ : New): Option[Tree] - } - - /** Type annotation, eliminated by cleanup */ - type Typed >: Null <: TermTree - - /** A tag that preserves the identity of the `Typed` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypedTag: ClassTag[Typed] - - /** The constructor/deconstructor for `Typed` instances. */ - val Typed: TypedExtractor - - /** An extractor class to create and pattern match with syntax `Typed(expr, tpt)`. - * This AST node corresponds to the following Scala code: - * - * expr: tpt - */ - abstract class TypedExtractor { - def apply(expr: Tree, tpt: Tree): Typed - def unapply(typed: Typed): Option[(Tree, Tree)] - } - - /** Common base class for Apply and TypeApply. This could in principle - * be a SymTree, but whether or not a Tree is a SymTree isn't used - * to settle any interesting questions, and it would add a useless - * field to all the instances (useless, since GenericApply forwards to - * the underlying fun.) - */ - type GenericApply >: Null <: TermTree - - /** A tag that preserves the identity of the `GenericApply` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val GenericApplyTag: ClassTag[GenericApply] - - /** Explicit type application. - * @PP: All signs point toward it being a requirement that args.nonEmpty, - * but I can't find that explicitly stated anywhere. Unless your last name - * is odersky, you should probably treat it as true. - */ - type TypeApply >: Null <: GenericApply - - /** A tag that preserves the identity of the `TypeApply` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeApplyTag: ClassTag[TypeApply] - - /** The constructor/deconstructor for `TypeApply` instances. */ - val TypeApply: TypeApplyExtractor - - /** An extractor class to create and pattern match with syntax `TypeApply(fun, args)`. - * This AST node corresponds to the following Scala code: - * - * fun[args] - */ - abstract class TypeApplyExtractor { - def apply(fun: Tree, args: List[Tree]): TypeApply - def unapply(typeApply: TypeApply): Option[(Tree, List[Tree])] - } - - /** Value application */ - type Apply >: Null <: GenericApply - - /** A tag that preserves the identity of the `Apply` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ApplyTag: ClassTag[Apply] - - /** The constructor/deconstructor for `Apply` instances. */ - val Apply: ApplyExtractor - - /** An extractor class to create and pattern match with syntax `Apply(fun, args)`. - * This AST node corresponds to the following Scala code: - * - * fun(args) - * - * For instance: - * - * fun[targs](args) - * - * Is expressed as: - * - * Apply(TypeApply(fun, targs), args) - */ - abstract class ApplyExtractor { - def apply(fun: Tree, args: List[Tree]): Apply - def unapply(apply: Apply): Option[(Tree, List[Tree])] - } - - /** Super reference, qual = corresponding this reference - * A super reference C.super[M] is represented as Super(This(C), M). - */ - type Super >: Null <: TermTree - - /** A tag that preserves the identity of the `Super` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SuperTag: ClassTag[Super] - - /** The constructor/deconstructor for `Super` instances. */ - val Super: SuperExtractor - - /** An extractor class to create and pattern match with syntax `Super(qual, mix)`. - * This AST node corresponds to the following Scala code: - * - * C.super[M] - * - * Which is represented as: - * - * Super(This(C), M) - * - * If `mix` is empty, it is tpnme.EMPTY. - * - * The symbol of a Super is the class _from_ which the super reference is made. - * For instance in C.super(...), it would be C. - */ - abstract class SuperExtractor { - def apply(qual: Tree, mix: TypeName): Super - def unapply(super_ : Super): Option[(Tree, TypeName)] - } - - /** Self reference */ - type This >: Null <: TermTree with SymTree - - /** A tag that preserves the identity of the `This` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ThisTag: ClassTag[This] - - /** The constructor/deconstructor for `This` instances. */ - val This: ThisExtractor - - /** An extractor class to create and pattern match with syntax `This(qual)`. - * This AST node corresponds to the following Scala code: - * - * qual.this - * - * The symbol of a This is the class to which the this refers. - * For instance in C.this, it would be C. - * - * If `mix` is empty, then ??? - */ - abstract class ThisExtractor { - def apply(qual: TypeName): This - def unapply(this_ : This): Option[TypeName] - } - - /** Designator <qualifier> . <name> */ - type Select >: Null <: RefTree - - /** A tag that preserves the identity of the `Select` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SelectTag: ClassTag[Select] - - /** The constructor/deconstructor for `Select` instances. */ - val Select: SelectExtractor - - /** An extractor class to create and pattern match with syntax `Select(qual, name)`. - * This AST node corresponds to the following Scala code: - * - * qualifier.selector - */ - abstract class SelectExtractor { - def apply(qualifier: Tree, name: Name): Select - def unapply(select: Select): Option[(Tree, Name)] - } - - /** Identifier <name> */ - type Ident >: Null <: RefTree - - /** A tag that preserves the identity of the `Ident` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val IdentTag: ClassTag[Ident] - - /** The constructor/deconstructor for `Ident` instances. */ - val Ident: IdentExtractor - - /** An extractor class to create and pattern match with syntax `Ident(qual, name)`. - * This AST node corresponds to the following Scala code: - * - * name - * - * Type checker converts idents that refer to enclosing fields or methods to selects. - * For example, name ==> this.name - */ - abstract class IdentExtractor { - def apply(name: Name): Ident - def unapply(ident: Ident): Option[Name] - } - - /** Marks underlying reference to id as boxed. - * @pre id must refer to a captured variable - * A reference such marked will refer to the boxed entity, no dereferencing - * with `.elem` is done on it. - * This tree node can be emitted by macros such as reify that call referenceCapturedVariable. - * It is eliminated in LambdaLift, where the boxing conversion takes place. - */ - type ReferenceToBoxed >: Null <: TermTree - - /** A tag that preserves the identity of the `ReferenceToBoxed` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ReferenceToBoxedTag: ClassTag[ReferenceToBoxed] - - /** The constructor/deconstructor for `ReferenceToBoxed` instances. */ - val ReferenceToBoxed: ReferenceToBoxedExtractor - - /** An extractor class to create and pattern match with syntax `ReferenceToBoxed(ident)`. - * This AST node does not have direct correspondence to Scala code, - * and is emitted by macros to reference capture vars directly without going through `elem`. - * - * For example: - * - * var x = ... - * fun { x } - * - * Will emit: - * - * Ident(x) - * - * Which gets transformed to: - * - * Select(Ident(x), "elem") - * - * If `ReferenceToBoxed` were used instead of Ident, no transformation would be performed. - */ - abstract class ReferenceToBoxedExtractor { - def apply(ident: Ident): ReferenceToBoxed - def unapply(referenceToBoxed: ReferenceToBoxed): Option[Ident] - } - - /** Literal */ - type Literal >: Null <: TermTree - - /** A tag that preserves the identity of the `Literal` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val LiteralTag: ClassTag[Literal] - - /** The constructor/deconstructor for `Literal` instances. */ - val Literal: LiteralExtractor - - /** An extractor class to create and pattern match with syntax `Literal(value)`. - * This AST node corresponds to the following Scala code: - * - * value - */ - abstract class LiteralExtractor { - def apply(value: Constant): Literal - def unapply(literal: Literal): Option[Constant] - } - - /** A tree that has an annotation attached to it. Only used for annotated types and - * annotation ascriptions, annotations on definitions are stored in the Modifiers. - * Eliminated by typechecker (typedAnnotated), the annotations are then stored in - * an AnnotatedType. - */ - type Annotated >: Null <: AnyRef with Tree - - /** A tag that preserves the identity of the `Annotated` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val AnnotatedTag: ClassTag[Annotated] - - /** The constructor/deconstructor for `Annotated` instances. */ - val Annotated: AnnotatedExtractor - - /** An extractor class to create and pattern match with syntax `Annotated(annot, arg)`. - * This AST node corresponds to the following Scala code: - * - * arg @annot // for types - * arg: @annot // for exprs - */ - abstract class AnnotatedExtractor { - def apply(annot: Tree, arg: Tree): Annotated - def unapply(annotated: Annotated): Option[(Tree, Tree)] - } - - /** Singleton type, eliminated by RefCheck */ - type SingletonTypeTree >: Null <: TypTree - - /** A tag that preserves the identity of the `SingletonTypeTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SingletonTypeTreeTag: ClassTag[SingletonTypeTree] - - /** The constructor/deconstructor for `SingletonTypeTree` instances. */ - val SingletonTypeTree: SingletonTypeTreeExtractor - - /** An extractor class to create and pattern match with syntax `SingletonTypeTree(ref)`. - * This AST node corresponds to the following Scala code: - * - * ref.type - */ - abstract class SingletonTypeTreeExtractor { - def apply(ref: Tree): SingletonTypeTree - def unapply(singletonTypeTree: SingletonTypeTree): Option[Tree] - } - - /** Type selection <qualifier> # <name>, eliminated by RefCheck */ - // [Eugene++] don't see why we need it, when we have Select - type SelectFromTypeTree >: Null <: TypTree with RefTree - - /** A tag that preserves the identity of the `SelectFromTypeTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SelectFromTypeTreeTag: ClassTag[SelectFromTypeTree] - - /** The constructor/deconstructor for `SelectFromTypeTree` instances. */ - val SelectFromTypeTree: SelectFromTypeTreeExtractor - - /** An extractor class to create and pattern match with syntax `SelectFromTypeTree(qualifier, name)`. - * This AST node corresponds to the following Scala code: - * - * qualifier # selector - * - * Note: a path-dependent type p.T is expressed as p.type # T - */ - abstract class SelectFromTypeTreeExtractor { - def apply(qualifier: Tree, name: TypeName): SelectFromTypeTree - def unapply(selectFromTypeTree: SelectFromTypeTree): Option[(Tree, TypeName)] - } - - /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ - type CompoundTypeTree >: Null <: TypTree - - /** A tag that preserves the identity of the `CompoundTypeTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val CompoundTypeTreeTag: ClassTag[CompoundTypeTree] - - /** The constructor/deconstructor for `CompoundTypeTree` instances. */ - val CompoundTypeTree: CompoundTypeTreeExtractor - - /** An extractor class to create and pattern match with syntax `CompoundTypeTree(templ)`. - * This AST node corresponds to the following Scala code: - * - * parent1 with ... with parentN { refinement } - */ - abstract class CompoundTypeTreeExtractor { - def apply(templ: Template): CompoundTypeTree - def unapply(compoundTypeTree: CompoundTypeTree): Option[Template] - } - - /** Applied type <tpt> [ <args> ], eliminated by RefCheck */ - type AppliedTypeTree >: Null <: TypTree - - /** A tag that preserves the identity of the `AppliedTypeTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val AppliedTypeTreeTag: ClassTag[AppliedTypeTree] - - /** The constructor/deconstructor for `AppliedTypeTree` instances. */ - val AppliedTypeTree: AppliedTypeTreeExtractor - - /** An extractor class to create and pattern match with syntax `AppliedTypeTree(tpt, args)`. - * This AST node corresponds to the following Scala code: - * - * tpt[args] - */ - abstract class AppliedTypeTreeExtractor { - def apply(tpt: Tree, args: List[Tree]): AppliedTypeTree - def unapply(appliedTypeTree: AppliedTypeTree): Option[(Tree, List[Tree])] - } - - /** Document me! */ - type TypeBoundsTree >: Null <: TypTree - - /** A tag that preserves the identity of the `TypeBoundsTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeBoundsTreeTag: ClassTag[TypeBoundsTree] - - /** The constructor/deconstructor for `TypeBoundsTree` instances. */ - val TypeBoundsTree: TypeBoundsTreeExtractor - - /** An extractor class to create and pattern match with syntax `TypeBoundsTree(lo, hi)`. - * This AST node corresponds to the following Scala code: - * - * >: lo <: hi - */ - abstract class TypeBoundsTreeExtractor { - def apply(lo: Tree, hi: Tree): TypeBoundsTree - def unapply(typeBoundsTree: TypeBoundsTree): Option[(Tree, Tree)] - } - - /** Document me! */ - type ExistentialTypeTree >: Null <: TypTree - - /** A tag that preserves the identity of the `ExistentialTypeTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ExistentialTypeTreeTag: ClassTag[ExistentialTypeTree] - - /** The constructor/deconstructor for `ExistentialTypeTree` instances. */ - val ExistentialTypeTree: ExistentialTypeTreeExtractor - - /** An extractor class to create and pattern match with syntax `ExistentialTypeTree(tpt, whereClauses)`. - * This AST node corresponds to the following Scala code: - * - * tpt forSome { whereClauses } - */ - abstract class ExistentialTypeTreeExtractor { - def apply(tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree - def unapply(existentialTypeTree: ExistentialTypeTree): Option[(Tree, List[Tree])] - } - - /** A synthetic tree holding an arbitrary type. Not to be confused with - * with TypTree, the trait for trees that are only used for type trees. - * TypeTree's are inserted in several places, but most notably in - * `RefCheck`, where the arbitrary type trees are all replaced by - * TypeTree's. */ - type TypeTree >: Null <: TypTree - - /** A tag that preserves the identity of the `TypeTree` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeTreeTag: ClassTag[TypeTree] - - /** The constructor/deconstructor for `TypeTree` instances. */ - val TypeTree: TypeTreeExtractor - - /** An extractor class to create and pattern match with syntax `TypeTree()`. - * This AST node does not have direct correspondence to Scala code, - * and is emitted by everywhere when we want to wrap a `Type` in a `Tree`. - */ - abstract class TypeTreeExtractor { - def apply(): TypeTree - def unapply(typeTree: TypeTree): Boolean - } - - /** ... */ - type Modifiers >: Null <: ModifiersBase - - /** A tag that preserves the identity of the `Modifiers` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ModifiersTag: ClassTag[Modifiers] - - /** ... */ - abstract class ModifiersBase { - def flags: FlagSet // default: NoFlags - def hasFlag(flag: FlagSet): Boolean - def privateWithin: Name // default: EmptyTypeName - def annotations: List[Tree] // default: List() - def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = - Modifiers(flags, privateWithin, f(annotations)) - } - - val Modifiers: ModifiersCreator - - abstract class ModifiersCreator { - def apply(): Modifiers = Modifiers(NoFlags, EmptyTypeName, List()) - def apply(flags: FlagSet, privateWithin: Name, annotations: List[Tree]): Modifiers - } - - def Modifiers(flags: FlagSet, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List()) - def Modifiers(flags: FlagSet): Modifiers = Modifiers(flags, EmptyTypeName) - - /** ... */ - lazy val NoMods = Modifiers() - -// ---------------------- factories ---------------------------------------------- - - /** @param sym the class symbol - * @param impl the implementation template - */ - def ClassDef(sym: Symbol, impl: Template): ClassDef - - /** - * @param sym the class symbol - * @param impl the implementation template - */ - def ModuleDef(sym: Symbol, impl: Template): ModuleDef - - def ValDef(sym: Symbol, rhs: Tree): ValDef - - def ValDef(sym: Symbol): ValDef - - def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef - - def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef - - def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef - - def DefDef(sym: Symbol, rhs: Tree): DefDef - - def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef - - /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */ - def TypeDef(sym: Symbol, rhs: Tree): TypeDef - - /** A TypeDef node which defines abstract type or type parameter for given `sym` */ - def TypeDef(sym: Symbol): TypeDef - - def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef - - /** Block factory that flattens directly nested blocks. - */ - def Block(stats: Tree*): Block - - /** casedef shorthand */ - def CaseDef(pat: Tree, body: Tree): CaseDef - - def Bind(sym: Symbol, body: Tree): Bind - - def Try(body: Tree, cases: (Tree, Tree)*): Try - - def Throw(tpe: Type, args: Tree*): Throw - - /** Factory method for object creation `new tpt(args_1)...(args_n)` - * A `New(t, as)` is expanded to: `(new t).<init>(as)` - */ - def New(tpt: Tree, argss: List[List[Tree]]): Tree - - /** 0-1 argument list new, based on a type. - */ - def New(tpe: Type, args: Tree*): Tree - - def New(sym: Symbol, args: Tree*): Tree - - def Apply(sym: Symbol, args: Tree*): Tree - - def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree - - def Super(sym: Symbol, mix: TypeName): Tree - - def This(sym: Symbol): Tree - - def Select(qualifier: Tree, name: String): Select - - def Select(qualifier: Tree, sym: Symbol): Select - - def Ident(name: String): Ident - - def Ident(sym: Symbol): Ident - - def TypeTree(tp: Type): TypeTree -}
\ No newline at end of file diff --git a/src/library/scala/reflect/base/TypeCreator.scala b/src/library/scala/reflect/base/TypeCreator.scala deleted file mode 100644 index 8a14e53dd3..0000000000 --- a/src/library/scala/reflect/base/TypeCreator.scala +++ /dev/null @@ -1,6 +0,0 @@ -package scala.reflect -package base - -abstract class TypeCreator { - def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type -} diff --git a/src/library/scala/reflect/base/Types.scala b/src/library/scala/reflect/base/Types.scala deleted file mode 100644 index 839c49805a..0000000000 --- a/src/library/scala/reflect/base/Types.scala +++ /dev/null @@ -1,426 +0,0 @@ -package scala.reflect -package base - -trait Types { self: Universe => - - /** The type of Scala types, and also Scala type signatures. - * (No difference is internally made between the two). - */ - type Type >: Null <: TypeBase - - /** The base API that all types support */ - abstract class TypeBase - - /** A tag that preserves the identity of the `Type` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeTagg: ClassTag[Type] - - /** This constant is used as a special value that indicates that no meaningful type exists. - */ - val NoType: Type - - /** This constant is used as a special value denoting the empty prefix in a path dependent type. - * For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for - * the symbol for `x`. - */ - val NoPrefix: Type - - /** The type of Scala singleton types, i.e. types that are inhabited - * by only one nun-null value. These include types of the forms - * {{{ - * C.this.type - * C.super.type - * x.type - * }}} - * as well as constant types. - */ - type SingletonType >: Null <: Type - - /** A tag that preserves the identity of the `SingletonType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SingletonTypeTag: ClassTag[SingletonType] - - /** The `ThisType` type describes types of the form on the left with the - * correspnding ThisType representations to the right. - * {{{ - * C.this.type ThisType(C) - * }}} - */ - type ThisType >: Null <: AnyRef with SingletonType - - /** A tag that preserves the identity of the `ThisType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ThisTypeTag: ClassTag[ThisType] - - /** The constructor/deconstructor for `ThisType` instances. */ - val ThisType: ThisTypeExtractor - - /** An extractor class to create and pattern match with syntax `ThisType(sym)` - * where `sym` is the class prefix of the this type. - */ - abstract class ThisTypeExtractor { - def apply(sym: Symbol): Type // not ThisTypebecause of implementation details - def unapply(tpe: ThisType): Option[Symbol] - } - - /** The `SingleType` type describes types of any of the forms on the left, - * with their TypeRef representations to the right. - * {{{ - * (T # x).type SingleType(T, x) - * p.x.type SingleType(p.type, x) - * x.type SingleType(NoPrefix, x) - * }}} - */ - type SingleType >: Null <: AnyRef with SingletonType - - /** A tag that preserves the identity of the `SingleType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SingleTypeTag: ClassTag[SingleType] - - /** The constructor/deconstructor for `SingleType` instances. */ - val SingleType: SingleTypeExtractor - - /** An extractor class to create and pattern match with syntax `SingleType(pre, sym)` - * Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol - * referred to by the single-type. - */ - abstract class SingleTypeExtractor { - def apply(pre: Type, sym: Symbol): Type // not SingleTypebecause of implementation details - def unapply(tpe: SingleType): Option[(Type, Symbol)] - } - - /** The `SuperType` type is not directly written, but arises when `C.super` is used - * as a prefix in a `TypeRef` or `SingleType`. It's internal presentation is - * {{{ - * SuperType(thistpe, supertpe) - * }}} - * Here, `thistpe` is the type of the corresponding this-type. For instance, - * in the type arising from C.super, the `thistpe` part would be `ThisType(C)`. - * `supertpe` is the type of the super class referred to by the `super`. - */ - type SuperType >: Null <: AnyRef with SingletonType - - /** A tag that preserves the identity of the `SuperType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val SuperTypeTag: ClassTag[SuperType] - - /** The constructor/deconstructor for `SuperType` instances. */ - val SuperType: SuperTypeExtractor - - /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)` - */ - abstract class SuperTypeExtractor { - def apply(thistpe: Type, supertpe: Type): Type // not SuperTypebecause of implementation details - def unapply(tpe: SuperType): Option[(Type, Type)] - } - - /** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant. - * The REPL expresses constant types like Int(11). Here are some constants with their types. - * {{{ - * 1 ConstantType(Constant(1)) - * "abc" ConstantType(Constant("abc")) - * }}} - */ - type ConstantType >: Null <: AnyRef with SingletonType - - /** A tag that preserves the identity of the `ConstantType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ConstantTypeTag: ClassTag[ConstantType] - - /** The constructor/deconstructor for `ConstantType` instances. */ - val ConstantType: ConstantTypeExtractor - - /** An extractor class to create and pattern match with syntax `ConstantType(constant)` - * Here, `constant` is the constant value represented by the type. - */ - abstract class ConstantTypeExtractor { - def apply(value: Constant): ConstantType - def unapply(tpe: ConstantType): Option[Constant] - } - - /** The `TypeRef` type describes types of any of the forms on the left, - * with their TypeRef representations to the right. - * {{{ - * T # C[T_1, ..., T_n] TypeRef(T, C, List(T_1, ..., T_n)) - * p.C[T_1, ..., T_n] TypeRef(p.type, C, List(T_1, ..., T_n)) - * C[T_1, ..., T_n] TypeRef(NoPrefix, C, List(T_1, ..., T_n)) - * T # C TypeRef(T, C, Nil) - * p.C TypeRef(p.type, C, Nil) - * C TypeRef(NoPrefix, C, Nil) - * }}} - */ - type TypeRef >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `TypeRef` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeRefTag: ClassTag[TypeRef] - - /** The constructor/deconstructor for `TypeRef` instances. */ - val TypeRef: TypeRefExtractor - - /** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)` - * Here, `pre` is the prefix of the type reference, `sym` is the symbol - * referred to by the type reference, and `args` is a possible empty list of - * type argumenrts. - */ - abstract class TypeRefExtractor { - def apply(pre: Type, sym: Symbol, args: List[Type]): Type // not TypeRefbecause of implementation details - def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] - } - - /** A subtype of Type representing refined types as well as `ClassInfo` signatures. - */ - type CompoundType >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `CompoundType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val CompoundTypeTag: ClassTag[CompoundType] - - /** The `RefinedType` type defines types of any of the forms on the left, - * with their RefinedType representations to the right. - * {{{ - * P_1 with ... with P_m { D_1; ...; D_n} RefinedType(List(P_1, ..., P_m), Scope(D_1, ..., D_n)) - * P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope()) - * { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n)) - * }}} - */ - type RefinedType >: Null <: AnyRef with CompoundType - - /** A tag that preserves the identity of the `RefinedType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val RefinedTypeTag: ClassTag[RefinedType] - - /** The constructor/deconstructor for `RefinedType` instances. */ - val RefinedType: RefinedTypeExtractor - - /** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)` - * Here, `parents` is the list of parent types of the class, and `decls` is the scope - * containing all declarations in the class. - */ - abstract class RefinedTypeExtractor { - def apply(parents: List[Type], decls: Scope): RefinedType - - /** An alternative constructor that passes in the synthetic classs symbol - * that backs the refined type. (Normally, a fresh class symbol is created automatically). - */ - def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType - def unapply(tpe: RefinedType): Option[(List[Type], Scope)] - } - - /** The `ClassInfo` type signature is used to define parents and declarations - * of classes, traits, and objects. If a class, trait, or object C is declared like this - * {{{ - * C extends P_1 with ... with P_m { D_1; ...; D_n} - * }}} - * its `ClassInfo` type has the following form: - * {{{ - * ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C) - * }}} - */ - type ClassInfoType >: Null <: AnyRef with CompoundType - - /** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ClassInfoTypeTag: ClassTag[ClassInfoType] - - /** The constructor/deconstructor for `ClassInfoType` instances. */ - val ClassInfoType: ClassInfoTypeExtractor - - /** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)` - * Here, `parents` is the list of parent types of the class, `decls` is the scope - * containing all declarations in the class, and `clazz` is the symbol of the class - * itself. - */ - abstract class ClassInfoTypeExtractor { - def apply(parents: List[Type], decls: Scope, typeSymbol: Symbol): ClassInfoType - def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] - } - - /** The `MethodType` type signature is used to indicate parameters and result type of a method - */ - type MethodType >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `MethodType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val MethodTypeTag: ClassTag[MethodType] - - /** The constructor/deconstructor for `MethodType` instances. */ - val MethodType: MethodTypeExtractor - - /** An extractor class to create and pattern match with syntax `MethodType(params, respte)` - * Here, `params` is a potentially empty list of parameter symbols of the method, - * and `restpe` is the result type of the method. If the method is curried, `restpe` would - * be another `MethodType`. - * Note: `MethodType(Nil, Int)` would be the type of a method defined with an empty parameter list. - * {{{ - * def f(): Int - * }}} - * If the method is completely parameterless, as in - * {{{ - * def f: Int - * }}} - * its type is a `NullaryMethodType`. - */ - abstract class MethodTypeExtractor { - def apply(params: List[Symbol], resultType: Type): MethodType - def unapply(tpe: MethodType): Option[(List[Symbol], Type)] - } - - /** The `NullaryMethodType` type signature is used for parameterless methods - * with declarations of the form `def foo: T` - */ - type NullaryMethodType >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType] - - /** The constructor/deconstructor for `NullaryMethodType` instances. */ - val NullaryMethodType: NullaryMethodTypeExtractor - - /** An extractor class to create and pattern match with syntax `NullaryMethodType(resultType)`. - * Here, `resultType` is the result type of the parameterless method. - */ - abstract class NullaryMethodTypeExtractor { - def apply(resultType: Type): NullaryMethodType - def unapply(tpe: NullaryMethodType): Option[(Type)] - } - - /** The `PolyType` type signature is used for polymorphic methods - * that have at least one type parameter. - */ - type PolyType >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `PolyType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val PolyTypeTag: ClassTag[PolyType] - - /** The constructor/deconstructor for `PolyType` instances. */ - val PolyType: PolyTypeExtractor - - /** An extractor class to create and pattern match with syntax `PolyType(typeParams, resultType)`. - * Here, `typeParams` are the type parameters of the method and `resultType` - * is the type signature following the type parameters. - */ - abstract class PolyTypeExtractor { - def apply(typeParams: List[Symbol], resultType: Type): PolyType - def unapply(tpe: PolyType): Option[(List[Symbol], Type)] - } - - /** The `ExistentialType` type signature is used for existential types and - * wildcard types. - */ - type ExistentialType >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `ExistentialType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val ExistentialTypeTag: ClassTag[ExistentialType] - - /** The constructor/deconstructor for `ExistentialType` instances. */ - val ExistentialType: ExistentialTypeExtractor - - /** An extractor class to create and pattern match with syntax - * `ExistentialType(quantified, underlying)`. - * Here, `quantified` are the type variables bound by the existential type and `underlying` - * is the type that's existentially quantified. - */ - abstract class ExistentialTypeExtractor { - def apply(quantified: List[Symbol], underlying: Type): ExistentialType - def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] - } - - /** The `AnnotatedType` type signature is used for annotated types of the - * for `<type> @<annotation>`. - */ - type AnnotatedType >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val AnnotatedTypeTag: ClassTag[AnnotatedType] - - /** The constructor/deconstructor for `AnnotatedType` instances. */ - val AnnotatedType: AnnotatedTypeExtractor - - /** An extractor class to create and pattern match with syntax - * `AnnotatedType(annotations, underlying, selfsym)`. - * Here, `annotations` are the annotations decorating the underlying type `underlying`. - * `selfSym` is a symbol representing the annotated type itself. - */ - abstract class AnnotatedTypeExtractor { - def apply(annotations: List[Annotation], underlying: Type, selfsym: Symbol): AnnotatedType - def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type, Symbol)] - } - - /** The `TypeBounds` type signature is used to indicate lower and upper type bounds - * of type parameters and abstract types. It is not a first-class type. - * If an abstract type or type parameter is declared with any of the forms - * on the left, its type signature is the TypeBounds type on the right. - * {{{ - * T >: L <: U TypeBounds(L, U) - * T >: L TypeBounds(L, Any) - * T <: U TypeBounds(Nothing, U) - * }}} - */ - type TypeBounds >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `TypeBounds` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val TypeBoundsTag: ClassTag[TypeBounds] - - /** The constructor/deconstructor for `TypeBounds` instances. */ - val TypeBounds: TypeBoundsExtractor - - /** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)` - * Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is - * the upper bound. - */ - abstract class TypeBoundsExtractor { - def apply(lo: Type, hi: Type): TypeBounds - def unapply(tpe: TypeBounds): Option[(Type, Type)] - } - - /** An object representing an unknown type, used during type inference. - * If you see WildcardType outside of inference it is almost certainly a bug. - */ - val WildcardType: Type - - /** BoundedWildcardTypes, used only during type inference, are created in - * two places that I can find: - * - * 1. If the expected type of an expression is an existential type, - * its hidden symbols are replaced with bounded wildcards. - * 2. When an implicit conversion is being sought based in part on - * the name of a method in the converted type, a HasMethodMatching - * type is created: a MethodType with parameters typed as - * BoundedWildcardTypes. - */ - type BoundedWildcardType >: Null <: AnyRef with Type - - /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure. - * Can be used for pattern matching, instance tests, serialization and likes. - */ - implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType] - - val BoundedWildcardType: BoundedWildcardTypeExtractor - - abstract class BoundedWildcardTypeExtractor { - def apply(bounds: TypeBounds): BoundedWildcardType - def unapply(tpe: BoundedWildcardType): Option[TypeBounds] - } -} diff --git a/src/library/scala/reflect/base/Universe.scala b/src/library/scala/reflect/base/Universe.scala deleted file mode 100644 index 36b85ca714..0000000000 --- a/src/library/scala/reflect/base/Universe.scala +++ /dev/null @@ -1,67 +0,0 @@ -package scala.reflect -package base - -abstract class Universe extends Symbols - with Types - with FlagSets - with Scopes - with Names - with Trees - with Constants - with Annotations - with Positions - with Exprs - with TypeTags - with TagInterop - with StandardDefinitions - with StandardNames - with BuildUtils - with Mirrors -{ - /** Given an expression, generate a tree that when compiled and executed produces the original tree. - * The produced tree will be bound to the Universe it was called from. - * - * For instance, given the abstract syntax tree representation of the <[ x + 1 ]> expression: - * - * {{{ - * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1)))) - * }}} - * - * The reifier transforms it to the following expression: - * - * {{{ - * <[ - * val $u: u.type = u // where u is a reference to the Universe that calls the reify - * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1)))))) - * ]> - * }}} - * - * Reification performs expression splicing (when processing Expr.splice) - * and type splicing (for every type T that has a TypeTag[T] implicit in scope): - * - * {{{ - * val two = mirror.reify(2) // Literal(Constant(2)) - * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree)) - * - * def macroImpl[T](c: Context) = { - * ... - * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion - * // however, if T were annotated with c.WeakTypeTag (which would declare an implicit parameter for macroImpl) - * // then reification would substitute T with the TypeTree that was used in a TypeApply of this particular macro invocation - * val factory = c.reify{ new Queryable[T] } - * ... - * } - * }}} - * - * The transformation looks mostly straightforward, but it has its tricky parts: - * * Reifier retains symbols and types defined outside the reified tree, however - * locally defined entities get erased and replaced with their original trees - * * Free variables are detected and wrapped in symbols of the type FreeVar - * * Mutable variables that are accessed from a local function are wrapped in refs - * * Since reified trees can be compiled outside of the scope they've been created in, - * special measures are taken to ensure that all members accessed in the reifee remain visible - */ - // implementation is hardwired to `scala.reflect.reify.Taggers` - // using the mechanism implemented in `scala.tools.reflect.FastTrack` - def reify[T](expr: T): Expr[T] = ??? // macro -}
\ No newline at end of file diff --git a/src/library/scala/reflect/macros/internal/package.scala b/src/library/scala/reflect/macros/internal/package.scala deleted file mode 100644 index 8457285752..0000000000 --- a/src/library/scala/reflect/macros/internal/package.scala +++ /dev/null @@ -1,14 +0,0 @@ -package scala.reflect.macros - -import scala.reflect.base.{Universe => BaseUniverse} -import scala.reflect.ClassTag - -// anchors for materialization macros emitted during tag materialization in Implicits.scala -// implementation is hardwired into `scala.reflect.reify.Taggers` -// using the mechanism implemented in `scala.tools.reflect.FastTrack` -// todo. once we have implicit macros for tag generation, we can remove these anchors -package object internal { - private[scala] def materializeClassTag[T](u: BaseUniverse): ClassTag[T] = ??? // macro - private[scala] def materializeWeakTypeTag[T](u: BaseUniverse): u.WeakTypeTag[T] = ??? // macro - private[scala] def materializeTypeTag[T](u: BaseUniverse): u.TypeTag[T] = ??? // macro -} diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index d97f2ec633..4f1cc03dc8 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -2,8 +2,6 @@ package scala package object reflect { - lazy val basis: base.Universe = new base.Base - // in the new scheme of things ClassManifests are aliased to ClassTags // this is done because we want `toArray` in collections work with ClassTags // but changing it to use the ClassTag context bound without aliasing ClassManifest @@ -42,13 +40,12 @@ package object reflect { val Manifest = ManifestFactory def classTag[T](implicit ctag: ClassTag[T]) = ctag - // typeTag incantation is defined inside scala.reflect.basis and scala.reflect.runtime.universe - - // ClassTag class is defined in ClassTag.scala - type TypeTag[T] = scala.reflect.basis.TypeTag[T] - // ClassTag object is defined in ClassTag.scala - lazy val TypeTag = scala.reflect.basis.TypeTag + // anchor for the class tag materialization macro emitted during tag materialization in Implicits.scala + // 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 this anchor + private[scala] def materializeClassTag[T](): ClassTag[T] = ??? // macro @deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0") type BeanDescription = scala.beans.BeanDescription diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index c7f1d2fcac..5c9e36450b 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -208,12 +208,12 @@ object ScalaRunTime { // Note that these are the implementations called by ##, so they // must not call ## themselves. - @inline def hash(x: Any): Int = + def hash(x: Any): Int = if (x == null) 0 else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number]) else x.hashCode - @inline def hash(dv: Double): Int = { + def hash(dv: Double): Int = { val iv = dv.toInt if (iv == dv) return iv @@ -223,7 +223,7 @@ object ScalaRunTime { val fv = dv.toFloat if (fv == dv) fv.hashCode else dv.hashCode } - @inline def hash(fv: Float): Int = { + def hash(fv: Float): Int = { val iv = fv.toInt if (iv == fv) return iv @@ -231,22 +231,22 @@ object ScalaRunTime { if (lv == fv) return hash(lv) else fv.hashCode } - @inline def hash(lv: Long): Int = { + def hash(lv: Long): Int = { val low = lv.toInt val lowSign = low >>> 31 val high = (lv >>> 32).toInt low ^ (high + lowSign) } - @inline def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x) + def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x) // The remaining overloads are here for completeness, but the compiler // inlines these definitions directly so they're not generally used. - @inline def hash(x: Int): Int = x - @inline def hash(x: Short): Int = x.toInt - @inline def hash(x: Byte): Int = x.toInt - @inline def hash(x: Char): Int = x.toInt - @inline def hash(x: Boolean): Int = if (x) true.hashCode else false.hashCode - @inline def hash(x: Unit): Int = 0 + def hash(x: Int): Int = x + def hash(x: Short): Int = x.toInt + def hash(x: Byte): Int = x.toInt + def hash(x: Char): Int = x.toInt + def hash(x: Boolean): Int = if (x) true.hashCode else false.hashCode + def hash(x: Unit): Int = 0 /** A helper method for constructing case class equality methods, * because existential types get in the way of a clean outcome and diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala index a1450ee876..6df0cec7fe 100644 --- a/src/partest/scala/tools/partest/CompilerTest.scala +++ b/src/partest/scala/tools/partest/CompilerTest.scala @@ -5,7 +5,7 @@ package scala.tools.partest -import scala.reflect.{basis => rb} +import scala.reflect.runtime.{universe => ru} import scala.tools.nsc._ /** For testing compiler internals directly. @@ -34,7 +34,7 @@ abstract class CompilerTest extends DirectTest { // Utility functions class MkType(sym: Symbol) { - def apply[M](implicit t: rb.TypeTag[M]): Type = + def apply[M](implicit t: ru.TypeTag[M]): Type = if (sym eq NoSymbol) NoType else appliedType(sym, compilerTypeFromTag(t)) } diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala index ebd3e46b7c..df1c296d47 100644 --- a/src/partest/scala/tools/partest/package.scala +++ b/src/partest/scala/tools/partest/package.scala @@ -93,11 +93,34 @@ package object partest { import scala.reflect.macros.Context def traceImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]): c.Expr[A] = { import c.universe._ - val exprCode = c.literal(show(a.tree)) - val exprType = c.literal(show(a.actualType)) - reify { - println(s"trace> ${exprCode.splice}\nres: ${exprType.splice} = ${a.splice}\n") - a.splice - } + import definitions._ + + // xeno.by: reify shouldn't be used explicitly before the final release of 2.10.0, + // because this impairs reflection refactorings + // + // val exprCode = c.literal(show(a.tree)) + // val exprType = c.literal(show(a.actualType)) + // reify { + // println(s"trace> ${exprCode.splice}\nres: ${exprType.splice} = ${a.splice}\n") + // a.splice + // } + + c.Expr(Block( + List(Apply( + Select(Ident(PredefModule), newTermName("println")), + List(Apply( + Select(Apply( + Select(Ident(ScalaPackage), newTermName("StringContext")), + List( + Literal(Constant("trace> ")), + Literal(Constant("\\nres: ")), + Literal(Constant(" = ")), + Literal(Constant("\\n")))), + newTermName("s")), + List( + Literal(Constant(show(a.tree))), + Literal(Constant(show(a.actualType))), + a.tree))))), + a.tree)) } } diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala index 43e95f9902..37882a9f3c 100644 --- a/src/reflect/scala/reflect/api/Annotations.scala +++ b/src/reflect/scala/reflect/api/Annotations.scala @@ -3,26 +3,121 @@ package api import scala.collection.immutable.ListMap -trait Annotations extends base.Annotations { self: Universe => +/** + * Defines the type hierarchy for annotations. + */ +trait Annotations { self: Universe => + + /** Typed information about an annotation. It can be attached to either a symbol or an annotated type. + * + * Annotations are either ''Scala annotations'', which conform to [[scala.annotation.StaticAnnotation]] + * or ''Java annotations'', which conform to [[scala.annotation.ClassfileAnnotation]]. + * Trait `ClassfileAnnotation` is automatically added to every Java annotation by the scalac classfile parser. + */ + type Annotation >: Null <: AnyRef with AnnotationApi + + /** A tag that preserves the identity of the `Annotation` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AnnotationTag: ClassTag[Annotation] + + /** The constructor/deconstructor for `Annotation` instances. */ + val Annotation: AnnotationExtractor + + /** An extractor class to create and pattern match with syntax `Annotation(atp, scalaArgs, javaArgs)`. + * Here, `atp` is the annotation type, `scalaArgs` the arguments, and `javaArgs` the annotation's key-value + * pairs. + * + * Annotations are pickled, i.e. written to scala symtab attribute in the classfile. + * Annotations are written to the classfile as Java annotations if `atp` conforms to `ClassfileAnnotation`. + * + * For Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty. Arguments in + * `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases + * following the type-checker. For Java annotations, `scalaArgs` is empty and arguments are stored in + * `javaArgs`. + */ + abstract class AnnotationExtractor { + def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation + def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])] + } - override type Annotation >: Null <: AnyRef with AnnotationApi trait AnnotationApi { def tpe: Type def scalaArgs: List[Tree] def javaArgs: ListMap[Name, JavaArgument] } - override type LiteralArgument >: Null <: JavaArgument with LiteralArgumentApi + /** A Java annotation argument */ + type JavaArgument >: Null <: AnyRef + implicit val JavaArgumentTag: ClassTag[JavaArgument] + + /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`*/ + type LiteralArgument >: Null <: AnyRef with JavaArgument with LiteralArgumentApi + + /** A tag that preserves the identity of the `LiteralArgument` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val LiteralArgumentTag: ClassTag[LiteralArgument] + + /** The constructor/deconstructor for `LiteralArgument` instances. */ + val LiteralArgument: LiteralArgumentExtractor + + /** An extractor class to create and pattern match with syntax `LiteralArgument(value)` + * where `value` is the constant argument. + */ + abstract class LiteralArgumentExtractor { + def apply(value: Constant): LiteralArgument + def unapply(arg: LiteralArgument): Option[Constant] + } + trait LiteralArgumentApi { def value: Constant } - override type ArrayArgument >: Null <: JavaArgument with ArrayArgumentApi + /** An array argument to a Java annotation as in `@Target(value={TYPE,FIELD,METHOD,PARAMETER})` + */ + type ArrayArgument >: Null <: AnyRef with JavaArgument with ArrayArgumentApi + + /** A tag that preserves the identity of the `ArrayArgument` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ArrayArgumentTag: ClassTag[ArrayArgument] + + /** The constructor/deconstructor for `ArrayArgument` instances. */ + val ArrayArgument: ArrayArgumentExtractor + + /** An extractor class to create and pattern match with syntax `ArrayArgument(args)` + * where `args` is the argument array. + */ + abstract class ArrayArgumentExtractor { + def apply(args: Array[JavaArgument]): ArrayArgument + def unapply(arg: ArrayArgument): Option[Array[JavaArgument]] + } + trait ArrayArgumentApi { def args: Array[JavaArgument] } - override type NestedArgument >: Null <: JavaArgument with NestedArgumentApi + /** A nested annotation argument to a Java annotation as `@Nested` in `@Outer(@Nested)`. + */ + type NestedArgument >: Null <: AnyRef with JavaArgument with NestedArgumentApi + + /** A tag that preserves the identity of the `NestedArgument` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val NestedArgumentTag: ClassTag[NestedArgument] + + /** The constructor/deconstructor for `NestedArgument` instances. */ + val NestedArgument: NestedArgumentExtractor + + /** An extractor class to create and pattern match with syntax `NestedArgument(annotation)` + * where `annotation` is the nested annotation. + */ + abstract class NestedArgumentExtractor { + def apply(annotation: Annotation): NestedArgument + def unapply(arg: NestedArgument): Option[Annotation] + } + trait NestedArgumentApi { def annotation: Annotation } diff --git a/src/library/scala/reflect/base/Attachments.scala b/src/reflect/scala/reflect/api/Attachments.scala index 889ac0ac14..edbb0131ca 100644 --- a/src/library/scala/reflect/base/Attachments.scala +++ b/src/reflect/scala/reflect/api/Attachments.scala @@ -1,35 +1,42 @@ package scala.reflect -package base +package api -/** Attachments is a generalisation of Position. - * Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads. +/** Attachments is a generalization of Position. Typically it stores a Position of a tree, but this can be extended to + * encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written + * with `update[T]` and `remove[T]`. * - * Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree + * Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree` * imposing an unnecessary memory tax because of something that will not be used in most cases. */ abstract class Attachments { self => + /** The position type of this attachment */ type Pos >: Null - /** Gets the underlying position */ + /** The underlying position */ def pos: Pos - /** Creates a copy of this attachment with its position updated */ + /** Creates a copy of this attachment with the position replaced by `newPos` */ def withPos(newPos: Pos): Attachments { type Pos = self.Pos } - /** Gets the underlying payload */ + /** The underlying payload with the guarantee that no two elements have the same type. */ def all: Set[Any] = Set.empty private def matchesTag[T: ClassTag](datum: Any) = classTag[T].runtimeClass == datum.getClass + /** An underlying payload of the given class type `T`. */ def get[T: ClassTag]: Option[T] = (all filter matchesTag[T]).headOption.asInstanceOf[Option[T]] - /** Creates a copy of this attachment with its payload updated */ + /** Creates a copy of this attachment with the payload slot of T added/updated with the provided value. + * + * Replaces an existing payload of the same type, if exists. + */ def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } = new NonemptyAttachments(this.pos, remove[T].all + attachment) + /** Creates a copy of this attachment with the payload of the given class type `T` removed. */ def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = { val newAll = all filterNot matchesTag[T] if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }] @@ -41,5 +48,3 @@ abstract class Attachments { self => def withPos(newPos: Pos) = new NonemptyAttachments(newPos, all) } } - - diff --git a/src/library/scala/reflect/base/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index e4710316e2..2bb0cc3c76 100644 --- a/src/library/scala/reflect/base/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -1,15 +1,18 @@ package scala.reflect -package base +package api +/** + * This is an internal implementation class. + */ trait BuildUtils { self: Universe => - val build: BuildBase + val build: BuildApi // this API abstracts away the functionality necessary for reification // it's too gimmicky and unstructured to be exposed directly in the universe // but we need it in a publicly available place for reification to work - abstract class BuildBase { + abstract class BuildApi { /** Selects type symbol with given simple name `name` from the defined members of `owner`. */ def selectType(owner: Symbol, name: String): TypeSymbol diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala index 6657245003..f2d8ef2eb9 100644 --- a/src/reflect/scala/reflect/api/Constants.scala +++ b/src/reflect/scala/reflect/api/Constants.scala @@ -6,10 +6,33 @@ package scala.reflect package api -trait Constants extends base.Constants { +/** + * Defines the type hierachy for compile-time constants. + * + * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here. + */ +trait Constants { self: Universe => - override type Constant >: Null <: AnyRef with ConstantApi + /** The type of compile-time constants. + */ + type Constant >: Null <: AnyRef with ConstantApi + + /** A tag that preserves the identity of the `Constant` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ConstantTag: ClassTag[Constant] + + /** The constructor/deconstructor for `Constant` instances. */ + val Constant: ConstantExtractor + + /** An extractor class to create and pattern match with syntax `Constant(value)` + * where `value` is the Scala value of the constant. + */ + abstract class ConstantExtractor { + def apply(value: Any): Constant + def unapply(arg: Constant): Option[Any] + } abstract class ConstantApi { val value: Any diff --git a/src/library/scala/reflect/base/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala index 45598c03e2..65b0eb9301 100644 --- a/src/library/scala/reflect/base/Exprs.scala +++ b/src/reflect/scala/reflect/api/Exprs.scala @@ -4,20 +4,77 @@ */ package scala.reflect -package base +package api + +import scala.reflect.runtime.{universe => ru} trait Exprs { self: Universe => - /** An expression tree tagged with its type */ + /** Expr wraps an expression tree and tags it with its type. */ trait Expr[+T] extends Equals with Serializable { val mirror: Mirror + /** + * Migrates the expression into another mirror, jumping into a different universe if necessary. + * + * This means that all symbolic references to classes/objects/packages in the expression + * will be re-resolved within the new mirror (typically using that mirror's classloader). + */ def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # Expr[T] + /** + * The Scala syntax tree representing the wrapped expression. + */ def tree: Tree + + /** + * Representation of the type of the wrapped expression tree as found via type tags. + */ def staticType: Type + /** + * Representation of the type of the wrapped expression tree as found in the tree. + */ def actualType: Type + /** + * A dummy method to mark expression splicing in reification. + * + * It should only be used within a `reify` call, which eliminates the `splice` call and embeds + * the wrapped tree into the reified surrounding expression. + * If used alone `splice` throws an exception when called at runtime. + * + * If you want to use an Expr in reification of some Scala code, you need to splice it in. + * For an expr of type `Expr[T]`, where `T` has a method `foo`, the following code + * {{{ + * reify{ expr.splice.foo } + * }}} + * uses splice to turn an expr of type Expr[T] into a value of type T in the context of `reify`. + * + * It is equivalent to + * {{{ + * Select( expr.tree, newTermName("foo") ) + * }}} + * + * The following example code however does not compile + * {{{ + * reify{ expr.foo } + * }}} + * because expr of type Expr[T] itself does not have a method foo. + */ def splice: T + /** + * A dummy value to denote cross-stage path-dependent type dependencies. + * + * For example for the following macro definition: + * {{{ + * class X { type T } + * object Macros { def foo(x: X): x.T = macro Impls.foo_impl } + * }}} + * + * The corresponding macro implementation should have the following signature (note how the return type denotes path-dependency on x): + * {{{ + * object Impls { def foo_impl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ... } + * }}} + */ val value: T /** case class accessories */ @@ -27,6 +84,12 @@ trait Exprs { self: Universe => override def toString = "Expr["+staticType+"]("+tree+")" } + /** + * Constructor/Extractor for Expr. + * + * Can be useful, when having a tree and wanting to splice it in reify call, + * in which case the tree first needs to be wrapped in an expr. + */ object Expr { def apply[T: WeakTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec) def unapply[T](expr: Expr[T]): Option[Tree] = Some(expr.tree) @@ -41,7 +104,7 @@ trait Exprs { self: Universe => lazy val tree: Tree = treec(mirror) lazy val staticType: Type = implicitly[WeakTypeTag[T]].tpe - def actualType: Type = treeType(tree) + def actualType: Type = tree.tpe def splice: T = throw new UnsupportedOperationException(""" |the function you're calling has not been spliced by the compiler. @@ -54,11 +117,11 @@ trait Exprs { self: Universe => |if you want to get a value of the underlying expression, add scala-compiler.jar to the classpath, |import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin) - private def writeReplace(): AnyRef = new SerializedExpr(treec, implicitly[WeakTypeTag[T]].in(scala.reflect.basis.rootMirror)) + private def writeReplace(): AnyRef = new SerializedExpr(treec, implicitly[WeakTypeTag[T]].in(ru.rootMirror)) } } -private[scala] class SerializedExpr(var treec: TreeCreator, var tag: scala.reflect.basis.WeakTypeTag[_]) extends Serializable { +private[scala] class SerializedExpr(var treec: TreeCreator, var tag: ru.WeakTypeTag[_]) extends Serializable { private def writeObject(out: java.io.ObjectOutputStream): Unit = { out.writeObject(treec) out.writeObject(tag) @@ -66,11 +129,11 @@ private[scala] class SerializedExpr(var treec: TreeCreator, var tag: scala.refle private def readObject(in: java.io.ObjectInputStream): Unit = { treec = in.readObject().asInstanceOf[TreeCreator] - tag = in.readObject().asInstanceOf[scala.reflect.basis.WeakTypeTag[_]] + tag = in.readObject().asInstanceOf[ru.WeakTypeTag[_]] } private def readResolve(): AnyRef = { - import scala.reflect.basis._ + import ru._ Expr(rootMirror, treec)(tag) } }
\ No newline at end of file diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index fdd43f1883..599c4ca426 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -3,10 +3,16 @@ package api import scala.language.implicitConversions -trait FlagSets extends base.FlagSets { self: Universe => +trait FlagSets { self: Universe => + /** An abstract type representing sets of flags (like private, final, etc.) that apply to definition trees and symbols */ type FlagSet + /** A tag that preserves the identity of the `FlagSet` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FlagSetTag: ClassTag[FlagSet] + trait FlagOps extends Any { def | (right: FlagSet): FlagSet } @@ -99,4 +105,7 @@ trait FlagSets extends base.FlagSets { self: Universe => /** Flag indicating that tree represents a variable or a member initialized to the default value */ val DEFAULTINIT: FlagSet } + + /** The empty set of flags */ + val NoFlags: FlagSet } diff --git a/src/reflect/scala/reflect/api/JavaUniverse.scala b/src/reflect/scala/reflect/api/JavaUniverse.scala index f2388433c4..ba38381561 100644 --- a/src/reflect/scala/reflect/api/JavaUniverse.scala +++ b/src/reflect/scala/reflect/api/JavaUniverse.scala @@ -1,7 +1,7 @@ package scala.reflect package api -trait JavaUniverse extends Universe with Mirrors with TagInterop { self => +trait JavaUniverse extends Universe with Mirrors { self => type RuntimeClass = java.lang.Class[_] @@ -13,5 +13,28 @@ trait JavaUniverse extends Universe with Mirrors with TagInterop { self => } def runtimeMirror(cl: ClassLoader): Mirror -} + override def typeTagToManifest[T: ClassTag](mirror0: Any, tag: Universe # TypeTag[T]): Manifest[T] = { + // SI-6239: make this conversion more precise + val mirror = mirror0.asInstanceOf[Mirror] + val runtimeClass = mirror.runtimeClass(tag.in(mirror).tpe) + Manifest.classType(runtimeClass).asInstanceOf[Manifest[T]] + } + + override def manifestToTypeTag[T](mirror0: Any, manifest: Manifest[T]): Universe # TypeTag[T] = + TypeTag(mirror0.asInstanceOf[Mirror], new TypeCreator { + def apply[U <: Universe with Singleton](mirror: MirrorOf[U]): U # Type = { + mirror.universe match { + case ju: JavaUniverse => + val jm = mirror.asInstanceOf[ju.Mirror] + val sym = jm.classSymbol(manifest.erasure) + val tpe = + if (manifest.typeArguments.isEmpty) sym.toType + else ju.appliedType(sym.toTypeConstructor, manifest.typeArguments map (targ => ju.manifestToTypeTag(jm, targ)) map (_.in(jm).tpe)) + tpe.asInstanceOf[U # Type] + case u => + u.manifestToTypeTag(mirror.asInstanceOf[u.Mirror], manifest).in(mirror).tpe + } + } + }) +} diff --git a/src/library/scala/reflect/base/MirrorOf.scala b/src/reflect/scala/reflect/api/MirrorOf.scala index 1e9619d062..cd5641e692 100644 --- a/src/library/scala/reflect/base/MirrorOf.scala +++ b/src/reflect/scala/reflect/api/MirrorOf.scala @@ -1,14 +1,33 @@ package scala.reflect -package base +package api -abstract class MirrorOf[U <: base.Universe with Singleton] { - /** .. */ +/** + * The base interface for all mirrors. + * + * @tparam U the type of the universe this mirror belongs to. + * + * This is defined outside the reflection universe cake pattern implementation + * so that it can be referenced from outside. For example TypeCreator and TreeCreator + * reference MirrorOf and also need to be defined outside the cake as they are + * used by type tags, which can be migrated between different universes and consequently + * cannot be bound to a fixed one. + * + * @see [[Mirrors]] + */ +abstract class MirrorOf[U <: Universe with Singleton] { + /** The universe this mirror belongs to. */ val universe: U - /** .. */ + /** The class symbol of the `_root_` package */ def RootClass: U#ClassSymbol + + /** The module symbol of the `_root_` package */ def RootPackage: U#ModuleSymbol + + /** The module class symbol of the default (unnamed) package */ def EmptyPackageClass: U#ClassSymbol + + /** The module symbol of the default (unnamed) package */ def EmptyPackage: U#ModuleSymbol /** The symbol corresponding to the globally accessible class with the diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index 8c4c423221..c935533027 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -1,7 +1,23 @@ package scala.reflect package api -trait Mirrors extends base.Mirrors { self: Universe => +/** + * Defines a type hierarchy for mirrors. + * + * Every universe has one or more mirrors. A mirror defines a hierarchy of symbols starting with the root package `_root_` + * and provides methods to locate and define classes and singleton objects in that hierarchy. + * + * On the JVM, there is a one to one correspondance between class loaders and mirrors. + */ +trait Mirrors { self: Universe => + + /** The base type of all mirrors of this universe */ + type Mirror >: Null <: MirrorOf[self.type] + + /** The root mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`, + * `Nothing`, `Null`, and all classes loaded from scala-library, which are shared across all mirrors within the enclosing universe. + */ + val rootMirror: Mirror type RuntimeClass >: Null diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala index d6868c26ab..e8665ca736 100644 --- a/src/reflect/scala/reflect/api/Names.scala +++ b/src/reflect/scala/reflect/api/Names.scala @@ -2,23 +2,52 @@ package scala.reflect package api /** A trait that manages names. - * A name is a string in one of two name universes: terms and types. - * The same string can be a name in both universes. - * Two names are equal if they represent the same string and they are - * members of the same universe. * - * Names are interned. That is, for two names `name11 and `name2`, - * `name1 == name2` implies `name1 eq name2`. + * @see TermName + * @see TypeName */ -trait Names extends base.Names { +trait Names { + // Intentionally no implicit from String => Name. + implicit def stringToTermName(s: String): TermName = newTermName(s) + implicit def stringToTypeName(s: String): TypeName = newTypeName(s) - /** The abstract type of names */ + /** + * The abstract type of names + * + * A Name wraps a string as the name for either a type ([[TypeName]]) of a term ([[TermName]]). + * Two names are equal, if the wrapped string are equal and they are either both `TypeName` or both `TermName`. + * The same string can co-exist as a `TypeName` and a `TermName`, but they would not be equal. + * Names are interned. That is, for two names `name11 and `name2`, + * `name1 == name2` implies `name1 eq name2`. + * + * One of the reasons for the existence of names rather than plain strings is being more explicit about what is a name and if it represents a type or a term. + */ type Name >: Null <: NameApi + implicit val NameTag: ClassTag[Name] + + /** The abstract type of names representing terms */ + type TypeName >: Null <: Name + implicit val TypeNameTag: ClassTag[TypeName] - /** The extended API of names that's supported on reflect mirror via an + /** The abstract type of names representing types */ + type TermName >: Null <: Name + implicit val TermNameTag: ClassTag[TermName] + + /** The API of names that's supported on reflect mirror via an * implicit conversion in reflect.ops */ - abstract class NameApi extends NameBase { + abstract class NameApi { + /** Checks wether the name is a a term name */ + def isTermName: Boolean + + /** Checks wether the name is a a type name */ + def isTypeName: Boolean + + /** Returns a term name that wraps the same string as `this` */ + def toTermName: TermName + + /** Returns a type name that wraps the same string as `this` */ + def toTypeName: TypeName /** Replaces all occurrences of \$op_names in this name by corresponding operator symbols. * Example: `foo_\$plus\$eq` becomes `foo_+=` @@ -38,4 +67,20 @@ trait Names extends base.Names { */ def encodedName: Name } + + /** Create a new term name. + */ + def newTermName(s: String): TermName + + /** Creates a new type name. + */ + def newTypeName(s: String): TypeName + + /** Wraps the empty string. Can be used as the null object for term name. + */ + def EmptyTermName: TermName = newTermName("") + + /** Wraps the empty string. Can be used as the null object for type name. + */ + def EmptyTypeName: TypeName = EmptyTermName.toTypeName } diff --git a/src/reflect/scala/reflect/api/Positions.scala b/src/reflect/scala/reflect/api/Positions.scala index 5e8d958f02..0eddc88fc4 100644 --- a/src/reflect/scala/reflect/api/Positions.scala +++ b/src/reflect/scala/reflect/api/Positions.scala @@ -1,12 +1,25 @@ package scala.reflect package api -trait Positions extends base.Positions { +/** + * Defines the type hierachy for positions. + * + * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here. + */ +trait Positions { self: Universe => /** .. */ type Position >: Null <: PositionApi { type Pos = Position } + /** A tag that preserves the identity of the `Position` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val PositionTag: ClassTag[Position] + + /** A special "missing" position. */ + val NoPosition: Position + /** Assigns a given position to all position-less nodes of a given AST. */ def atPos[T <: Tree](pos: Position)(tree: T): T diff --git a/src/library/scala/reflect/base/Scopes.scala b/src/reflect/scala/reflect/api/Scopes.scala index a388fdc392..d30da07ad5 100644 --- a/src/library/scala/reflect/base/Scopes.scala +++ b/src/reflect/scala/reflect/api/Scopes.scala @@ -1,24 +1,33 @@ package scala.reflect -package base +package api +/** + * Defines the type hierachy for scopes. + * + * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here. + */ trait Scopes { self: Universe => - type Scope >: Null <: ScopeBase + /** The base type of all scopes. A scope object generally maps names to symbols available in the current lexical scope. + * Scopes can be nested. This base type, however, only exposes a minimal interface, representing a scope as an iterable of symbols. + */ + type Scope >: Null <: ScopeApi - /** The base API that all scopes support */ - trait ScopeBase extends Iterable[Symbol] + /** The API that all scopes support */ + trait ScopeApi extends Iterable[Symbol] /** A tag that preserves the identity of the `Scope` abstract type from erasure. * Can be used for pattern matching, instance tests, serialization and likes. */ implicit val ScopeTag: ClassTag[Scope] - type MemberScope >: Null <: Scope with MemberScopeBase + /** The type of member scopes, as in class definitions, for example. */ + type MemberScope >: Null <: Scope with MemberScopeApi - /** The base API that all member scopes support */ - trait MemberScopeBase extends ScopeBase { + /** The API that all member scopes support */ + trait MemberScopeApi extends ScopeApi { /** Sorts the symbols included in this scope so that: - * 1) Symbols appear the linearization order of their owners. + * 1) Symbols appear in the linearization order of their owners. * 2) Symbols with the same owner appear in reverse order of their declarations. * 3) Synthetic members (e.g. getters/setters for vals/vars) might appear in arbitrary order. */ @@ -30,12 +39,12 @@ trait Scopes { self: Universe => */ implicit val MemberScopeTag: ClassTag[MemberScope] - /** Create a new scope */ + /** Create a new scope. */ def newScope: Scope - /** Create a new scope nested in another one with which it shares its elements */ + /** Create a new scope nested in another one with which it shares its elements. */ def newNestedScope(outer: Scope): Scope - /** Create a new scope with given initial elements */ + /** Create a new scope with the given initial elements. */ def newScopeWith(elems: Symbol*): Scope }
\ No newline at end of file diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala index c6f02f1a33..03f2a6b0aa 100644 --- a/src/reflect/scala/reflect/api/StandardDefinitions.scala +++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala @@ -5,12 +5,59 @@ package scala.reflect package api -trait StandardDefinitions extends base.StandardDefinitions { +/** + * Defines standard symbols and types. + */ +trait StandardDefinitions { self: Universe => + /** A value containing all standard defnitions. */ val definitions: DefinitionsApi - trait DefinitionsApi extends DefinitionsBase { + /** Defines standard symbols (and types via its base trait). */ + trait DefinitionsApi extends StandardTypes { + /** The class symbol of package `scala`. */ + def ScalaPackageClass: ClassSymbol + + /** The module class symbol of package `scala`. */ + def ScalaPackage: ModuleSymbol + + // top types + def AnyClass : ClassSymbol + def AnyValClass: ClassSymbol + def ObjectClass: ClassSymbol + def AnyRefClass: TypeSymbol + + // bottom types + def NullClass : ClassSymbol + def NothingClass: ClassSymbol + + // the scala value classes + def UnitClass : ClassSymbol + def ByteClass : ClassSymbol + def ShortClass : ClassSymbol + def CharClass : ClassSymbol + def IntClass : ClassSymbol + def LongClass : ClassSymbol + def FloatClass : ClassSymbol + def DoubleClass : ClassSymbol + def BooleanClass: ClassSymbol + + /** The class symbol of class `String`. */ + def StringClass : ClassSymbol + + /** The class symbol of class `Class`. */ + def ClassClass : ClassSymbol + + /** The class symbol of class `Array`. */ + def ArrayClass : ClassSymbol + + /** The class symbol of class `List`. */ + def ListClass : ClassSymbol + + /** The module symbol of `scala.Predef`. */ + def PredefModule: ModuleSymbol + def JavaLangPackageClass: ClassSymbol def JavaLangPackage: ModuleSymbol def ArrayModule: ModuleSymbol @@ -45,4 +92,52 @@ trait StandardDefinitions extends base.StandardDefinitions { def ScalaPrimitiveValueClasses: List[ClassSymbol] def ScalaNumericValueClasses: List[ClassSymbol] } + + /** Defines standard types. */ + trait StandardTypes { + /** The `Type` of type `Unit`. */ + val UnitTpe: Type + + /** The `Type` of primitive type `Byte`. */ + val ByteTpe: Type + + /** The `Type` of primitive type `Short`. */ + val ShortTpe: Type + + /** The `Type` of primitive type `Char`. */ + val CharTpe: Type + + /** The `Type` of primitive type `Int`. */ + val IntTpe: Type + + /** The `Type` of primitive type `Long`. */ + val LongTpe: Type + + /** The `Type` of primitive type `Float`. */ + val FloatTpe: Type + + /** The `Type` of primitive type `Double`. */ + val DoubleTpe: Type + + /** The `Type` of primitive type `Boolean`. */ + val BooleanTpe: Type + + /** The `Type` of type `Any`. */ + val AnyTpe: Type + + /** The `Type` of type `AnyVal`. */ + val AnyValTpe: Type + + /** The `Type` of type `AnyRef`. */ + val AnyRefTpe: Type + + /** The `Type` of type `Object`. */ + val ObjectTpe: Type + + /** The `Type` of type `Nothing`. */ + val NothingTpe: Type + + /** The `Type` of type `Null`. */ + val NullTpe: Type + } } diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala index 65d87ad7f0..354a9f9328 100644 --- a/src/reflect/scala/reflect/api/StandardNames.scala +++ b/src/reflect/scala/reflect/api/StandardNames.scala @@ -5,26 +5,40 @@ package scala.reflect package api -// Q: I have a pretty name. Where do I put it - into base.StandardNames or into api.StandardNames? -// A: <see base.StandardNames> +// Q: I have a pretty name. Can I put it here? +// A: Is it necessary to construct trees (like EMPTY or WILDCARD_STAR)? If yes, then sure. +// Is it necessary to perform reflection (like ERROR or LOCAL_SUFFIX_STRING)? If yes, then sure. +// Otherwise you'd better not - reflection API should stay minimalistic. -trait StandardNames extends base.StandardNames { +// TODO: document better +/** + * Names necessary to create Scala trees. + */ +trait StandardNames { self: Universe => val nme: TermNamesApi val tpnme: TypeNamesApi - trait NamesApi extends NamesBase { + trait NamesApi { + type NameType >: Null <: Name + val WILDCARD: NameType val ROOT: NameType val EMPTY: NameType val ERROR: NameType val PACKAGE: NameType } - trait TermNamesApi extends NamesApi with TermNamesBase { + trait TermNamesApi extends NamesApi { + type NameType = TermName + val CONSTRUCTOR: NameType + val ROOTPKG: NameType val LOCAL_SUFFIX_STRING: String } - trait TypeNamesApi extends NamesApi with TypeNamesBase { + trait TypeNamesApi extends NamesApi { + type NameType = TypeName + val EMPTY: NameType + val WILDCARD_STAR: NameType } } diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 0c4be4f7e1..78345e27f2 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -1,24 +1,216 @@ package scala.reflect package api -trait Symbols extends base.Symbols { self: Universe => - - override type Symbol >: Null <: SymbolApi - override type TypeSymbol >: Null <: Symbol with TypeSymbolApi - override type TermSymbol >: Null <: Symbol with TermSymbolApi - override type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi - override type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolApi - override type ClassSymbol >: Null <: TypeSymbol with ClassSymbolApi - override type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolApi - override type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi +/** + * Defines the type hierachy for symbols + * + * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here. + */ +trait Symbols { self: Universe => + + /** The type of symbols representing declarations */ + type Symbol >: Null <: SymbolApi + + /** A tag that preserves the identity of the `Symbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SymbolTag: ClassTag[Symbol] + + /** The type of type symbols representing type, class, and trait declarations, + * as well as type parameters + */ + type TypeSymbol >: Null <: Symbol with TypeSymbolApi + + /** A tag that preserves the identity of the `TypeSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeSymbolTag: ClassTag[TypeSymbol] + + /** The type of term symbols representing val, var, def, and object declarations as + * well as packages and value parameters. + */ + type TermSymbol >: Null <: Symbol with TermSymbolApi + + /** A tag that preserves the identity of the `TermSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TermSymbolTag: ClassTag[TermSymbol] + + /** The type of method symbols representing def declarations */ + type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi + + /** A tag that preserves the identity of the `MethodSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MethodSymbolTag: ClassTag[MethodSymbol] + + /** The type of module symbols representing object declarations */ + type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolApi + + /** A tag that preserves the identity of the `ModuleSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ModuleSymbolTag: ClassTag[ModuleSymbol] + + /** The type of class symbols representing class and trait definitions */ + type ClassSymbol >: Null <: TypeSymbol with ClassSymbolApi + + /** A tag that preserves the identity of the `ClassSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ClassSymbolTag: ClassTag[ClassSymbol] + + /** The type of free terms introduced by reification */ + type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolApi + + /** A tag that preserves the identity of the `FreeTermSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol] + + /** The type of free types introduced by reification */ + type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi + + /** A tag that preserves the identity of the `FreeTypeSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FreeTypeSymbolTag: ClassTag[FreeTypeSymbol] + + /** A special "missing" symbol */ + val NoSymbol: Symbol /** The API of symbols */ - trait SymbolApi extends SymbolBase { this: Symbol => + trait SymbolApi { this: Symbol => + + /** The owner of this symbol. This is the symbol + * that directly contains the current symbol's definition. + * The `NoSymbol` symbol does not have an owner, and calling this method + * on one causes an internal error. + * The owner of the Scala root class [[scala.reflect.api.MirrorOf.RootClass]] + * and the Scala root object [[scala.reflect.api.MirrorOf.RootPackage]] is `NoSymbol`. + * Every other symbol has a chain of owners that ends in + * [[scala.reflect.api.MirrorOf.RootClass]]. + */ + def owner: Symbol + + /** The type of the symbol name. + * Can be either `TermName` or `TypeName` depending on whether this is a `TermSymbol` or a `TypeSymbol`. + * + * Type name namespaces do not intersect with term name namespaces. + * This fact is reflected in different types for names of `TermSymbol` and `TypeSymbol`. + */ + type NameType >: Null <: Name + + /** The name of the symbol as a member of the `Name` type. + */ + def name: Name + + /** The encoded full path name of this symbol, where outer names and inner names + * are separated by periods. + */ + def fullName: String + + /** Does this symbol represent the definition of a type? + * Note that every symbol is either a term or a type. + * So for every symbol `sym` (except for `NoSymbol`), + * either `sym.isTerm` is true or `sym.isType` is true. + */ + def isType: Boolean = false + + /** This symbol cast to a TypeSymbol. + * @throws ScalaReflectionException if `isType` is false. + */ + def asType: TypeSymbol = throw new ScalaReflectionException(s"$this is not a type") + + /** Does this symbol represent the definition of a term? + * Note that every symbol is either a term or a type. + * So for every symbol `sym` (except for `NoSymbol`), + * either `sym.isTerm` is true or `sym.isTerm` is true. + */ + def isTerm: Boolean = false + + /** This symbol cast to a TermSymbol. + * @throws ScalaReflectionException if `isTerm` is false. + */ + def asTerm: TermSymbol = throw new ScalaReflectionException(s"$this is not a term") + + /** Does this symbol represent the definition of a method? + * If yes, `isTerm` is also guaranteed to be true. + */ + def isMethod: Boolean = false + + /** This symbol cast to a MethodSymbol. + * @throws ScalaReflectionException if `isMethod` is false. + */ + def asMethod: MethodSymbol = { + def overloadedMsg = + "encapsulates multiple overloaded alternatives and cannot be treated as a method. "+ + "Consider invoking `<offending symbol>.asTerm.alternatives` and manually picking the required method" + def vanillaMsg = "is not a method" + val msg = if (isOverloadedMethod) overloadedMsg else vanillaMsg + throw new ScalaReflectionException(s"$this $msg") + } + + /** Used to provide a better error message for `asMethod` */ + protected def isOverloadedMethod = false + + /** Does this symbol represent the definition of a module (i.e. it + * results from an object definition?). + * If yes, `isTerm` is also guaranteed to be true. + */ + def isModule: Boolean = false + + /** This symbol cast to a ModuleSymbol defined by an object definition. + * @throws ScalaReflectionException if `isModule` is false. + */ + def asModule: ModuleSymbol = throw new ScalaReflectionException(s"$this is not a module") + + /** Does this symbol represent the definition of a class or trait? + * If yes, `isType` is also guaranteed to be true. + */ + def isClass: Boolean = false + + /** Does this symbol represent the definition of a class implicitly associated + * with an object definition (module class in scala compiler parlance). + * If yes, `isType` is also guaranteed to be true. + */ + def isModuleClass: Boolean = false + + /** This symbol cast to a ClassSymbol representing a class or trait. + * @throws ScalaReflectionException if `isClass` is false. + */ + def asClass: ClassSymbol = throw new ScalaReflectionException(s"$this is not a class") + + /** Does this symbol represent a free term captured by reification? + * If yes, `isTerm` is also guaranteed to be true. + */ + def isFreeTerm: Boolean = false + + /** This symbol cast to a free term symbol. + * @throws ScalaReflectionException if `isFreeTerm` is false. + */ + def asFreeTerm: FreeTermSymbol = throw new ScalaReflectionException(s"$this is not a free term") + + /** Does this symbol represent a free type captured by reification? + * If yes, `isType` is also guaranteed to be true. + */ + def isFreeType: Boolean = false + + /** This symbol cast to a free type symbol. + * @throws ScalaReflectionException if `isFreeType` is false. + */ + def asFreeType: FreeTypeSymbol = throw new ScalaReflectionException(s"$this is not a free type") + + def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol + def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol) + def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol + def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol + def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol /** Source file if this symbol is created during this compilation run, * or a class file if this symbol is loaded from a *.class or *.jar. */ - def associatedFile: scala.tools.nsc.io.AbstractFile + def associatedFile: scala.reflect.io.AbstractFile /** A list of annotations attached to this Symbol. */ @@ -195,7 +387,14 @@ trait Symbols extends base.Symbols { self: Universe => } /** The API of term symbols */ - trait TermSymbolApi extends SymbolApi with TermSymbolBase { this: TermSymbol => + trait TermSymbolApi extends SymbolApi { this: TermSymbol => + /** Term symbols have their names of type `TermName`. + */ + final type NameType = TermName + + final override def isTerm = true + final override def asTerm = this + /** Is this symbol introduced as `val`? */ def isVal: Boolean @@ -269,7 +468,41 @@ trait Symbols extends base.Symbols { self: Universe => } /** The API of type symbols */ - trait TypeSymbolApi extends SymbolApi with TypeSymbolBase { this: TypeSymbol => + trait TypeSymbolApi extends SymbolApi { this: TypeSymbol => + /** Type symbols have their names of type `TypeName`. + */ + final type NameType = TypeName + + /** The type constructor corresponding to this type symbol. + * This is different from `toType` in that type parameters + * are part of results of `toType`, but not of `toTypeConstructor`. + * + * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol + * `C`. Then `C.toType` is the type `C[T]`, but `C.toTypeConstructor` is `C`. + */ + def toTypeConstructor: Type + + /** A type reference that refers to this type symbol seen + * as a member of given type `site`. + */ + def toTypeIn(site: Type): Type + + /** A type reference that refers to this type symbol + * Note if symbol is a member of a class, one almost always is interested + * in `asTypeIn` with a site type instead. + * + * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol + * `C`. Then `C.toType` is the type `C[T]`. + * + * By contrast, `C.typeSignature` would be a type signature of form + * `PolyType(ClassInfoType(...))` that describes type parameters, value + * parameters, parent types, and members of `C`. + */ + def toType: Type + + final override def isType = true + final override def asType = this + /** Is the type parameter represented by this symbol contravariant? */ def isContravariant : Boolean @@ -300,7 +533,10 @@ trait Symbols extends base.Symbols { self: Universe => } /** The API of method symbols */ - trait MethodSymbolApi extends TermSymbolApi with MethodSymbolBase { this: MethodSymbol => + trait MethodSymbolApi extends TermSymbolApi { this: MethodSymbol => + final override def isMethod = true + final override def asMethod = this + /** Does this method represent a constructor? * * If `owner` is a class, then this is a vanilla JVM constructor. @@ -331,11 +567,23 @@ trait Symbols extends base.Symbols { self: Universe => } /** The API of module symbols */ - trait ModuleSymbolApi extends TermSymbolApi with ModuleSymbolBase { this: ModuleSymbol => + trait ModuleSymbolApi extends TermSymbolApi { this: ModuleSymbol => + /** The class implicitly associated with the object definition. + * One can go back from a module class to the associated module symbol + * by inspecting its `selfType.termSymbol`. + */ + def moduleClass: Symbol // needed for tree traversals + // when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life + + final override def isModule = true + final override def asModule = this } /** The API of class symbols */ - trait ClassSymbolApi extends TypeSymbolApi with ClassSymbolBase { this: ClassSymbol => + trait ClassSymbolApi extends TypeSymbolApi { this: ClassSymbol => + final override def isClass = true + final override def asClass = this + /** Does this symbol represent the definition of a primitive class? * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? @@ -398,7 +646,10 @@ trait Symbols extends base.Symbols { self: Universe => } /** The API of free term symbols */ - trait FreeTermSymbolApi extends TermSymbolApi with FreeTermSymbolBase { this: FreeTermSymbol => + trait FreeTermSymbolApi extends TermSymbolApi { this: FreeTermSymbol => + final override def isFreeTerm = true + final override def asFreeTerm = this + /** The place where this symbol has been spawned */ def origin: String @@ -407,7 +658,10 @@ trait Symbols extends base.Symbols { self: Universe => } /** The API of free term symbols */ - trait FreeTypeSymbolApi extends TypeSymbolApi with FreeTypeSymbolBase { this: FreeTypeSymbol => + trait FreeTypeSymbolApi extends TypeSymbolApi { this: FreeTypeSymbol => + final override def isFreeType = true + final override def asFreeType = this + /** The place where this symbol has been spawned */ def origin: String } diff --git a/src/reflect/scala/reflect/api/TagInterop.scala b/src/reflect/scala/reflect/api/TagInterop.scala index 5ab085741e..fc0558d717 100644 --- a/src/reflect/scala/reflect/api/TagInterop.scala +++ b/src/reflect/scala/reflect/api/TagInterop.scala @@ -1,32 +1,27 @@ package scala.reflect package api -import scala.reflect.base.TypeCreator -import scala.reflect.base.{Universe => BaseUniverse} +trait TagInterop { self: Universe => + // TODO `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work + // if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala -trait TagInterop { self: JavaUniverse => + /** + * Convert a typetag to a pre `Scala-2.10` manifest. + * For example + * {{{ + * typeTagToManifest( scala.reflect.runtime.currentMirror, implicitly[TypeTag[String]] ) + * }}} + */ + def typeTagToManifest[T: ClassTag](mirror: Any, tag: Universe#TypeTag[T]): Manifest[T] = + throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use a JavaUniverse, e.g. the scala.reflect.runtime.universe.") - override def typeTagToManifest[T: ClassTag](mirror0: Any, tag: base.Universe # TypeTag[T]): Manifest[T] = { - // SI-6239: make this conversion more precise - val mirror = mirror0.asInstanceOf[Mirror] - val runtimeClass = mirror.runtimeClass(tag.in(mirror).tpe) - Manifest.classType(runtimeClass).asInstanceOf[Manifest[T]] - } - - override def manifestToTypeTag[T](mirror0: Any, manifest: Manifest[T]): base.Universe # TypeTag[T] = - TypeTag(mirror0.asInstanceOf[Mirror], new TypeCreator { - def apply[U <: BaseUniverse with Singleton](mirror: MirrorOf[U]): U # Type = { - mirror.universe match { - case ju: JavaUniverse => - val jm = mirror.asInstanceOf[ju.Mirror] - val sym = jm.classSymbol(manifest.erasure) - val tpe = - if (manifest.typeArguments.isEmpty) sym.toType - else ju.appliedType(sym.toTypeConstructor, manifest.typeArguments map (targ => ju.manifestToTypeTag(jm, targ)) map (_.in(jm).tpe)) - tpe.asInstanceOf[U # Type] - case u => - u.manifestToTypeTag(mirror.asInstanceOf[u.Mirror], manifest).in(mirror).tpe - } - } - }) + /** + * Convert a pre `Scala-2.10` manifest to a typetag. + * For example + * {{{ + * manifestToTypeTag( scala.reflect.runtime.currentMirror, implicitly[Manifest[String]] ) + * }}} + */ + def manifestToTypeTag[T](mirror: Any, manifest: Manifest[T]): Universe#TypeTag[T] = + throw new UnsupportedOperationException("This universe does not support manifest -> tag conversions. Use a JavaUniverse, e.g. the scala.reflect.runtime.universe.") } diff --git a/src/reflect/scala/reflect/api/TreeCreator.scala b/src/reflect/scala/reflect/api/TreeCreator.scala new file mode 100644 index 0000000000..0c8701775c --- /dev/null +++ b/src/reflect/scala/reflect/api/TreeCreator.scala @@ -0,0 +1,26 @@ +package scala.reflect +package api + +/** A mirror-aware factory for trees. + * + * In the reflection API, artifacts are specific to universes and + * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors. + * + * Therefore to build a tree one needs to know a universe that the tree is going to be bound to + * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int` + * points to a core class `Int` from scala-library.jar). + * + * `TreeCreator` implements this notion by providing a standalone tree factory. + * + * This is immediately useful for reification. When the compiler reifies an expression, + * the end result needs to make sense in any mirror. That's because the compiler knows + * the universe it's reifying an expression into (specified by the target of the `reify` call), + * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM + * it doesn't know what classloader use to resolve symbolic names in the reifee). + * + * Due to a typechecker restriction (no eta-expansion for dependent method types), + * `TreeCreator` can't have a functional type, so it's implemented as class with an apply method. + */ +abstract class TreeCreator { + def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Tree +} diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index e46a977be8..1f15ee6070 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -6,12 +6,75 @@ package scala.reflect package api // Syncnote: Trees are currently not thread-safe. -trait Trees extends base.Trees { self: Universe => +trait Trees { self: Universe => + + /** Tree is the basis for scala's abstract syntax. The nodes are + * implemented as case classes, and the parameters which initialize + * a given tree are immutable: however Trees have several mutable + * fields which are manipulated in the course of typechecking, + * including pos, symbol, and tpe. + * + * Newly instantiated trees have tpe set to null (though it + * may be set immediately thereafter depending on how it is + * constructed.) When a tree is passed to the typer, typically via + * `typer.typed(tree)`, under normal circumstances the tpe must be + * null or the typer will ignore it. Furthermore, the typer is not + * required to return the same tree it was passed. + * + * Trees can be easily traversed with e.g. foreach on the root node; + * for a more nuanced traversal, subclass Traverser. Transformations + * can be considerably trickier: see the numerous subclasses of + * Transformer found around the compiler. + * + * Copying Trees should be done with care depending on whether + * it needs be done lazily or strictly (see LazyTreeCopier and + * StrictTreeCopier) and on whether the contents of the mutable + * fields should be copied. The tree copiers will copy the mutable + * attributes to the new tree; calling Tree#duplicate will copy + * symbol and tpe, but all the positions will be focused. + * + * Trees can be coarsely divided into four mutually exclusive categories: + * + * - TermTrees, representing terms + * - TypTrees, representing types. Note that is `TypTree`, not `TypeTree`. + * - SymTrees, which may represent types or terms. + * - Other Trees, which have none of those as parents. + * + * SymTrees include important nodes Ident and Select, which are + * used as both terms and types; they are distinguishable based on + * whether the Name is a TermName or TypeName. The correct way + * to test any Tree for a type or a term are the `isTerm`/`isType` + * methods on Tree. + * + * "Others" are mostly syntactic or short-lived constructs. Examples + * include CaseDef, which wraps individual match cases: they are + * neither terms nor types, nor do they carry a symbol. Another + * example is Parens, which is eliminated during parsing. + */ + type Tree >: Null <: TreeApi - override type Tree >: Null <: TreeApi + /** A tag that preserves the identity of the `Tree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TreeTag: ClassTag[Tree] - /** ... */ - trait TreeApi extends TreeBase { this: Tree => + /** The API that all trees support */ + trait TreeApi extends Product { this: Tree => + // TODO + /** ... */ + def isDef: Boolean + + // TODO + /** ... */ + def isEmpty: Boolean + + /** The canonical way to test if a Tree represents a term. + */ + def isTerm: Boolean + + /** The canonical way to test if a Tree represents a type. + */ + def isType: Boolean /** ... */ def pos: Position @@ -107,37 +170,83 @@ trait Trees extends base.Trees { self: Universe => * in this tree will be found when searching by position). */ def duplicate: this.type + + /** Obtains string representation of a tree */ + override def toString: String = treeToString(this) } - override protected def treeType(tree: Tree) = tree.tpe + /** Obtains string representation of a tree */ + protected def treeToString(tree: Tree): String - override type TermTree >: Null <: Tree with TermTreeApi + /** The empty tree */ + val EmptyTree: Tree + + /** A tree for a term. Not all trees representing terms are TermTrees; use isTerm + * to reliably identify terms. + */ + type TermTree >: Null <: AnyRef with Tree with TermTreeApi + + /** A tag that preserves the identity of the `TermTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TermTreeTag: ClassTag[TermTree] /** The API that all term trees support */ trait TermTreeApi extends TreeApi { this: TermTree => } - override type TypTree >: Null <: Tree with TypTreeApi + /** A tree for a type. Not all trees representing types are TypTrees; use isType + * to reliably identify types. + */ + type TypTree >: Null <: AnyRef with Tree with TypTreeApi + + /** A tag that preserves the identity of the `TypTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypTreeTag: ClassTag[TypTree] /** The API that all typ trees support */ trait TypTreeApi extends TreeApi { this: TypTree => } - override type SymTree >: Null <: Tree with SymTreeApi + /** A tree with a mutable symbol field, initialized to NoSymbol. + */ + type SymTree >: Null <: AnyRef with Tree with SymTreeApi + + /** A tag that preserves the identity of the `SymTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SymTreeTag: ClassTag[SymTree] /** The API that all sym trees support */ trait SymTreeApi extends TreeApi { this: SymTree => def symbol: Symbol } - override type NameTree >: Null <: Tree with NameTreeApi + /** A tree with a name - effectively, a DefTree or RefTree. + */ + type NameTree >: Null <: AnyRef with Tree with NameTreeApi + + /** A tag that preserves the identity of the `NameTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val NameTreeTag: ClassTag[NameTree] /** The API that all name trees support */ trait NameTreeApi extends TreeApi { this: NameTree => def name: Name } - override type RefTree >: Null <: SymTree with NameTree with RefTreeApi + /** A tree which references a symbol-carrying entity. + * References one, as opposed to defining one; definitions + * are in DefTrees. + */ + type RefTree >: Null <: SymTree with NameTree with RefTreeApi + + /** A tag that preserves the identity of the `RefTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val RefTreeTag: ClassTag[RefTree] /** The API that all ref trees support */ trait RefTreeApi extends SymTreeApi with NameTreeApi { this: RefTree => @@ -145,21 +254,56 @@ trait Trees extends base.Trees { self: Universe => def name: Name } - override type DefTree >: Null <: SymTree with NameTree with DefTreeApi + /** A tree which defines a symbol-carrying entity. + */ + type DefTree >: Null <: SymTree with NameTree with DefTreeApi + + /** A tag that preserves the identity of the `DefTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val DefTreeTag: ClassTag[DefTree] /** The API that all def trees support */ trait DefTreeApi extends SymTreeApi with NameTreeApi { this: DefTree => def name: Name } - override type MemberDef >: Null <: DefTree with MemberDefApi + /** Common base class for all member definitions: types, classes, + * objects, packages, vals and vars, defs. + */ + type MemberDef >: Null <: DefTree with MemberDefApi + + /** A tag that preserves the identity of the `MemberDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MemberDefTag: ClassTag[MemberDef] /** The API that all member defs support */ trait MemberDefApi extends DefTreeApi { this: MemberDef => def mods: Modifiers } - override type PackageDef >: Null <: MemberDef with PackageDefApi + /** A packaging, such as `package pid { stats }` + */ + type PackageDef >: Null <: MemberDef with PackageDefApi + + /** A tag that preserves the identity of the `PackageDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val PackageDefTag: ClassTag[PackageDef] + + /** The constructor/deconstructor for `PackageDef` instances. */ + val PackageDef: PackageDefExtractor + + /** An extractor class to create and pattern match with syntax `PackageDef(pid, stats)`. + * This AST node corresponds to the following Scala code: + * + * `package` pid { stats } + */ + abstract class PackageDefExtractor { + def apply(pid: RefTree, stats: List[Tree]): PackageDef + def unapply(packageDef: PackageDef): Option[(RefTree, List[Tree])] + } /** The API that all package defs support */ trait PackageDefApi extends MemberDefApi { this: PackageDef => @@ -167,14 +311,45 @@ trait Trees extends base.Trees { self: Universe => val stats: List[Tree] } - override type ImplDef >: Null <: MemberDef with ImplDefApi + /** A common base class for class and object definitions. + */ + type ImplDef >: Null <: MemberDef with ImplDefApi + + /** A tag that preserves the identity of the `ImplDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ImplDefTag: ClassTag[ImplDef] /** The API that all impl defs support */ trait ImplDefApi extends MemberDefApi { this: ImplDef => val impl: Template } - override type ClassDef >: Null <: ImplDef with ClassDefApi + /** A class definition. + */ + type ClassDef >: Null <: ImplDef with ClassDefApi + + /** A tag that preserves the identity of the `ClassDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ClassDefTag: ClassTag[ClassDef] + + /** The constructor/deconstructor for `ClassDef` instances. */ + val ClassDef: ClassDefExtractor + + /** An extractor class to create and pattern match with syntax `ClassDef(mods, name, tparams, impl)`. + * This AST node corresponds to the following Scala code: + * + * mods `class` name [tparams] impl + * + * Where impl stands for: + * + * `extends` parents { defs } + */ + abstract class ClassDefExtractor { + def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template): ClassDef + def unapply(classDef: ClassDef): Option[(Modifiers, TypeName, List[TypeDef], Template)] + } /** The API that all class defs support */ trait ClassDefApi extends ImplDefApi { this: ClassDef => @@ -184,7 +359,33 @@ trait Trees extends base.Trees { self: Universe => val impl: Template } - override type ModuleDef >: Null <: ImplDef with ModuleDefApi + /** An object definition, e.g. `object Foo`. Internally, objects are + * quite frequently called modules to reduce ambiguity. + * Eliminated by compiler phase refcheck. + */ + type ModuleDef >: Null <: ImplDef with ModuleDefApi + + /** A tag that preserves the identity of the `ModuleDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ModuleDefTag: ClassTag[ModuleDef] + + /** The constructor/deconstructor for `ModuleDef` instances. */ + val ModuleDef: ModuleDefExtractor + + /** An extractor class to create and pattern match with syntax `ModuleDef(mods, name, impl)`. + * This AST node corresponds to the following Scala code: + * + * mods `object` name impl + * + * Where impl stands for: + * + * `extends` parents { defs } + */ + abstract class ModuleDefExtractor { + def apply(mods: Modifiers, name: TermName, impl: Template): ModuleDef + def unapply(moduleDef: ModuleDef): Option[(Modifiers, TermName, Template)] + } /** The API that all module defs support */ trait ModuleDefApi extends ImplDefApi { this: ModuleDef => @@ -193,7 +394,14 @@ trait Trees extends base.Trees { self: Universe => val impl: Template } - override type ValOrDefDef >: Null <: MemberDef with ValOrDefDefApi + /** A common base class for ValDefs and DefDefs. + */ + type ValOrDefDef >: Null <: MemberDef with ValOrDefDefApi + + /** A tag that preserves the identity of the `ValOrDefDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ValOrDefDefTag: ClassTag[ValOrDefDef] /** The API that all val defs and def defs support */ trait ValOrDefDefApi extends MemberDefApi { this: ValOrDefDef => @@ -202,7 +410,42 @@ trait Trees extends base.Trees { self: Universe => def rhs: Tree } - override type ValDef >: Null <: ValOrDefDef with ValDefApi + /** Broadly speaking, a value definition. All these are encoded as ValDefs: + * + * - immutable values, e.g. "val x" + * - mutable values, e.g. "var x" - the MUTABLE flag set in mods + * - lazy values, e.g. "lazy val x" - the LAZY flag set in mods + * - method parameters, see vparamss in [[scala.reflect.api.Trees#DefDef]] - the PARAM flag is set in mods + * - explicit self-types, e.g. class A { self: Bar => } + */ + type ValDef >: Null <: ValOrDefDef with ValDefApi + + /** A tag that preserves the identity of the `ValDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ValDefTag: ClassTag[ValDef] + + /** The constructor/deconstructor for `ValDef` instances. */ + val ValDef: ValDefExtractor + + /** An extractor class to create and pattern match with syntax `ValDef(mods, name, tpt, rhs)`. + * This AST node corresponds to any of the following Scala code: + * + * mods `val` name: tpt = rhs + * + * mods `var` name: tpt = rhs + * + * mods name: tpt = rhs // in signatures of function and method definitions + * + * self: Bar => // self-types + * + * If the type of a value is not specified explicitly (i.e. is meant to be inferred), + * this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!). + */ + abstract class ValDefExtractor { + def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef + def unapply(valDef: ValDef): Option[(Modifiers, TermName, Tree, Tree)] + } /** The API that all val defs support */ trait ValDefApi extends ValOrDefDefApi { this: ValDef => @@ -212,7 +455,31 @@ trait Trees extends base.Trees { self: Universe => val rhs: Tree } - override type DefDef >: Null <: ValOrDefDef with DefDefApi + /** A method or macro definition. + * @param name The name of the method or macro. Can be a type name in case this is a type macro + */ + type DefDef >: Null <: ValOrDefDef with DefDefApi + + /** A tag that preserves the identity of the `DefDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val DefDefTag: ClassTag[DefDef] + + /** The constructor/deconstructor for `DefDef` instances. */ + val DefDef: DefDefExtractor + + /** An extractor class to create and pattern match with syntax `DefDef(mods, name, tparams, vparamss, tpt, rhs)`. + * This AST node corresponds to the following Scala code: + * + * mods `def` name[tparams](vparams_1)...(vparams_n): tpt = rhs + * + * If the return type is not specified explicitly (i.e. is meant to be inferred), + * this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!). + */ + abstract class DefDefExtractor { + def apply(mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef + def unapply(defDef: DefDef): Option[(Modifiers, Name, List[TypeDef], List[List[ValDef]], Tree, Tree)] + } /** The API that all def defs support */ trait DefDefApi extends ValOrDefDefApi { this: DefDef => @@ -224,7 +491,34 @@ trait Trees extends base.Trees { self: Universe => val rhs: Tree } - override type TypeDef >: Null <: MemberDef with TypeDefApi + /** An abstract type, a type parameter, or a type alias. + * Eliminated by erasure. + */ + type TypeDef >: Null <: MemberDef with TypeDefApi + + /** A tag that preserves the identity of the `TypeDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeDefTag: ClassTag[TypeDef] + + /** The constructor/deconstructor for `TypeDef` instances. */ + val TypeDef: TypeDefExtractor + + /** An extractor class to create and pattern match with syntax `TypeDef(mods, name, tparams, rhs)`. + * This AST node corresponds to the following Scala code: + * + * mods `type` name[tparams] = rhs + * + * mods `type` name[tparams] >: lo <: hi + * + * First usage illustrates `TypeDefs` representing type aliases and type parameters. + * Second usage illustrates `TypeDefs` representing abstract types, + * where lo and hi are both `TypeBoundsTrees` and `Modifier.deferred` is set in mods. + */ + abstract class TypeDefExtractor { + def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef + def unapply(typeDef: TypeDef): Option[(Modifiers, TypeName, List[TypeDef], Tree)] + } /** The API that all type defs support */ trait TypeDefApi extends MemberDefApi { this: TypeDef => @@ -234,7 +528,46 @@ trait Trees extends base.Trees { self: Universe => val rhs: Tree } - override type LabelDef >: Null <: DefTree with TermTree with LabelDefApi + /** A labelled expression. Not expressible in language syntax, but + * generated by the compiler to simulate while/do-while loops, and + * also by the pattern matcher. + * + * The label acts much like a nested function, where `params` represents + * the incoming parameters. The symbol given to the LabelDef should have + * a MethodType, as if it were a nested function. + * + * Jumps are apply nodes attributed with a label's symbol. The + * arguments from the apply node will be passed to the label and + * assigned to the Idents. + * + * Forward jumps within a block are allowed. + */ + type LabelDef >: Null <: DefTree with TermTree with LabelDefApi + + /** A tag that preserves the identity of the `LabelDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val LabelDefTag: ClassTag[LabelDef] + + /** The constructor/deconstructor for `LabelDef` instances. */ + val LabelDef: LabelDefExtractor + + /** An extractor class to create and pattern match with syntax `LabelDef(name, params, rhs)`. + * + * This AST node does not have direct correspondence to Scala code. + * It is used for tailcalls and like. + * For example, while/do are desugared to label defs as follows: + * {{{ + * while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) + * }}} + * {{{ + * do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) + * }}} + */ + abstract class LabelDefExtractor { + def apply(name: TermName, params: List[Ident], rhs: Tree): LabelDef + def unapply(labelDef: LabelDef): Option[(TermName, List[Ident], Tree)] + } /** The API that all label defs support */ trait LabelDefApi extends DefTreeApi with TermTreeApi { this: LabelDef => @@ -243,7 +576,34 @@ trait Trees extends base.Trees { self: Universe => val rhs: Tree } - override type ImportSelector >: Null <: ImportSelectorApi + /** Import selector + * + * Representation of an imported name its optional rename and their optional positions + * + * Eliminated by typecheck. + * + * @param name the imported name + * @param namePos its position or -1 if undefined + * @param rename the name the import is renamed to (== name if no renaming) + * @param renamePos the position of the rename or -1 if undefined + */ + type ImportSelector >: Null <: AnyRef with ImportSelectorApi + + /** A tag that preserves the identity of the `ImportSelector` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ImportSelectorTag: ClassTag[ImportSelector] + + /** The constructor/deconstructor for `ImportSelector` instances. */ + val ImportSelector: ImportSelectorExtractor + + /** An extractor class to create and pattern match with syntax `ImportSelector(name:, namePos, rename, renamePos)`. + * This is not an AST node, it is used as a part of the `Import` node. + */ + abstract class ImportSelectorExtractor { + def apply(name: Name, namePos: Int, rename: Name, renamePos: Int): ImportSelector + def unapply(importSelector: ImportSelector): Option[(Name, Int, Name, Int)] + } /** The API that all import selectors support */ trait ImportSelectorApi { this: ImportSelector => @@ -253,7 +613,42 @@ trait Trees extends base.Trees { self: Universe => val renamePos: Int } - override type Import >: Null <: SymTree with ImportApi + /** Import clause + * + * @param expr + * @param selectors + */ + type Import >: Null <: SymTree with ImportApi + + /** A tag that preserves the identity of the `Import` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ImportTag: ClassTag[Import] + + /** The constructor/deconstructor for `Import` instances. */ + val Import: ImportExtractor + + /** An extractor class to create and pattern match with syntax `Import(expr, selectors)`. + * This AST node corresponds to the following Scala code: + * + * import expr.{selectors} + * + * Selectors are a list of ImportSelectors, which conceptually are pairs of names (from, to). + * The last (and maybe only name) may be a nme.WILDCARD. For instance: + * + * import qual.{x, y => z, _} + * + * Would be represented as: + * + * Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) + * + * The symbol of an `Import` is an import symbol @see Symbol.newImport. + * It's used primarily as a marker to check that the import has been typechecked. + */ + abstract class ImportExtractor { + def apply(expr: Tree, selectors: List[ImportSelector]): Import + def unapply(import_ : Import): Option[(Tree, List[ImportSelector])] + } /** The API that all imports support */ trait ImportApi extends SymTreeApi { this: Import => @@ -261,7 +656,43 @@ trait Trees extends base.Trees { self: Universe => val selectors: List[ImportSelector] } - override type Template >: Null <: SymTree with TemplateApi + /** Instantiation template of a class or trait + * + * @param parents + * @param body + */ + type Template >: Null <: SymTree with TemplateApi + + /** A tag that preserves the identity of the `Template` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TemplateTag: ClassTag[Template] + + /** The constructor/deconstructor for `Template` instances. */ + val Template: TemplateExtractor + + /** An extractor class to create and pattern match with syntax `Template(parents, self, body)`. + * This AST node corresponds to the following Scala code: + * + * `extends` parents { self => body } + * + * In case when the self-type annotation is missing, it is represented as + * an empty value definition with nme.WILDCARD as name and NoType as type. + * + * The symbol of a template is a local dummy. @see Symbol.newLocalDummy + * The owner of the local dummy is the enclosing trait or class. + * The local dummy is itself the owner of any local blocks. For example: + * + * class C { + * def foo { // owner is C + * def bar // owner is local dummy + * } + * } + */ + abstract class TemplateExtractor { + def apply(parents: List[Tree], self: ValDef, body: List[Tree]): Template + def unapply(template: Template): Option[(List[Tree], ValDef, List[Tree])] + } /** The API that all templates support */ trait TemplateApi extends SymTreeApi { this: Template => @@ -270,7 +701,28 @@ trait Trees extends base.Trees { self: Universe => val body: List[Tree] } - override type Block >: Null <: TermTree with BlockApi + /** Block of expressions (semicolon separated expressions) */ + type Block >: Null <: TermTree with BlockApi + + /** A tag that preserves the identity of the `Block` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val BlockTag: ClassTag[Block] + + /** The constructor/deconstructor for `Block` instances. */ + val Block: BlockExtractor + + /** An extractor class to create and pattern match with syntax `Block(stats, expr)`. + * This AST node corresponds to the following Scala code: + * + * { stats; expr } + * + * If the block is empty, the `expr` is set to `Literal(Constant(()))`. + */ + abstract class BlockExtractor { + def apply(stats: List[Tree], expr: Tree): Block + def unapply(block: Block): Option[(List[Tree], Tree)] + } /** The API that all blocks support */ trait BlockApi extends TermTreeApi { this: Block => @@ -278,7 +730,32 @@ trait Trees extends base.Trees { self: Universe => val expr: Tree } - override type CaseDef >: Null <: Tree with CaseDefApi + /** Case clause in a pattern match. + * (except for occurrences in switch statements). + * Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher) + */ + type CaseDef >: Null <: AnyRef with Tree with CaseDefApi + + /** A tag that preserves the identity of the `CaseDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val CaseDefTag: ClassTag[CaseDef] + + /** The constructor/deconstructor for `CaseDef` instances. */ + val CaseDef: CaseDefExtractor + + /** An extractor class to create and pattern match with syntax `CaseDef(pat, guard, body)`. + * This AST node corresponds to the following Scala code: + * + * `case` pat `if` guard => body + * + * If the guard is not present, the `guard` is set to `EmptyTree`. + * If the body is not specified, the `body` is set to `Literal(Constant())` + */ + abstract class CaseDefExtractor { + def apply(pat: Tree, guard: Tree, body: Tree): CaseDef + def unapply(caseDef: CaseDef): Option[(Tree, Tree, Tree)] + } /** The API that all case defs support */ trait CaseDefApi extends TreeApi { this: CaseDef => @@ -287,21 +764,92 @@ trait Trees extends base.Trees { self: Universe => val body: Tree } - override type Alternative >: Null <: TermTree with AlternativeApi + /** Alternatives of patterns. + * + * Eliminated by compiler phases Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher), + * except for + * occurrences in encoded Switch stmt (i.e. remaining Match(CaseDef(...))) + */ + type Alternative >: Null <: TermTree with AlternativeApi + + /** A tag that preserves the identity of the `Alternative` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AlternativeTag: ClassTag[Alternative] + + /** The constructor/deconstructor for `Alternative` instances. */ + val Alternative: AlternativeExtractor + + /** An extractor class to create and pattern match with syntax `Alternative(trees)`. + * This AST node corresponds to the following Scala code: + * + * pat1 | ... | patn + */ + abstract class AlternativeExtractor { + def apply(trees: List[Tree]): Alternative + def unapply(alternative: Alternative): Option[List[Tree]] + } /** The API that all alternatives support */ trait AlternativeApi extends TermTreeApi { this: Alternative => val trees: List[Tree] } - override type Star >: Null <: TermTree with StarApi + /** Repetition of pattern. + * + * Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). + */ + type Star >: Null <: TermTree with StarApi + + /** A tag that preserves the identity of the `Star` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val StarTag: ClassTag[Star] + + /** The constructor/deconstructor for `Star` instances. */ + val Star: StarExtractor + + /** An extractor class to create and pattern match with syntax `Star(elem)`. + * This AST node corresponds to the following Scala code: + * + * pat* + */ + abstract class StarExtractor { + def apply(elem: Tree): Star + def unapply(star: Star): Option[Tree] + } /** The API that all stars support */ trait StarApi extends TermTreeApi { this: Star => val elem: Tree } - override type Bind >: Null <: DefTree with BindApi + /** Bind a variable to a rhs pattern. + * + * Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). + * + * @param name + * @param body + */ + type Bind >: Null <: DefTree with BindApi + + /** A tag that preserves the identity of the `Bind` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val BindTag: ClassTag[Bind] + + /** The constructor/deconstructor for `Bind` instances. */ + val Bind: BindExtractor + + /** An extractor class to create and pattern match with syntax `Bind(name, body)`. + * This AST node corresponds to the following Scala code: + * + * pat* + */ + abstract class BindExtractor { + def apply(name: Name, body: Tree): Bind + def unapply(bind: Bind): Option[(Name, Tree)] + } /** The API that all binds support */ trait BindApi extends DefTreeApi { this: Bind => @@ -309,7 +857,51 @@ trait Trees extends base.Trees { self: Universe => val body: Tree } - override type UnApply >: Null <: TermTree with UnApplyApi + /** + * Used to represent `unapply` methods in pattern matching. + * + * For example: + * {{{ + * 2 match { case Foo(x) => x } + * }}} + * + * Is represented as: + * {{{ + * Match( + * Literal(Constant(2)), + * List( + * CaseDef( + * UnApply( + * // a dummy node that carries the type of unapplication to patmat + * // the <unapply-selector> here doesn't have an underlying symbol + * // it only has a type assigned, therefore after `resetAllAttrs` this tree is no longer typeable + * Apply(Select(Ident(Foo), newTermName("unapply")), List(Ident(newTermName("<unapply-selector>")))), + * // arguments of the unapply => nothing synthetic here + * List(Bind(newTermName("x"), Ident(nme.WILDCARD)))), + * EmptyTree, + * Ident(newTermName("x"))))) + * }}} + * + * Introduced by typer. Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). + */ + type UnApply >: Null <: TermTree with UnApplyApi + + /** A tag that preserves the identity of the `UnApply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val UnApplyTag: ClassTag[UnApply] + + /** The constructor/deconstructor for `UnApply` instances. */ + val UnApply: UnApplyExtractor + + /** An extractor class to create and pattern match with syntax `UnApply(fun, args)`. + * This AST node does not have direct correspondence to Scala code, + * and is introduced when typechecking pattern matches and `try` blocks. + */ + abstract class UnApplyExtractor { + def apply(fun: Tree, args: List[Tree]): UnApply + def unapply(unApply: UnApply): Option[(Tree, List[Tree])] + } /** The API that all unapplies support */ trait UnApplyApi extends TermTreeApi { this: UnApply => @@ -317,23 +909,56 @@ trait Trees extends base.Trees { self: Universe => val args: List[Tree] } - override type ArrayValue >: Null <: TermTree with ArrayValueApi + /** Anonymous function, eliminated by compiler phase lambdalift */ + type Function >: Null <: TermTree with SymTree with FunctionApi - /** The API that all array values support */ - trait ArrayValueApi extends TermTreeApi { this: ArrayValue => - val elemtpt: Tree - val elems: List[Tree] + /** A tag that preserves the identity of the `Function` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FunctionTag: ClassTag[Function] + + /** The constructor/deconstructor for `Function` instances. */ + val Function: FunctionExtractor + + /** An extractor class to create and pattern match with syntax `Function(vparams, body)`. + * This AST node corresponds to the following Scala code: + * + * vparams => body + * + * The symbol of a Function is a synthetic TermSymbol. + * It is the owner of the function's parameters. + */ + abstract class FunctionExtractor { + def apply(vparams: List[ValDef], body: Tree): Function + def unapply(function: Function): Option[(List[ValDef], Tree)] } - override type Function >: Null <: TermTree with SymTree with FunctionApi - /** The API that all functions support */ trait FunctionApi extends TermTreeApi with SymTreeApi { this: Function => val vparams: List[ValDef] val body: Tree } - override type Assign >: Null <: TermTree with AssignApi + /** Assignment */ + type Assign >: Null <: TermTree with AssignApi + + /** A tag that preserves the identity of the `Assign` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AssignTag: ClassTag[Assign] + + /** The constructor/deconstructor for `Assign` instances. */ + val Assign: AssignExtractor + + /** An extractor class to create and pattern match with syntax `Assign(lhs, rhs)`. + * This AST node corresponds to the following Scala code: + * + * lhs = rhs + */ + abstract class AssignExtractor { + def apply(lhs: Tree, rhs: Tree): Assign + def unapply(assign: Assign): Option[(Tree, Tree)] + } /** The API that all assigns support */ trait AssignApi extends TermTreeApi { this: Assign => @@ -341,7 +966,34 @@ trait Trees extends base.Trees { self: Universe => val rhs: Tree } - override type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi + /** Either an assignment or a named argument. Only appears in argument lists, + * eliminated by compiler phase typecheck (doTypedApply), resurrected by reifier. + */ + type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi + + /** A tag that preserves the identity of the `AssignOrNamedArg` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AssignOrNamedArgTag: ClassTag[AssignOrNamedArg] + + /** The constructor/deconstructor for `AssignOrNamedArg` instances. */ + val AssignOrNamedArg: AssignOrNamedArgExtractor + + /** An extractor class to create and pattern match with syntax `AssignOrNamedArg(lhs, rhs)`. + * This AST node corresponds to the following Scala code: + * + * {{{ + * m.f(lhs = rhs) + * }}} + * {{{ + * @annotation(lhs = rhs) + * }}} + * + */ + abstract class AssignOrNamedArgExtractor { + def apply(lhs: Tree, rhs: Tree): AssignOrNamedArg + def unapply(assignOrNamedArg: AssignOrNamedArg): Option[(Tree, Tree)] + } /** The API that all assigns support */ trait AssignOrNamedArgApi extends TermTreeApi { this: AssignOrNamedArg => @@ -349,7 +1001,28 @@ trait Trees extends base.Trees { self: Universe => val rhs: Tree } - override type If >: Null <: TermTree with IfApi + /** Conditional expression */ + type If >: Null <: TermTree with IfApi + + /** A tag that preserves the identity of the `If` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val IfTag: ClassTag[If] + + /** The constructor/deconstructor for `If` instances. */ + val If: IfExtractor + + /** An extractor class to create and pattern match with syntax `If(cond, thenp, elsep)`. + * This AST node corresponds to the following Scala code: + * + * `if` (cond) thenp `else` elsep + * + * If the alternative is not present, the `elsep` is set to `Literal(Constant(()))`. + */ + abstract class IfExtractor { + def apply(cond: Tree, thenp: Tree, elsep: Tree): If + def unapply(if_ : If): Option[(Tree, Tree, Tree)] + } /** The API that all ifs support */ trait IfApi extends TermTreeApi { this: If => @@ -358,7 +1031,38 @@ trait Trees extends base.Trees { self: Universe => val elsep: Tree } - override type Match >: Null <: TermTree with MatchApi + /** - Pattern matching expression (before compiler phase explicitouter before 2.10 / patmat from 2.10) + * - Switch statements (after compiler phase explicitouter before 2.10 / patmat from 2.10) + * + * After compiler phase explicitouter before 2.10 / patmat from 2.10, cases will satisfy the following constraints: + * + * - all guards are `EmptyTree`, + * - all patterns will be either `Literal(Constant(x:Int))` + * or `Alternative(lit|...|lit)` + * - except for an "otherwise" branch, which has pattern + * `Ident(nme.WILDCARD)` + */ + type Match >: Null <: TermTree with MatchApi + + /** A tag that preserves the identity of the `Match` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MatchTag: ClassTag[Match] + + /** The constructor/deconstructor for `Match` instances. */ + val Match: MatchExtractor + + /** An extractor class to create and pattern match with syntax `Match(selector, cases)`. + * This AST node corresponds to the following Scala code: + * + * selector `match` { cases } + * + * `Match` is also used in pattern matching assignments like `val (foo, bar) = baz`. + */ + abstract class MatchExtractor { + def apply(selector: Tree, cases: List[CaseDef]): Match + def unapply(match_ : Match): Option[(Tree, List[CaseDef])] + } /** The API that all matches support */ trait MatchApi extends TermTreeApi { this: Match => @@ -366,14 +1070,56 @@ trait Trees extends base.Trees { self: Universe => val cases: List[CaseDef] } - override type Return >: Null <: TermTree with SymTree with ReturnApi + /** Return expression */ + type Return >: Null <: TermTree with SymTree with ReturnApi + + /** A tag that preserves the identity of the `Return` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ReturnTag: ClassTag[Return] + + /** The constructor/deconstructor for `Return` instances. */ + val Return: ReturnExtractor + + /** An extractor class to create and pattern match with syntax `Return(expr)`. + * This AST node corresponds to the following Scala code: + * + * `return` expr + * + * The symbol of a Return node is the enclosing method. + */ + abstract class ReturnExtractor { + def apply(expr: Tree): Return + def unapply(return_ : Return): Option[Tree] + } /** The API that all returns support */ trait ReturnApi extends TermTreeApi { this: Return => val expr: Tree } - override type Try >: Null <: TermTree with TryApi + /** [Eugene++] comment me! */ + type Try >: Null <: TermTree with TryApi + + /** A tag that preserves the identity of the `Try` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TryTag: ClassTag[Try] + + /** The constructor/deconstructor for `Try` instances. */ + val Try: TryExtractor + + /** An extractor class to create and pattern match with syntax `Try(block, catches, finalizer)`. + * This AST node corresponds to the following Scala code: + * + * `try` block `catch` { catches } `finally` finalizer + * + * If the finalizer is not present, the `finalizer` is set to `EmptyTree`. + */ + abstract class TryExtractor { + def apply(block: Tree, catches: List[CaseDef], finalizer: Tree): Try + def unapply(try_ : Try): Option[(Tree, List[CaseDef], Tree)] + } /** The API that all tries support */ trait TryApi extends TermTreeApi { this: Try => @@ -382,21 +1128,89 @@ trait Trees extends base.Trees { self: Universe => val finalizer: Tree } - override type Throw >: Null <: TermTree with ThrowApi + /** Throw expression */ + type Throw >: Null <: TermTree with ThrowApi + + /** A tag that preserves the identity of the `Throw` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ThrowTag: ClassTag[Throw] + + /** The constructor/deconstructor for `Throw` instances. */ + val Throw: ThrowExtractor + + /** An extractor class to create and pattern match with syntax `Throw(expr)`. + * This AST node corresponds to the following Scala code: + * + * `throw` expr + */ + abstract class ThrowExtractor { + def apply(expr: Tree): Throw + def unapply(throw_ : Throw): Option[Tree] + } /** The API that all tries support */ trait ThrowApi extends TermTreeApi { this: Throw => val expr: Tree } - override type New >: Null <: TermTree with NewApi + /** Object instantiation + */ + type New >: Null <: TermTree with NewApi + + /** A tag that preserves the identity of the `New` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val NewTag: ClassTag[New] + + /** The constructor/deconstructor for `New` instances. + */ + val New: NewExtractor + + /** An extractor class to create and pattern match with syntax `New(tpt)`. + * This AST node corresponds to the following Scala code: + * + * `new` T + * + * This node always occurs in the following context: + * + * (`new` tpt).<init>[targs](args) + */ + abstract class NewExtractor { + /** A user level `new`. + * One should always use this factory method to build a user level `new`. + * + * @param tpt a class type + */ + def apply(tpt: Tree): New + def unapply(new_ : New): Option[Tree] + } /** The API that all news support */ trait NewApi extends TermTreeApi { this: New => val tpt: Tree } - override type Typed >: Null <: TermTree with TypedApi + /** Type annotation, eliminated by compiler phase cleanup */ + type Typed >: Null <: TermTree with TypedApi + + /** A tag that preserves the identity of the `Typed` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypedTag: ClassTag[Typed] + + /** The constructor/deconstructor for `Typed` instances. */ + val Typed: TypedExtractor + + /** An extractor class to create and pattern match with syntax `Typed(expr, tpt)`. + * This AST node corresponds to the following Scala code: + * + * expr: tpt + */ + abstract class TypedExtractor { + def apply(expr: Tree, tpt: Tree): Typed + def unapply(typed: Typed): Option[(Tree, Tree)] + } /** The API that all typeds support */ trait TypedApi extends TermTreeApi { this: Typed => @@ -404,7 +1218,14 @@ trait Trees extends base.Trees { self: Universe => val tpt: Tree } - override type GenericApply >: Null <: TermTree with GenericApplyApi + /** Common base class for Apply and TypeApply. + */ + type GenericApply >: Null <: TermTree with GenericApplyApi + + /** A tag that preserves the identity of the `GenericApply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val GenericApplyTag: ClassTag[GenericApply] /** The API that all applies support */ trait GenericApplyApi extends TermTreeApi { this: GenericApply => @@ -412,19 +1233,99 @@ trait Trees extends base.Trees { self: Universe => val args: List[Tree] } - override type TypeApply >: Null <: GenericApply with TypeApplyApi + /* @PP: All signs point toward it being a requirement that args.nonEmpty, + * but I can't find that explicitly stated anywhere. Unless your last name + * is odersky, you should probably treat it as true. + */ + /** Explicit type application. */ + type TypeApply >: Null <: GenericApply with TypeApplyApi + + /** A tag that preserves the identity of the `TypeApply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeApplyTag: ClassTag[TypeApply] + + /** The constructor/deconstructor for `TypeApply` instances. */ + val TypeApply: TypeApplyExtractor + + /** An extractor class to create and pattern match with syntax `TypeApply(fun, args)`. + * This AST node corresponds to the following Scala code: + * + * fun[args] + */ + abstract class TypeApplyExtractor { + def apply(fun: Tree, args: List[Tree]): TypeApply + def unapply(typeApply: TypeApply): Option[(Tree, List[Tree])] + } /** The API that all type applies support */ trait TypeApplyApi extends GenericApplyApi { this: TypeApply => } - override type Apply >: Null <: GenericApply with ApplyApi + /** Value application */ + type Apply >: Null <: GenericApply with ApplyApi + + /** A tag that preserves the identity of the `Apply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ApplyTag: ClassTag[Apply] + + /** The constructor/deconstructor for `Apply` instances. */ + val Apply: ApplyExtractor + + /** An extractor class to create and pattern match with syntax `Apply(fun, args)`. + * This AST node corresponds to the following Scala code: + * + * fun(args) + * + * For instance: + * + * fun[targs](args) + * + * Is expressed as: + * + * Apply(TypeApply(fun, targs), args) + */ + abstract class ApplyExtractor { + def apply(fun: Tree, args: List[Tree]): Apply + def unapply(apply: Apply): Option[(Tree, List[Tree])] + } /** The API that all applies support */ trait ApplyApi extends GenericApplyApi { this: Apply => } - override type Super >: Null <: TermTree with SuperApi + /** Super reference, where `qual` is the corresponding `this` reference. + * A super reference `C.super[M]` is represented as `Super(This(C), M)`. + */ + type Super >: Null <: TermTree with SuperApi + + /** A tag that preserves the identity of the `Super` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SuperTag: ClassTag[Super] + + /** The constructor/deconstructor for `Super` instances. */ + val Super: SuperExtractor + + /** An extractor class to create and pattern match with syntax `Super(qual, mix)`. + * This AST node corresponds to the following Scala code: + * + * C.super[M] + * + * Which is represented as: + * + * Super(This(C), M) + * + * If `mix` is empty, it is tpnme.EMPTY. + * + * The symbol of a Super is the class _from_ which the super reference is made. + * For instance in C.super(...), it would be C. + */ + abstract class SuperExtractor { + def apply(qual: Tree, mix: TypeName): Super + def unapply(super_ : Super): Option[(Tree, TypeName)] + } /** The API that all supers support */ trait SuperApi extends TermTreeApi { this: Super => @@ -432,14 +1333,57 @@ trait Trees extends base.Trees { self: Universe => val mix: TypeName } - override type This >: Null <: TermTree with SymTree with ThisApi + /** Self reference */ + type This >: Null <: TermTree with SymTree with ThisApi + + /** A tag that preserves the identity of the `This` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ThisTag: ClassTag[This] + + /** The constructor/deconstructor for `This` instances. */ + val This: ThisExtractor + + /** An extractor class to create and pattern match with syntax `This(qual)`. + * This AST node corresponds to the following Scala code: + * + * qual.this + * + * The symbol of a This is the class to which the this refers. + * For instance in C.this, it would be C. + * + * If `mix` is empty, then ??? + */ + abstract class ThisExtractor { + def apply(qual: TypeName): This + def unapply(this_ : This): Option[TypeName] + } /** The API that all thises support */ trait ThisApi extends TermTreeApi with SymTreeApi { this: This => val qual: TypeName } - override type Select >: Null <: RefTree with SelectApi + /** Designator <qualifier> . <name> */ + type Select >: Null <: RefTree with SelectApi + + /** A tag that preserves the identity of the `Select` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SelectTag: ClassTag[Select] + + /** The constructor/deconstructor for `Select` instances. */ + val Select: SelectExtractor + + /** An extractor class to create and pattern match with syntax `Select(qual, name)`. + * This AST node corresponds to the following Scala code: + * + * qualifier.selector + */ + abstract class SelectExtractor { + def apply(qualifier: Tree, name: Name): Select + def unapply(select: Select): Option[(Tree, Name)] + } /** The API that all selects support */ trait SelectApi extends RefTreeApi { this: Select => @@ -447,28 +1391,132 @@ trait Trees extends base.Trees { self: Universe => val name: Name } - override type Ident >: Null <: RefTree with IdentApi + /** Identifier <name> */ + type Ident >: Null <: RefTree with IdentApi + + /** A tag that preserves the identity of the `Ident` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val IdentTag: ClassTag[Ident] + + /** The constructor/deconstructor for `Ident` instances. */ + val Ident: IdentExtractor + + /** An extractor class to create and pattern match with syntax `Ident(qual, name)`. + * This AST node corresponds to the following Scala code: + * + * name + * + * Type checker converts idents that refer to enclosing fields or methods to selects. + * For example, name ==> this.name + */ + abstract class IdentExtractor { + def apply(name: Name): Ident + def unapply(ident: Ident): Option[Name] + } /** The API that all idents support */ trait IdentApi extends RefTreeApi { this: Ident => val name: Name } - override type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi + /** Marks underlying reference to id as boxed. + * @pre id must refer to a captured variable + * A reference such marked will refer to the boxed entity, no dereferencing + * with `.elem` is done on it. + * This tree node can be emitted by macros such as reify that call referenceCapturedVariable. + * It is eliminated in LambdaLift, where the boxing conversion takes place. + */ + type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi + + /** A tag that preserves the identity of the `ReferenceToBoxed` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ReferenceToBoxedTag: ClassTag[ReferenceToBoxed] + + /** The constructor/deconstructor for `ReferenceToBoxed` instances. */ + val ReferenceToBoxed: ReferenceToBoxedExtractor + + /** An extractor class to create and pattern match with syntax `ReferenceToBoxed(ident)`. + * This AST node does not have direct correspondence to Scala code, + * and is emitted by macros to reference capture vars directly without going through `elem`. + * + * For example: + * + * var x = ... + * fun { x } + * + * Will emit: + * + * Ident(x) + * + * Which gets transformed to: + * + * Select(Ident(x), "elem") + * + * If `ReferenceToBoxed` were used instead of Ident, no transformation would be performed. + */ + abstract class ReferenceToBoxedExtractor { + def apply(ident: Ident): ReferenceToBoxed + def unapply(referenceToBoxed: ReferenceToBoxed): Option[Ident] + } /** The API that all references support */ trait ReferenceToBoxedApi extends TermTreeApi { this: ReferenceToBoxed => val ident: Tree } - override type Literal >: Null <: TermTree with LiteralApi + /** Literal */ + type Literal >: Null <: TermTree with LiteralApi + + /** A tag that preserves the identity of the `Literal` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val LiteralTag: ClassTag[Literal] + + /** The constructor/deconstructor for `Literal` instances. */ + val Literal: LiteralExtractor + + /** An extractor class to create and pattern match with syntax `Literal(value)`. + * This AST node corresponds to the following Scala code: + * + * value + */ + abstract class LiteralExtractor { + def apply(value: Constant): Literal + def unapply(literal: Literal): Option[Constant] + } /** The API that all literals support */ trait LiteralApi extends TermTreeApi { this: Literal => val value: Constant } - override type Annotated >: Null <: Tree with AnnotatedApi + /** A tree that has an annotation attached to it. Only used for annotated types and + * annotation ascriptions, annotations on definitions are stored in the Modifiers. + * Eliminated by typechecker (typedAnnotated), the annotations are then stored in + * an AnnotatedType. + */ + type Annotated >: Null <: AnyRef with Tree with AnnotatedApi + + /** A tag that preserves the identity of the `Annotated` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AnnotatedTag: ClassTag[Annotated] + + /** The constructor/deconstructor for `Annotated` instances. */ + val Annotated: AnnotatedExtractor + + /** An extractor class to create and pattern match with syntax `Annotated(annot, arg)`. + * This AST node corresponds to the following Scala code: + * + * arg @annot // for types + * arg: @annot // for exprs + */ + abstract class AnnotatedExtractor { + def apply(annot: Tree, arg: Tree): Annotated + def unapply(annotated: Annotated): Option[(Tree, Tree)] + } /** The API that all annotateds support */ trait AnnotatedApi extends TreeApi { this: Annotated => @@ -476,14 +1524,55 @@ trait Trees extends base.Trees { self: Universe => val arg: Tree } - override type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi + /** Singleton type, eliminated by RefCheck */ + type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi + + /** A tag that preserves the identity of the `SingletonTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SingletonTypeTreeTag: ClassTag[SingletonTypeTree] + + /** The constructor/deconstructor for `SingletonTypeTree` instances. */ + val SingletonTypeTree: SingletonTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `SingletonTypeTree(ref)`. + * This AST node corresponds to the following Scala code: + * + * ref.type + */ + abstract class SingletonTypeTreeExtractor { + def apply(ref: Tree): SingletonTypeTree + def unapply(singletonTypeTree: SingletonTypeTree): Option[Tree] + } /** The API that all singleton type trees support */ trait SingletonTypeTreeApi extends TypTreeApi { this: SingletonTypeTree => val ref: Tree } - override type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi + /** Type selection <qualifier> # <name>, eliminated by RefCheck */ + // [Eugene++] don't see why we need it, when we have Select + type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi + + /** A tag that preserves the identity of the `SelectFromTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SelectFromTypeTreeTag: ClassTag[SelectFromTypeTree] + + /** The constructor/deconstructor for `SelectFromTypeTree` instances. */ + val SelectFromTypeTree: SelectFromTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `SelectFromTypeTree(qualifier, name)`. + * This AST node corresponds to the following Scala code: + * + * qualifier # selector + * + * Note: a path-dependent type p.T is expressed as p.type # T + */ + abstract class SelectFromTypeTreeExtractor { + def apply(qualifier: Tree, name: TypeName): SelectFromTypeTree + def unapply(selectFromTypeTree: SelectFromTypeTree): Option[(Tree, TypeName)] + } /** The API that all selects from type trees support */ trait SelectFromTypeTreeApi extends TypTreeApi with RefTreeApi { this: SelectFromTypeTree => @@ -491,14 +1580,52 @@ trait Trees extends base.Trees { self: Universe => val name: TypeName } - override type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi + /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ + type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi + + /** A tag that preserves the identity of the `CompoundTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val CompoundTypeTreeTag: ClassTag[CompoundTypeTree] + + /** The constructor/deconstructor for `CompoundTypeTree` instances. */ + val CompoundTypeTree: CompoundTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `CompoundTypeTree(templ)`. + * This AST node corresponds to the following Scala code: + * + * parent1 with ... with parentN { refinement } + */ + abstract class CompoundTypeTreeExtractor { + def apply(templ: Template): CompoundTypeTree + def unapply(compoundTypeTree: CompoundTypeTree): Option[Template] + } /** The API that all compound type trees support */ trait CompoundTypeTreeApi extends TypTreeApi { this: CompoundTypeTree => val templ: Template } - override type AppliedTypeTree >: Null <: TypTree with AppliedTypeTreeApi + /** Applied type <tpt> [ <args> ], eliminated by RefCheck */ + type AppliedTypeTree >: Null <: TypTree with AppliedTypeTreeApi + + /** A tag that preserves the identity of the `AppliedTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AppliedTypeTreeTag: ClassTag[AppliedTypeTree] + + /** The constructor/deconstructor for `AppliedTypeTree` instances. */ + val AppliedTypeTree: AppliedTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `AppliedTypeTree(tpt, args)`. + * This AST node corresponds to the following Scala code: + * + * tpt[args] + */ + abstract class AppliedTypeTreeExtractor { + def apply(tpt: Tree, args: List[Tree]): AppliedTypeTree + def unapply(appliedTypeTree: AppliedTypeTree): Option[(Tree, List[Tree])] + } /** The API that all applied type trees support */ trait AppliedTypeTreeApi extends TypTreeApi { this: AppliedTypeTree => @@ -506,7 +1633,26 @@ trait Trees extends base.Trees { self: Universe => val args: List[Tree] } - override type TypeBoundsTree >: Null <: TypTree with TypeBoundsTreeApi + /** Document me! */ + type TypeBoundsTree >: Null <: TypTree with TypeBoundsTreeApi + + /** A tag that preserves the identity of the `TypeBoundsTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeBoundsTreeTag: ClassTag[TypeBoundsTree] + + /** The constructor/deconstructor for `TypeBoundsTree` instances. */ + val TypeBoundsTree: TypeBoundsTreeExtractor + + /** An extractor class to create and pattern match with syntax `TypeBoundsTree(lo, hi)`. + * This AST node corresponds to the following Scala code: + * + * >: lo <: hi + */ + abstract class TypeBoundsTreeExtractor { + def apply(lo: Tree, hi: Tree): TypeBoundsTree + def unapply(typeBoundsTree: TypeBoundsTree): Option[(Tree, Tree)] + } /** The API that all type bound trees support */ trait TypeBoundsTreeApi extends TypTreeApi { this: TypeBoundsTree => @@ -514,7 +1660,26 @@ trait Trees extends base.Trees { self: Universe => val hi: Tree } - override type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi + /** Document me! */ + type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi + + /** A tag that preserves the identity of the `ExistentialTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ExistentialTypeTreeTag: ClassTag[ExistentialTypeTree] + + /** The constructor/deconstructor for `ExistentialTypeTree` instances. */ + val ExistentialTypeTree: ExistentialTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `ExistentialTypeTree(tpt, whereClauses)`. + * This AST node corresponds to the following Scala code: + * + * tpt forSome { whereClauses } + */ + abstract class ExistentialTypeTreeExtractor { + def apply(tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree + def unapply(existentialTypeTree: ExistentialTypeTree): Option[(Tree, List[Tree])] + } /** The API that all existential type trees support */ trait ExistentialTypeTreeApi extends TypTreeApi { this: ExistentialTypeTree => @@ -522,7 +1687,29 @@ trait Trees extends base.Trees { self: Universe => val whereClauses: List[Tree] } - override type TypeTree >: Null <: TypTree with TypeTreeApi + /** A synthetic tree holding an arbitrary type. Not to be confused with + * with TypTree, the trait for trees that are only used for type trees. + * TypeTree's are inserted in several places, but most notably in + * `RefCheck`, where the arbitrary type trees are all replaced by + * TypeTree's. */ + type TypeTree >: Null <: TypTree with TypeTreeApi + + /** A tag that preserves the identity of the `TypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeTreeTag: ClassTag[TypeTree] + + /** The constructor/deconstructor for `TypeTree` instances. */ + val TypeTree: TypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `TypeTree()`. + * This AST node does not have direct correspondence to Scala code, + * and is emitted by everywhere when we want to wrap a `Type` in a `Tree`. + */ + abstract class TypeTreeExtractor { + def apply(): TypeTree + def unapply(typeTree: TypeTree): Boolean + } /** The API that all type trees support */ trait TypeTreeApi extends TypTreeApi { this: TypeTree => @@ -536,6 +1723,83 @@ trait Trees extends base.Trees { self: Universe => */ val emptyValDef: ValDef +// ---------------------- factories ---------------------------------------------- + + /** @param sym the class symbol + * @param impl the implementation template + */ + def ClassDef(sym: Symbol, impl: Template): ClassDef + + /** + * @param sym the class symbol + * @param impl the implementation template + */ + def ModuleDef(sym: Symbol, impl: Template): ModuleDef + + def ValDef(sym: Symbol, rhs: Tree): ValDef + + def ValDef(sym: Symbol): ValDef + + def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef + + def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef + + def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef + + def DefDef(sym: Symbol, rhs: Tree): DefDef + + def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef + + /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */ + def TypeDef(sym: Symbol, rhs: Tree): TypeDef + + /** A TypeDef node which defines abstract type or type parameter for given `sym` */ + def TypeDef(sym: Symbol): TypeDef + + def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef + + /** Block factory that flattens directly nested blocks. + */ + def Block(stats: Tree*): Block + + /** casedef shorthand */ + def CaseDef(pat: Tree, body: Tree): CaseDef + + def Bind(sym: Symbol, body: Tree): Bind + + def Try(body: Tree, cases: (Tree, Tree)*): Try + + def Throw(tpe: Type, args: Tree*): Throw + + /** Factory method for object creation `new tpt(args_1)...(args_n)` + * A `New(t, as)` is expanded to: `(new t).<init>(as)` + */ + def New(tpt: Tree, argss: List[List[Tree]]): Tree + + /** 0-1 argument list new, based on a type. + */ + def New(tpe: Type, args: Tree*): Tree + + def New(sym: Symbol, args: Tree*): Tree + + def Apply(sym: Symbol, args: Tree*): Tree + + def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree + + def Super(sym: Symbol, mix: TypeName): Tree + + def This(sym: Symbol): Tree + + def Select(qualifier: Tree, name: String): Select + + def Select(qualifier: Tree, sym: Symbol): Select + + def Ident(name: String): Ident + + def Ident(sym: Symbol): Ident + + def TypeTree(tp: Type): TypeTree + // ---------------------- copying ------------------------------------------------ /** The standard (lazy) tree copier @@ -565,7 +1829,6 @@ trait Trees extends base.Trees { self: Universe => def Star(tree: Tree, elem: Tree): Star def Bind(tree: Tree, name: Name, body: Tree): Bind def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply - def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg @@ -682,9 +1945,35 @@ trait Trees extends base.Trees { self: Universe => protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree) - type Modifiers >: Null <: ModifiersApi - abstract class ModifiersApi extends ModifiersBase + /** ... */ + type Modifiers >: Null <: AnyRef with ModifiersApi -} + /** A tag that preserves the identity of the `Modifiers` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ModifiersTag: ClassTag[Modifiers] + + /** ... */ + abstract class ModifiersApi { + def flags: FlagSet // default: NoFlags + def hasFlag(flag: FlagSet): Boolean + def privateWithin: Name // default: EmptyTypeName + def annotations: List[Tree] // default: List() + def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = + Modifiers(flags, privateWithin, f(annotations)) + } + + val Modifiers: ModifiersCreator + abstract class ModifiersCreator { + def apply(): Modifiers = Modifiers(NoFlags, EmptyTypeName, List()) + def apply(flags: FlagSet, privateWithin: Name, annotations: List[Tree]): Modifiers + } + + def Modifiers(flags: FlagSet, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List()) + def Modifiers(flags: FlagSet): Modifiers = Modifiers(flags, EmptyTypeName) + + /** ... */ + lazy val NoMods = Modifiers() +} diff --git a/src/reflect/scala/reflect/api/TypeCreator.scala b/src/reflect/scala/reflect/api/TypeCreator.scala new file mode 100644 index 0000000000..cc6d38c548 --- /dev/null +++ b/src/reflect/scala/reflect/api/TypeCreator.scala @@ -0,0 +1,26 @@ +package scala.reflect +package api + +/** A mirror-aware factory for types. + * + * In the reflection API, artifacts are specific to universes and + * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors. + * + * Therefore to build a type one needs to know a universe that the type is going to be bound to + * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int` + * points to a core class `Int` from scala-library.jar). + * + * `TypeCreator` implements this notion by providing a standalone type factory. + * + * This is immediately useful for type tags. When the compiler creates a type tag, + * the end result needs to make sense in any mirror. That's because the compiler knows + * the universe it's creating a type tag for (since `TypeTag` is path-dependent on a universe), + * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM + * it doesn't know what classloader use to resolve symbolic names in the type tag). + * + * Due to a typechecker restriction (no eta-expansion for dependent method types), + * `TypeCreator` can't have a functional type, so it's implemented as class with an apply method. + */ +abstract class TypeCreator { + def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type +} diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/reflect/scala/reflect/api/TypeTags.scala index 55708c5274..a7e58d2bcb 100644 --- a/src/library/scala/reflect/base/TypeTags.scala +++ b/src/reflect/scala/reflect/api/TypeTags.scala @@ -5,50 +5,84 @@ package scala package reflect -package base +package api import java.lang.{ Class => jClass } import scala.language.implicitConversions +/* + * TODO + * add @see to docs about universes + * [Eugene++] also mention sensitivity to prefixes, i.e. that rb.TypeTag is different from ru.TypeTag + * [Chris++] tag.in(some mirror) or expr.in(some mirror) (does not work for tag and exprs in macros) + * Backwards compat item1: [Eugene++] it might be useful, though, to guard against abstractness of the incoming type. + */ /** - * Type tags encapsulate a representation of type T. - * They are supposed to replace the pre-2.10 concept of a [[scala.reflect.Manifest]]. - * TypeTags are much better integrated with reflection than manifests are, and are consequently much simpler. + * A type tag encapsulates a representation of type T. * - * === Overview === + * Type tags replace the pre-2.10 concept of a [[scala.reflect.Manifest]] and are integrated with reflection. * - * Type tags are organized in a hierarchy of three classes: - * [[scala.reflect.ClassTag]], [[scala.reflect.base.Universe#TypeTag]] and [[scala.reflect.base.Universe#WeakTypeTag]]. + * === Overview and examples === * - * A [[scala.reflect.ClassTag]] carries a runtime class that corresponds to the source type T. - * As of such, it possesses the knowledge about how to build single- and multi-dimensional arrays of elements of that type. - * It guarantees that the source type T did not to contain any references to type parameters or abstract types. - * [[scala.reflect.ClassTag]] corresponds to a previous notion of [[scala.reflect.ClassManifest]]. + * Type tags are organized in a hierarchy of three classes: + * [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]]. * - * A [[scala.reflect.base.Universe#WeakTypeTag]] value wraps a full Scala type in its tpe field. - * A [[scala.reflect.base.Universe#TypeTag]] value is an [[scala.reflect.base.Universe#WeakTypeTag]] - * that is guaranteed not to contain any references to type parameters or abstract types. + * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]], [[scala.reflect.api.Universe#WeakTypeTag]] * - * [Eugene++] also mention sensitivity to prefixes, i.e. that rb.TypeTag is different from ru.TypeTag - * [Eugene++] migratability between mirrors and universes is also worth mentioning + * Examples: + * {{{ + * scala> class Person + * scala> class Container[T] + * scala> import scala.reflect.ClassTag + * scala> import scala.reflect.runtime.universe.TypeTag + * scala> import scala.reflect.runtime.universe.WeakTypeTag + * scala> def firstTypeArg( tag: WeakTypeTag[_] ) = (tag.tpe match {case TypeRef(_,_,typeArgs) => typeArgs})(0) + * }}} + * TypeTag contains concrete type arguments: + * {{{ + * scala> firstTypeArg( implicitly[TypeTag[Container[Person]]] ) + * res0: reflect.runtime.universe.Type = Person + * }}} + * TypeTag guarantees concrete type arguments (fails for references to unbound type arguments): + * {{{ + * scala> def foo1[T] = implicitly[TypeTag[Container[T]]] + * <console>:11: error: No TypeTag available for Container[T] + * def foo1[T] = implicitly[TypeTag[Container[T]]] + * }}} + * WeakTypeTag allows references to unbound type arguments: + * {{{ + * scala> def foo2[T] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] ) + * foo2: [T]=> reflect.runtime.universe.Type + * scala> foo2[Person] + * res1: reflect.runtime.universe.Type = T + * }}} + * TypeTag allows unbound type arguments for which type tags are available: + * {{{ + * scala> def foo3[T:TypeTag] = firstTypeArg( implicitly[TypeTag[Container[T]]] ) + * foo3: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type + * scala> foo3[Person] + * res1: reflect.runtime.universe.Type = Person + * }}} + * WeakTypeTag contains concrete type arguments if available via existing tags: + * {{{ + * scala> def foo4[T:WeakTypeTag] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] ) + * foo4: [T](implicit evidence$1: reflect.runtime.universe.WeakTypeTag[T])reflect.runtime.universe.Type + * scala> foo4[Person] + * res1: reflect.runtime.universe.Type = Person + * }}} * - * === Splicing === * - * Tags can be spliced, i.e. if compiler generates a tag for a type that contains references to tagged - * type parameters or abstract type members, it will retrieve the corresponding tag and embed it into the result. - * An example that illustrates the TypeTag embedding, consider the following function: + * [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]] are path dependent on their universe. * - * import reflect.mirror._ - * def f[T: TypeTag, U] = { - * type L = T => U - * implicitly[WeakTypeTag[L]] - * } + * The default universe is [[scala.reflect.runtime.universe]] * - * Then a call of f[String, Int] will yield a result of the form + * Type tags can be migrated to another universe given the corresponding mirror using * - * WeakTypeTag(<[ String => U ]>). + * {{{ + * tag.in( other_mirror ) + * }}} * - * Note that T has been replaced by String, because it comes with a TypeTag in f, whereas U was left as a type parameter. + * See [[scala.reflect.api.TypeTags#WeakTypeTag.in]] * * === WeakTypeTag vs TypeTag === * @@ -56,15 +90,17 @@ import scala.language.implicitConversions * This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime * by getting cryptic errors far away from their source. For example, consider the following snippet: * + * {{{ * def bind[T: WeakTypeTag](name: String, value: T): IR.Result = bind((name, value)) * def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value) * object NamedParam { * implicit def namedValue[T: WeakTypeTag](name: String, x: T): NamedParam = apply(name, x) * def apply[T: WeakTypeTag](name: String, x: T): NamedParam = new Typed[T](name, x) * } + * }}} * - * This fragment of Scala REPL implementation defines a `bind` function that carries a named value along with its type - * into the heart of the REPL. Using a [[scala.reflect.base.Universe#WeakTypeTag]] here is reasonable, because it is desirable + * This fragment of the Scala REPL implementation defines a `bind` function that carries a named value along with its type + * into the heart of the REPL. Using a [[scala.reflect.api.Universe#WeakTypeTag]] here is reasonable, because it is desirable * to work with all types, even if they are type parameters or abstract type members. * * However if any of the three `WeakTypeTag` context bounds is omitted, the resulting code will be incorrect, @@ -73,7 +109,7 @@ import scala.language.implicitConversions * If `WeakTypeTag` context bounds were replaced with `TypeTag`, then such errors would be reported statically. * But in that case we wouldn't be able to use `bind` in arbitrary contexts. * - * === Backward compatibility === + * === Backward compatibility with Manifests === * * Type tags correspond loosely to manifests. * @@ -81,50 +117,72 @@ import scala.language.implicitConversions * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag, * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.runtime.universe.TypeTag, * - * In Scala 2.10, manifests are deprecated, so it's adviseable to migrate them to tags, - * because manifests might be removed in the next major release. + * In Scala 2.10, manifests are deprecated, so it's advisable to migrate them to tags, + * because manifests will probably be removed in the next major release. * - * In most cases it will be enough to replace ClassManifests with ClassTags and Manifests with TypeTags, - * however there are a few caveats: + * In most cases it will be enough to replace ClassManifest with ClassTag and Manifest with TypeTag. + * There are however a few caveats: * * 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available. - * // [Eugene++] it might be useful, though, to guard against abstractness of the incoming type. * * 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the base tags * (defined in the corresponding companion objects) to find out whether it represents a primitive value class. * You can also use `<tag>.tpe.typeSymbol.isPrimitiveValueClass` for that purpose (requires scala-reflect.jar). * * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects. - * Consider assembling corresponding types using reflection API provided by Java (for classes) and Scala (for types). + * Consider assembling corresponding types using the reflection APIs provided by Java (for classes) and Scala (for types). * * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API. - * Consider using reflection API provided by Java (for classes) and Scala (for types) instead. + * Consider using the reflection APIs provided by Java (for classes) and Scala (for types) instead. */ trait TypeTags { self: Universe => import definitions._ /** - * If an implicit value of type u.WeakTypeTag[T] is required, the compiler will make one up on demand. - * The implicitly created value contains in its tpe field a value of type u.Type that is a reflective representation of T. - * In that value, any occurrences of type parameters or abstract types U - * which come themselves with a TypeTag are represented by the type referenced by that TypeTag. + * If an implicit value of type WeakTypeTag[T] is required, the compiler will create one. + * A reflective representation of T can be accessed via the tpe field. + * Components of T can be references to type parameters or abstract types. WeakTypeTag makes an effort to + * be as concrete as possible, i.e. if type tags are available for the referenced type arguments or abstract types, + * they are used to embed the concrete types into the WeakTypeTag. Otherwise the WeakTypeTag will contain a reference + * to an abstract type. This behavior can be useful, when one expects T to be possibly partially abstract, but + * requires special care to handle this case. If however T is expected to be fully known, use + * [[scala.reflect.api.Universe#TypeTag]] instead, which statically guarantees this property. * - * @see [[scala.reflect.base.TypeTags]] + * @see [[scala.reflect.api.TypeTags]] */ @annotation.implicitNotFound(msg = "No WeakTypeTag available for ${T}") trait WeakTypeTag[T] extends Equals with Serializable { + /** + * Mirror corresponding to the universe of this WeakTypeTag. + */ val mirror: Mirror + /** + * Migrates type tag to another universe. + * + * Type tags are path dependent on their universe. This methods allows migration + * given the mirror corresponding to the target universe. + * + * Migration means that all symbolic references to classes/objects/packages in the expression + * will be re-resolved within the new mirror (typically using that mirror's classloader). + */ def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # WeakTypeTag[T] + + /** + * Reflective representation of type T. + */ def tpe: Type - /** case class accessories */ + // case class accessories override def canEqual(x: Any) = x.isInstanceOf[WeakTypeTag[_]] override def equals(x: Any) = x.isInstanceOf[WeakTypeTag[_]] && this.mirror == x.asInstanceOf[WeakTypeTag[_]].mirror && this.tpe == x.asInstanceOf[WeakTypeTag[_]].tpe override def hashCode = mirror.hashCode * 31 + tpe.hashCode override def toString = "WeakTypeTag[" + tpe + "]" } + /** + * Type tags corresponding to primitive types and constructor/extractor for WeakTypeTags. + */ object WeakTypeTag { val Byte : WeakTypeTag[scala.Byte] = TypeTag.Byte val Short : WeakTypeTag[scala.Short] = TypeTag.Short @@ -142,6 +200,7 @@ trait TypeTags { self: Universe => val Nothing : WeakTypeTag[scala.Nothing] = TypeTag.Nothing val Null : WeakTypeTag[scala.Null] = TypeTag.Null + def apply[T](mirror1: MirrorOf[self.type], tpec1: TypeCreator): WeakTypeTag[T] = tpec1(mirror1) match { case ByteTpe => WeakTypeTag.Byte.asInstanceOf[WeakTypeTag[T]] @@ -175,16 +234,20 @@ trait TypeTags { self: Universe => } /** - * If an implicit value of type u.TypeTag[T] is required, the compiler will make one up on demand following the same procedure as for TypeTags. - * However, if the resulting type still contains references to type parameters or abstract types, a static error results. + * A `TypeTag` is a [[scala.reflect.api.Universe#WeakTypeTag]] with the additional + * static guarantee that all type references are concrete, i.e. it does <b>not</b> contain any references to + * unresolved type parameters or abstract types. * - * @see [[scala.reflect.base.TypeTags]] + * @see [[scala.reflect.api.TypeTags]] */ @annotation.implicitNotFound(msg = "No TypeTag available for ${T}") trait TypeTag[T] extends WeakTypeTag[T] with Equals with Serializable { + /** + * @inheritdoc + */ override def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T] - /** case class accessories */ + // case class accessories override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]] override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.mirror == x.asInstanceOf[TypeTag[_]].mirror && this.tpe == x.asInstanceOf[TypeTag[_]].tpe override def hashCode = mirror.hashCode * 31 + tpe.hashCode @@ -239,23 +302,36 @@ trait TypeTags { self: Universe => private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true) } - private class PredefTypeCreator[T](copyIn: Universe => Universe # TypeTag[T]) extends TypeCreator { + private class PredefTypeCreator[T](copyIn: Universe => Universe#TypeTag[T]) extends TypeCreator { def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type = { copyIn(m.universe).asInstanceOf[U # TypeTag[T]].tpe } } - private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe # TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) { + private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe#TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) { override lazy val tpe: Type = _tpe private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true) } - // incantations + /** + * Shortcut for `implicitly[WeakTypeTag[T]]` + */ def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag + + /** + * Shortcut for `implicitly[TypeTag[T]]` + */ def typeTag[T](implicit ttag: TypeTag[T]) = ttag // big thanks to Viktor Klang for this brilliant idea! + /** + * Shortcut for `implicitly[WeakTypeTag[T]].tpe` + */ def weakTypeOf[T](implicit attag: WeakTypeTag[T]): Type = attag.tpe + + /** + * Shortcut for `implicitly[TypeTag[T]].tpe` + */ def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe } @@ -271,7 +347,7 @@ private[scala] class SerializedTypeTag(var tpec: TypeCreator, var concrete: Bool } private def readResolve(): AnyRef = { - import scala.reflect.basis._ + import scala.reflect.runtime.universe._ if (concrete) TypeTag(rootMirror, tpec) else WeakTypeTag(rootMirror, tpec) } diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala index 1c79de02c3..af70c9e761 100644 --- a/src/reflect/scala/reflect/api/Types.scala +++ b/src/reflect/scala/reflect/api/Types.scala @@ -1,13 +1,39 @@ package scala.reflect package api -trait Types extends base.Types { self: Universe => +/** + * Defines the type hierachy for types. + * + * Note: Because of implementation details, some type factories have return type `Type` + * instead of a more precise type. + * + * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here. + */ +trait Types { self: Universe => + + /** The type of Scala types, and also Scala type signatures. + * (No difference is internally made between the two). + */ + type Type >: Null <: TypeApi - override type Type >: Null <: TypeApi + /** A tag that preserves the identity of the `Type` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeTagg: ClassTag[Type] - /** The extended API of types + /** This constant is used as a special value that indicates that no meaningful type exists. */ - abstract class TypeApi extends TypeBase { + val NoType: Type + + /** This constant is used as a special value denoting the empty prefix in a path dependent type. + * For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for + * the symbol for `x`. + */ + val NoPrefix: Type + + /** The API of types + */ + abstract class TypeApi { /** The term symbol associated with the type, or `NoSymbol` for types * that do not refer to a term symbol. */ @@ -152,42 +178,177 @@ trait Types extends base.Types { self: Universe => def contains(sym: Symbol): Boolean } - /** .. */ - override type ThisType >: Null <: SingletonType with ThisTypeApi + /** The type of Scala singleton types, i.e., types that are inhabited + * by only one nun-null value. These include types of the forms + * {{{ + * C.this.type + * C.super.type + * x.type + * }}} + * as well as [[ConstantType constant types]]. + */ + type SingletonType >: Null <: Type + + /** A tag that preserves the identity of the `SingletonType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SingletonTypeTag: ClassTag[SingletonType] + + /** A singleton type that describes types of the form on the left with the + * corresponding `ThisType` representation to the right: + * {{{ + * C.this.type ThisType(C) + * }}} + */ + type ThisType >: Null <: AnyRef with SingletonType with ThisTypeApi + + /** A tag that preserves the identity of the `ThisType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ThisTypeTag: ClassTag[ThisType] + + /** The constructor/deconstructor for `ThisType` instances. */ + val ThisType: ThisTypeExtractor + + /** An extractor class to create and pattern match with syntax `ThisType(sym)` + * where `sym` is the class prefix of the this type. + */ + abstract class ThisTypeExtractor { + /** + * Creates a ThisType from the given class symbol. + */ + def apply(sym: Symbol): Type + def unapply(tpe: ThisType): Option[Symbol] + } /** The API that all this types support */ trait ThisTypeApi extends TypeApi { this: ThisType => val sym: Symbol } - /** .. */ - override type SingleType >: Null <: SingletonType with SingleTypeApi + /** The `SingleType` type describes types of any of the forms on the left, + * with their TypeRef representations to the right. + * {{{ + * (T # x).type SingleType(T, x) + * p.x.type SingleType(p.type, x) + * x.type SingleType(NoPrefix, x) + * }}} + */ + type SingleType >: Null <: AnyRef with SingletonType with SingleTypeApi + + /** A tag that preserves the identity of the `SingleType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SingleTypeTag: ClassTag[SingleType] + + /** The constructor/deconstructor for `SingleType` instances. */ + val SingleType: SingleTypeExtractor + + /** An extractor class to create and pattern match with syntax `SingleType(pre, sym)` + * Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol + * referred to by the single-type. + */ + abstract class SingleTypeExtractor { + def apply(pre: Type, sym: Symbol): Type // not SingleTypebecause of implementation details + def unapply(tpe: SingleType): Option[(Type, Symbol)] + } /** The API that all single types support */ trait SingleTypeApi extends TypeApi { this: SingleType => val pre: Type val sym: Symbol } + /** The `SuperType` type is not directly written, but arises when `C.super` is used + * as a prefix in a `TypeRef` or `SingleType`. It's internal presentation is + * {{{ + * SuperType(thistpe, supertpe) + * }}} + * Here, `thistpe` is the type of the corresponding this-type. For instance, + * in the type arising from C.super, the `thistpe` part would be `ThisType(C)`. + * `supertpe` is the type of the super class referred to by the `super`. + */ + type SuperType >: Null <: AnyRef with SingletonType with SuperTypeApi - /** .. */ - override type SuperType >: Null <: SingletonType with SuperTypeApi + /** A tag that preserves the identity of the `SuperType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SuperTypeTag: ClassTag[SuperType] + + /** The constructor/deconstructor for `SuperType` instances. */ + val SuperType: SuperTypeExtractor + + /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)` + */ + abstract class SuperTypeExtractor { + def apply(thistpe: Type, supertpe: Type): Type // not SuperTypebecause of implementation details + def unapply(tpe: SuperType): Option[(Type, Type)] + } /** The API that all super types support */ trait SuperTypeApi extends TypeApi { this: SuperType => val thistpe: Type val supertpe: Type } + /** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant. + * The REPL expresses constant types like `Int(11)`. Here are some constants with their types: + * {{{ + * 1 ConstantType(Constant(1)) + * "abc" ConstantType(Constant("abc")) + * }}} + */ + type ConstantType >: Null <: AnyRef with SingletonType with ConstantTypeApi + + /** A tag that preserves the identity of the `ConstantType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ConstantTypeTag: ClassTag[ConstantType] - /** .. */ - override type ConstantType >: Null <: SingletonType with ConstantTypeApi + /** The constructor/deconstructor for `ConstantType` instances. */ + val ConstantType: ConstantTypeExtractor + + /** An extractor class to create and pattern match with syntax `ConstantType(constant)` + * Here, `constant` is the constant value represented by the type. + */ + abstract class ConstantTypeExtractor { + def apply(value: Constant): ConstantType + def unapply(tpe: ConstantType): Option[Constant] + } /** The API that all constant types support */ trait ConstantTypeApi extends TypeApi { this: ConstantType => val value: Constant } - /** .. */ - override type TypeRef >: Null <: Type with TypeRefApi + /** The `TypeRef` type describes types of any of the forms on the left, + * with their TypeRef representations to the right. + * {{{ + * T # C[T_1, ..., T_n] TypeRef(T, C, List(T_1, ..., T_n)) + * p.C[T_1, ..., T_n] TypeRef(p.type, C, List(T_1, ..., T_n)) + * C[T_1, ..., T_n] TypeRef(NoPrefix, C, List(T_1, ..., T_n)) + * T # C TypeRef(T, C, Nil) + * p.C TypeRef(p.type, C, Nil) + * C TypeRef(NoPrefix, C, Nil) + * }}} + */ + type TypeRef >: Null <: AnyRef with Type with TypeRefApi + + /** A tag that preserves the identity of the `TypeRef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeRefTag: ClassTag[TypeRef] + + /** The constructor/deconstructor for `TypeRef` instances. */ + val TypeRef: TypeRefExtractor + + /** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)` + * Here, `pre` is the prefix of the type reference, `sym` is the symbol + * referred to by the type reference, and `args` is a possible empty list of + * type argumenrts. + */ + abstract class TypeRefExtractor { + def apply(pre: Type, sym: Symbol, args: List[Type]): Type // not TypeRefbecause of implementation details + def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] + } /** The API that all type refs support */ trait TypeRefApi extends TypeApi { this: TypeRef => @@ -196,8 +357,46 @@ trait Types extends base.Types { self: Universe => val args: List[Type] } - /** .. */ - override type RefinedType >: Null <: CompoundType with RefinedTypeApi + /** A subtype of Type representing refined types as well as `ClassInfo` signatures. + */ + type CompoundType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `CompoundType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val CompoundTypeTag: ClassTag[CompoundType] + + /** The `RefinedType` type defines types of any of the forms on the left, + * with their RefinedType representations to the right. + * {{{ + * P_1 with ... with P_m { D_1; ...; D_n} RefinedType(List(P_1, ..., P_m), Scope(D_1, ..., D_n)) + * P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope()) + * { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n)) + * }}} + */ + type RefinedType >: Null <: AnyRef with CompoundType with RefinedTypeApi + + /** A tag that preserves the identity of the `RefinedType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val RefinedTypeTag: ClassTag[RefinedType] + + /** The constructor/deconstructor for `RefinedType` instances. */ + val RefinedType: RefinedTypeExtractor + + /** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)` + * Here, `parents` is the list of parent types of the class, and `decls` is the scope + * containing all declarations in the class. + */ + abstract class RefinedTypeExtractor { + def apply(parents: List[Type], decls: Scope): RefinedType + + /** An alternative constructor that passes in the synthetic classs symbol + * that backs the refined type. (Normally, a fresh class symbol is created automatically). + */ + def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType + def unapply(tpe: RefinedType): Option[(List[Type], Scope)] + } /** The API that all refined types support */ trait RefinedTypeApi extends TypeApi { this: RefinedType => @@ -205,8 +404,35 @@ trait Types extends base.Types { self: Universe => val decls: Scope } - /** .. */ - override type ClassInfoType >: Null <: CompoundType with ClassInfoTypeApi + /** The `ClassInfo` type signature is used to define parents and declarations + * of classes, traits, and objects. If a class, trait, or object C is declared like this + * {{{ + * C extends P_1 with ... with P_m { D_1; ...; D_n} + * }}} + * its `ClassInfo` type has the following form: + * {{{ + * ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C) + * }}} + */ + type ClassInfoType >: Null <: AnyRef with CompoundType with ClassInfoTypeApi + + /** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ClassInfoTypeTag: ClassTag[ClassInfoType] + + /** The constructor/deconstructor for `ClassInfoType` instances. */ + val ClassInfoType: ClassInfoTypeExtractor + + /** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)` + * Here, `parents` is the list of parent types of the class, `decls` is the scope + * containing all declarations in the class, and `clazz` is the symbol of the class + * itself. + */ + abstract class ClassInfoTypeExtractor { + def apply(parents: List[Type], decls: Scope, typeSymbol: Symbol): ClassInfoType + def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] + } /** The API that all class info types support */ trait ClassInfoTypeApi extends TypeApi { this: ClassInfoType => @@ -215,8 +441,36 @@ trait Types extends base.Types { self: Universe => val typeSymbol: Symbol } - /** .. */ - override type MethodType >: Null <: Type with MethodTypeApi + /** The `MethodType` type signature is used to indicate parameters and result type of a method + */ + type MethodType >: Null <: AnyRef with Type with MethodTypeApi + + /** A tag that preserves the identity of the `MethodType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MethodTypeTag: ClassTag[MethodType] + + /** The constructor/deconstructor for `MethodType` instances. */ + val MethodType: MethodTypeExtractor + + /** An extractor class to create and pattern match with syntax `MethodType(params, respte)` + * Here, `params` is a potentially empty list of parameter symbols of the method, + * and `restpe` is the result type of the method. If the method is curried, `restpe` would + * be another `MethodType`. + * Note: `MethodType(Nil, Int)` would be the type of a method defined with an empty parameter list. + * {{{ + * def f(): Int + * }}} + * If the method is completely parameterless, as in + * {{{ + * def f: Int + * }}} + * its type is a `NullaryMethodType`. + */ + abstract class MethodTypeExtractor { + def apply(params: List[Symbol], resultType: Type): MethodType + def unapply(tpe: MethodType): Option[(List[Symbol], Type)] + } /** The API that all method types support */ trait MethodTypeApi extends TypeApi { this: MethodType => @@ -224,16 +478,53 @@ trait Types extends base.Types { self: Universe => val resultType: Type } - /** .. */ - override type NullaryMethodType >: Null <: Type with NullaryMethodTypeApi + /** The `NullaryMethodType` type signature is used for parameterless methods + * with declarations of the form `def foo: T` + */ + type NullaryMethodType >: Null <: AnyRef with Type with NullaryMethodTypeApi + + /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType] + + /** The constructor/deconstructor for `NullaryMethodType` instances. */ + val NullaryMethodType: NullaryMethodTypeExtractor + + /** An extractor class to create and pattern match with syntax `NullaryMethodType(resultType)`. + * Here, `resultType` is the result type of the parameterless method. + */ + abstract class NullaryMethodTypeExtractor { + def apply(resultType: Type): NullaryMethodType + def unapply(tpe: NullaryMethodType): Option[(Type)] + } /** The API that all nullary method types support */ trait NullaryMethodTypeApi extends TypeApi { this: NullaryMethodType => val resultType: Type } - /** .. */ - override type PolyType >: Null <: Type with PolyTypeApi + /** The `PolyType` type signature is used for polymorphic methods + * that have at least one type parameter. + */ + type PolyType >: Null <: AnyRef with Type with PolyTypeApi + + /** A tag that preserves the identity of the `PolyType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val PolyTypeTag: ClassTag[PolyType] + + /** The constructor/deconstructor for `PolyType` instances. */ + val PolyType: PolyTypeExtractor + + /** An extractor class to create and pattern match with syntax `PolyType(typeParams, resultType)`. + * Here, `typeParams` are the type parameters of the method and `resultType` + * is the type signature following the type parameters. + */ + abstract class PolyTypeExtractor { + def apply(typeParams: List[Symbol], resultType: Type): PolyType + def unapply(tpe: PolyType): Option[(List[Symbol], Type)] + } /** The API that all polymorphic types support */ trait PolyTypeApi extends TypeApi { this: PolyType => @@ -241,8 +532,28 @@ trait Types extends base.Types { self: Universe => val resultType: Type } - /** .. */ - override type ExistentialType >: Null <: Type with ExistentialTypeApi + /** The `ExistentialType` type signature is used for existential types and + * wildcard types. + */ + type ExistentialType >: Null <: AnyRef with Type with ExistentialTypeApi + + /** A tag that preserves the identity of the `ExistentialType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ExistentialTypeTag: ClassTag[ExistentialType] + + /** The constructor/deconstructor for `ExistentialType` instances. */ + val ExistentialType: ExistentialTypeExtractor + + /** An extractor class to create and pattern match with syntax + * `ExistentialType(quantified, underlying)`. + * Here, `quantified` are the type variables bound by the existential type and `underlying` + * is the type that's existentially quantified. + */ + abstract class ExistentialTypeExtractor { + def apply(quantified: List[Symbol], underlying: Type): ExistentialType + def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] + } /** The API that all existential types support */ trait ExistentialTypeApi extends TypeApi { this: ExistentialType => @@ -250,8 +561,28 @@ trait Types extends base.Types { self: Universe => val underlying: Type } - /** .. */ - override type AnnotatedType >: Null <: Type with AnnotatedTypeApi + /** The `AnnotatedType` type signature is used for annotated types of the + * for `<type> @<annotation>`. + */ + type AnnotatedType >: Null <: AnyRef with Type with AnnotatedTypeApi + + /** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AnnotatedTypeTag: ClassTag[AnnotatedType] + + /** The constructor/deconstructor for `AnnotatedType` instances. */ + val AnnotatedType: AnnotatedTypeExtractor + + /** An extractor class to create and pattern match with syntax + * `AnnotatedType(annotations, underlying, selfsym)`. + * Here, `annotations` are the annotations decorating the underlying type `underlying`. + * `selfSym` is a symbol representing the annotated type itself. + */ + abstract class AnnotatedTypeExtractor { + def apply(annotations: List[Annotation], underlying: Type, selfsym: Symbol): AnnotatedType + def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type, Symbol)] + } /** The API that all annotated types support */ trait AnnotatedTypeApi extends TypeApi { this: AnnotatedType => @@ -260,8 +591,34 @@ trait Types extends base.Types { self: Universe => val selfsym: Symbol } - /** .. */ - override type TypeBounds >: Null <: Type with TypeBoundsApi + /** The `TypeBounds` type signature is used to indicate lower and upper type bounds + * of type parameters and abstract types. It is not a first-class type. + * If an abstract type or type parameter is declared with any of the forms + * on the left, its type signature is the TypeBounds type on the right. + * {{{ + * T >: L <: U TypeBounds(L, U) + * T >: L TypeBounds(L, Any) + * T <: U TypeBounds(Nothing, U) + * }}} + */ + type TypeBounds >: Null <: AnyRef with Type with TypeBoundsApi + + /** A tag that preserves the identity of the `TypeBounds` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeBoundsTag: ClassTag[TypeBounds] + + /** The constructor/deconstructor for `TypeBounds` instances. */ + val TypeBounds: TypeBoundsExtractor + + /** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)` + * Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is + * the upper bound. + */ + abstract class TypeBoundsExtractor { + def apply(lo: Type, hi: Type): TypeBounds + def unapply(tpe: TypeBounds): Option[(Type, Type)] + } /** The API that all type bounds support */ trait TypeBoundsApi extends TypeApi { this: TypeBounds => @@ -269,8 +626,38 @@ trait Types extends base.Types { self: Universe => val hi: Type } - /** .. */ - override type BoundedWildcardType >: Null <: Type with BoundedWildcardTypeApi + /** An object representing an unknown type, used during type inference. + * If you see WildcardType outside of inference it is almost certainly a bug. + */ + val WildcardType: Type + + /** BoundedWildcardTypes, used only during type inference, are created in + * two places: + * + * 1. If the expected type of an expression is an existential type, + * its hidden symbols are replaced with bounded wildcards. + * 2. When an implicit conversion is being sought based in part on + * the name of a method in the converted type, a HasMethodMatching + * type is created: a MethodType with parameters typed as + * BoundedWildcardTypes. + */ + type BoundedWildcardType >: Null <: AnyRef with Type with BoundedWildcardTypeApi + + /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType] + + /** The constructor/deconstructor for `BoundedWildcardType` instances. */ + val BoundedWildcardType: BoundedWildcardTypeExtractor + + /** An extractor class to create and pattern match with syntax `BoundedWildcardTypeExtractor(bounds)` + * with `bounds` denoting the type bounds. + */ + abstract class BoundedWildcardTypeExtractor { + def apply(bounds: TypeBounds): BoundedWildcardType + def unapply(tpe: BoundedWildcardType): Option[TypeBounds] + } /** The API that all this types support */ trait BoundedWildcardTypeApi extends TypeApi { this: BoundedWildcardType => diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index 3165f9abcd..7d0f6cf0d6 100644 --- a/src/reflect/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -1,17 +1,82 @@ package scala.reflect package api -abstract class Universe extends base.Universe - with Symbols +abstract class Universe extends Symbols with Types with FlagSets + with Scopes with Names with Trees - with Printers with Constants + with Annotations with Positions - with Mirrors + with Exprs + with TypeTags + with TagInterop with StandardDefinitions with StandardNames + with BuildUtils + with Mirrors + with Printers with Importers - with Annotations +{ + /** Produce the abstract syntax tree representing the given Scala expression. + * + * For example + * + * {{{ + * val five = reify{ 5 } // Literal(Constant(5)) + * reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("$plus")), List( Literal(Constant(4)) ) ) + * reify{ five.splice + 4 } // Apply( Select( Literal(Constant(5)), newTermName("$plus")), List( Literal(Constant(4)) ) ) + * }}} + * + * The produced tree is path dependent on the Universe `reify` was called from. + * + * Use [[scala.reflect.api.Exprs#Expr.splice]] to embed an existing expression into a reify call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced. + * + * == Further info and implementation details == + * + * `reify` is implemented as a macro, which given an expression, generates a tree that when compiled and executed produces the original tree. + * + * For instance in `reify{ x + 1 }` the macro `reify` receives the abstract syntax tree of `x + 1` as its argument, which is + * + * {{{ + * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1)))) + * }}} + * + * and returns a tree, which produces the tree above, when compiled and executed. So in other terms, the refiy call expands to something like + * + * {{{ + * val $u: u.type = u // where u is a reference to the Universe that calls the reify + * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1)))))) + * }}} + * + * ------ + * + * Reification performs expression splicing (when processing Expr.splice) + * and type splicing (for every type T that has a TypeTag[T] implicit in scope): + * + * {{{ + * val two = mirror.reify(2) // Literal(Constant(2)) + * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree)) + * + * def macroImpl[T](c: Context) = { + * ... + * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion + * // however, if T were annotated with c.WeakTypeTag (which would declare an implicit parameter for macroImpl) + * // then reification would substitute T with the TypeTree that was used in a TypeApply of this particular macro invocation + * val factory = c.reify{ new Queryable[T] } + * ... + * } + * }}} + * + * The transformation looks mostly straightforward, but it has its tricky parts: + * - Reifier retains symbols and types defined outside the reified tree, however + * locally defined entities get erased and replaced with their original trees + * - Free variables are detected and wrapped in symbols of the type `FreeTermSymbol` or `FreeTypeSymbol` + * - Mutable variables that are accessed from a local function are wrapped in refs + */ + // implementation is hardwired to `scala.reflect.reify.Taggers` + // using the mechanism implemented in `scala.tools.reflect.FastTrack` + def reify[T](expr: T): Expr[T] = ??? // macro +}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala index d2fce7cf1d..0b2a43936e 100644 --- a/src/reflect/scala/reflect/api/package.scala +++ b/src/reflect/scala/reflect/api/package.scala @@ -1,12 +1,80 @@ package scala.reflect -package object api { +import scala.reflect.api.{Universe => ApiUniverse} - // type and value aliases for slices of the base Universe cake that are not - // repeated in api.Universe - type Scopes = base.Scopes - type BuildUtils = base.BuildUtils - type Attachments = base.Attachments +/** + * The main package of Scala's reflection library. + * + * The reflection library is structured according to the 'cake pattern'. The main layer + * resides in package [[scala.reflect.api]] and defines an interface to the following main types: + * + * - [[scala.reflect.api.Types#Type Types]] represent types + * - [[scala.reflect.api.Symbols#Symbol Symbols]] represent definitions + * - [[scala.reflect.api.Trees#Tree Trees]] represent abstract syntax trees + * - [[scala.reflect.api.Names#Name Names]] represent term and type names + * - [[scala.reflect.api.Annotations#Annotation Annotations]] represent annotations + * - [[scala.reflect.api.Positions#Position Positions]] represent source positions of tree nodes + * - [[scala.reflect.api.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and + * definition trees + * - [[scala.reflect.api.Constants#Constant Constants]] represent compile-time constants. + * + * Each of these types are defined in their own enclosing traits, which are ultimately all inherited by class + * [[scala.reflect.api.Universe Universe]]. The main universe defines a minimal interface to the above types. + * Universes that provide additional functionality such as deeper introspection or runtime code generation, + * are defined in packages [[scala.reflect.api]] and `scala.tools.reflect`. + * + * The cake pattern employed here requires to write certain Scala idioms with more indirections that usual. + * What follows is a description of these indirections, which will help to navigate the Scaladocs easily. + * + * For instance, consider the base type of all abstract syntax trees: [[scala.reflect.api.Trees#Tree]]. + * This type is not a class but is abstract and has an upper bound of [[scala.reflect.api.Trees#TreeApi]], + * which is a class defining the minimal base interface for all trees. + * + * For a more interesting tree type, consider [[scala.reflect.api.Trees#If]] representing if-expressions. + * It is defined next to a value `If` of type [[scala.reflect.api.Trees#IfExtractor]]. + * This value serves as the companion object defining a factory method `apply` and a corresponding `unapply` + * for pattern matching. + * + * {{{ + * import scala.reflect.runtime.universe._ + * val cond = reify{ condition }.tree // <- just some tree representing a condition + * val body = Literal(Constant(1)) + * val other = Literal(Constant(2)) + * val iftree = If(cond,body,other) + * }}} + * + * is equivalent to + * + * {{{ + * import scala.reflect.runtime.universe._ + * val iftree = reify{ if( condition ) 1 else 2 }.tree + * }}} + * + * and can be pattern matched as + * + * {{{ + * iftree match { case If(cond,body,other) => ... } + * }}} + * + * Moreover, there is an implicit value [[scala.reflect.api.Trees#IfTag]] of type + * `ClassTag[If]` that is used by the Scala compiler so that we can indeed pattern match on `If`: + * {{{ + * iftree match { case _:If => ... } + * }}} + * Without the given implicit value, this pattern match would raise an "unchecked" warning at compile time + * since `If` is an abstract type that gets erased at runtime. See [[scala.reflect.ClassTag]] for details. + * + * To summarize: each tree type `X` (and similarly for other types such as `Type` or `Symbol`) is represented + * by an abstract type `X`, optionally together with a class `XApi` that defines `X`'s' interface. + * `X`'s companion object, if it exists, is represented by a value `X` that is of type `XExtractor`. + * Moreover, for each type `X`, there is a value `XTag` of type `ClassTag[X]` that allows to pattern match on `X`. + */ +package object api { - type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] -} + // anchors for materialization macros emitted during tag materialization in Implicits.scala + // 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 +}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index f7371f4180..9f41f0336e 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -3,9 +3,9 @@ package internal import Flags._ -trait BuildUtils extends base.BuildUtils { self: SymbolTable => +trait BuildUtils { self: SymbolTable => - class BuildImpl extends BuildBase { + class BuildImpl extends BuildApi { def selectType(owner: Symbol, name: String): TypeSymbol = select(owner, newTypeName(name)).asType @@ -64,5 +64,5 @@ trait BuildUtils extends base.BuildUtils { self: SymbolTable => def setSymbol[T <: Tree](tree: T, sym: Symbol): T = { tree.setSymbol(sym); tree } } - val build: BuildBase = new BuildImpl + val build: BuildApi = new BuildImpl } diff --git a/src/reflect/scala/reflect/internal/Chars.scala b/src/reflect/scala/reflect/internal/Chars.scala index e5e5325b93..b1ae105e56 100644 --- a/src/reflect/scala/reflect/internal/Chars.scala +++ b/src/reflect/scala/reflect/internal/Chars.scala @@ -51,7 +51,7 @@ trait Chars { } /** Is character a line break? */ - @inline def isLineBreakChar(c: Char) = (c: @switch) match { + def isLineBreakChar(c: Char) = (c: @switch) match { case LF|FF|CR|SU => true case _ => false } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 48a658192b..2db8c29a63 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -10,7 +10,7 @@ import scala.annotation.{ switch, meta } import scala.collection.{ mutable, immutable } import Flags._ import PartialFunction._ -import scala.reflect.base.{Universe => BaseUniverse} +import scala.reflect.api.{Universe => ApiUniverse} trait Definitions extends api.StandardDefinitions { self: SymbolTable => @@ -484,7 +484,7 @@ trait Definitions extends api.StandardDefinitions { // scala.reflect lazy val ReflectPackage = requiredModule[scala.reflect.`package`.type] - def ReflectBasis = getMemberValue(ReflectPackage, nme.basis) + 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 @@ -496,28 +496,31 @@ trait Definitions extends api.StandardDefinitions { lazy val OptManifestClass = requiredClass[scala.reflect.OptManifest[_]] lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type] - lazy val ExprsClass = requiredClass[scala.reflect.base.Exprs] - lazy val ExprClass = getMemberClass(ExprsClass, tpnme.Expr) - def ExprSplice = getMemberMethod(ExprClass, nme.splice) - def ExprValue = getMemberMethod(ExprClass, nme.value) - lazy val ExprModule = getMemberModule(ExprsClass, nme.Expr) - - lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]] - lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]] - lazy val TypeTagsClass = requiredClass[scala.reflect.base.TypeTags] - lazy val WeakTypeTagClass = getMemberClass(TypeTagsClass, tpnme.WeakTypeTag) - lazy val WeakTypeTagModule = getMemberModule(TypeTagsClass, nme.WeakTypeTag) - lazy val TypeTagClass = getMemberClass(TypeTagsClass, tpnme.TypeTag) - lazy val TypeTagModule = getMemberModule(TypeTagsClass, nme.TypeTag) - - lazy val BaseUniverseClass = requiredClass[scala.reflect.base.Universe] - def BaseUniverseReify = getMemberMethod(BaseUniverseClass, nme.reify) + 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 ExprModule = if (ExprsClass != NoSymbol) getMemberModule(ExprsClass, nme.Expr) else NoSymbol + + 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 + 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 + + 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 lazy val JavaUniverseClass = getClassIfDefined("scala.reflect.api.JavaUniverse") // defined in scala-reflect.jar, so we need to be careful - lazy val MirrorOfClass = requiredClass[scala.reflect.base.MirrorOf[_]] + lazy val MirrorOfClass = getClassIfDefined("scala.reflect.api.MirrorOf") // defined in scala-reflect.jar, so we need to be careful - lazy val TypeCreatorClass = requiredClass[scala.reflect.base.TypeCreator] - lazy val TreeCreatorClass = requiredClass[scala.reflect.base.TreeCreator] + 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 @@ -525,10 +528,6 @@ trait Definitions extends api.StandardDefinitions { def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol def MacroContextMirror = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.mirror) else NoSymbol lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl] - lazy val MacroInternalPackage = getPackageObject("scala.reflect.macros.internal") - def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag) - def MacroInternal_materializeWeakTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeWeakTypeTag) - def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag) lazy val StringContextClass = requiredClass[scala.StringContext] def StringContext_f = getMemberMethod(StringContextClass, nme.f) @@ -542,8 +541,8 @@ trait Definitions extends api.StandardDefinitions { lazy val NoneModule: ModuleSymbol = requiredModule[scala.None.type] lazy val SomeModule: ModuleSymbol = requiredModule[scala.Some.type] - def compilerTypeFromTag(tt: BaseUniverse # WeakTypeTag[_]): Type = tt.in(rootMirror).tpe - def compilerSymbolFromTag(tt: BaseUniverse # WeakTypeTag[_]): Symbol = tt.in(rootMirror).tpe.typeSymbol + def compilerTypeFromTag(tt: ApiUniverse # WeakTypeTag[_]): Type = tt.in(rootMirror).tpe + def compilerSymbolFromTag(tt: ApiUniverse # WeakTypeTag[_]): Symbol = tt.in(rootMirror).tpe.typeSymbol // The given symbol represents either String.+ or StringAdd.+ def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+ diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index 385e45997b..89332d0ae5 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -41,7 +41,7 @@ trait Scopes extends api.Scopes { self: SymbolTable => * This is necessary because when run from reflection every scope needs to have a * SynchronizedScope as mixin. */ - class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends ScopeBase with MemberScopeBase { + class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends ScopeApi with MemberScopeApi { protected[Scopes] def this(base: Scope) = { this(base.elems) diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 5f6a3bf777..5c4d1f7e28 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -8,7 +8,7 @@ trait StdAttachments { * Common code between reflect-internal Symbol and Tree related to Attachments. */ trait Attachable { - protected var rawatt: base.Attachments { type Pos = Position } = NoPosition + protected var rawatt: scala.reflect.api.Attachments { type Pos = Position } = NoPosition def attachments = rawatt def updateAttachment[T: ClassTag](attachment: T): this.type = { rawatt = rawatt.update(attachment); this } def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } diff --git a/src/reflect/scala/reflect/internal/StdCreators.scala b/src/reflect/scala/reflect/internal/StdCreators.scala index 3e6b7c1ab4..eba583d4b5 100644 --- a/src/reflect/scala/reflect/internal/StdCreators.scala +++ b/src/reflect/scala/reflect/internal/StdCreators.scala @@ -1,20 +1,20 @@ package scala.reflect package internal -import scala.reflect.base.{TreeCreator, TypeCreator} -import scala.reflect.base.{Universe => BaseUniverse} +import scala.reflect.api.{TreeCreator, TypeCreator} +import scala.reflect.api.{Universe => ApiUniverse} trait StdCreators { self: SymbolTable => case class FixedMirrorTreeCreator(mirror: MirrorOf[StdCreators.this.type], tree: Tree) extends TreeCreator { - def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Tree = + def apply[U <: ApiUniverse with Singleton](m: MirrorOf[U]): U # Tree = if (m eq mirror) tree.asInstanceOf[U # Tree] else throw new IllegalArgumentException(s"Expr defined in $mirror cannot be migrated to other mirrors.") } case class FixedMirrorTypeCreator(mirror: MirrorOf[StdCreators.this.type], tpe: Type) extends TypeCreator { - def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = + def apply[U <: ApiUniverse with Singleton](m: MirrorOf[U]): U # Type = if (m eq mirror) tpe.asInstanceOf[U # Type] else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.") } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 2f305296f5..2cdfb05e77 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -206,7 +206,6 @@ trait StdNames { } abstract class TypeNames extends Keywords with TypeNamesApi { - type NameType = TypeName protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name) final val BYNAME_PARAM_CLASS_NAME: NameType = "<byname>" @@ -273,7 +272,6 @@ trait StdNames { } abstract class TermNames extends Keywords with TermNamesApi { - type NameType = TermName protected implicit def createNameType(name: String): TermName = newTermNameCached(name) /** Base strings from which synthetic names are derived. */ @@ -635,7 +633,6 @@ trait StdNames { val asInstanceOf_Ob : NameType = "$asInstanceOf" val assert_ : NameType = "assert" val assume_ : NameType = "assume" - val basis : NameType = "basis" val box: NameType = "box" val build : NameType = "build" val bytes: NameType = "bytes" diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 74f4769fec..a0e28bf735 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -10,9 +10,8 @@ import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer import util.Statistics import Flags._ -import base.Attachments import scala.annotation.tailrec -import scala.tools.nsc.io.AbstractFile +import scala.reflect.io.AbstractFile trait Symbols extends api.Symbols { self: SymbolTable => import definitions._ @@ -346,7 +345,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => // don't test directly -- use isGADTSkolem // used to single out a gadt skolem symbol in deskolemizeGADT // gadtskolems are created in adaptConstrPattern and removed at the end of typedCase - @inline final protected[Symbols] def GADT_SKOLEM_FLAGS = CASEACCESSOR | SYNTHETIC + final protected[Symbols] def GADT_SKOLEM_FLAGS = CASEACCESSOR | SYNTHETIC // flags set up to maintain TypeSkolem's invariant: origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL) // GADT_SKOLEM_FLAGS (== CASEACCESSOR | SYNTHETIC) used to single this symbol out in deskolemizeGADT @@ -586,11 +585,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => && owner.isPackageClass && nme.isReplWrapperName(name) ) - @inline final def getFlag(mask: Long): Long = flags & mask + final def getFlag(mask: Long): Long = flags & mask /** Does symbol have ANY flag in `mask` set? */ - @inline final def hasFlag(mask: Long): Boolean = (flags & mask) != 0 + final def hasFlag(mask: Long): Boolean = (flags & mask) != 0 /** Does symbol have ALL the flags in `mask` set? */ - @inline final def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask + final def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask def setFlag(mask: Long): this.type = { _rawflags |= mask ; this } def resetFlag(mask: Long): this.type = { _rawflags &= ~mask ; this } diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index f953e9b757..ebf0998573 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -272,9 +272,6 @@ abstract class TreeGen extends macros.TreeBuilder { def mkOr(tree1: Tree, tree2: Tree): Tree = Apply(Select(tree1, Boolean_or), List(tree2)) - def mkBasisUniverseRef: Tree = - mkAttributedRef(ReflectBasis) setType singleType(ReflectBasis.owner.thisPrefix, ReflectBasis) - def mkRuntimeUniverseRef: Tree = { assert(ReflectRuntimeUniverse != NoSymbol) mkAttributedRef(ReflectRuntimeUniverse) setType singleType(ReflectRuntimeUniverse.owner.thisPrefix, ReflectRuntimeUniverse) diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 5a6d6ce7c7..7ec9f7086d 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -7,7 +7,6 @@ package scala.reflect package internal import Flags._ -import base.Attachments import scala.collection.mutable.{ListBuffer, LinkedHashSet} import util.Statistics @@ -21,10 +20,10 @@ trait Trees extends api.Trees { self: SymbolTable => if (Statistics.canEnable) Statistics.incCounter(TreesStats.nodeByType, getClass) - @inline final override def pos: Position = rawatt.pos + final override def pos: Position = rawatt.pos private[this] var rawtpe: Type = _ - @inline final def tpe = rawtpe + final def tpe = rawtpe def tpe_=(t: Type) = rawtpe = t def setType(tp: Type): this.type = { rawtpe = tp; this } def defineType(tp: Type): this.type = setType(tp) @@ -328,9 +327,23 @@ trait Trees extends api.Trees { self: SymbolTable => extends TermTree with UnApplyApi object UnApply extends UnApplyExtractor - case class ArrayValue(elemtpt: Tree, elems: List[Tree]) - extends TermTree with ArrayValueApi - object ArrayValue extends ArrayValueExtractor + /** An array of expressions. This AST node needs to be translated in backend. + * It is used to pass arguments to vararg arguments. + * Introduced by compiler phase uncurry. + * + * This AST node does not have direct correspondence to Scala code, + * and is used to pass arguments to vararg arguments. For instance: + * + * printf("%s%d", foo, 42) + * + * Is translated to after compiler phase uncurry to: + * + * Apply( + * Ident("printf"), + * Literal("%s%d"), + * ArrayValue(<Any>, List(Ident("foo"), Literal(42)))) + */ + case class ArrayValue(elemtpt: Tree, elems: List[Tree]) extends TermTree case class Function(vparams: List[ValDef], body: Tree) extends SymTree with TermTree with FunctionApi @@ -497,6 +510,7 @@ trait Trees extends api.Trees { self: SymbolTable => override type TreeCopier <: InternalTreeCopierOps abstract class InternalTreeCopierOps extends TreeCopierOps { def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic + def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue } class StrictTreeCopier extends InternalTreeCopierOps { @@ -1574,7 +1588,6 @@ trait Trees extends api.Trees { self: SymbolTable => implicit val StarTag = ClassTag[Star](classOf[Star]) implicit val BindTag = ClassTag[Bind](classOf[Bind]) implicit val UnApplyTag = ClassTag[UnApply](classOf[UnApply]) - implicit val ArrayValueTag = ClassTag[ArrayValue](classOf[ArrayValue]) implicit val FunctionTag = ClassTag[Function](classOf[Function]) implicit val AssignTag = ClassTag[Assign](classOf[Assign]) implicit val AssignOrNamedArgTag = ClassTag[AssignOrNamedArg](classOf[AssignOrNamedArg]) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index cda8a382de..ee488c9d18 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -4429,7 +4429,7 @@ trait Types extends api.Types { self: SymbolTable => var capturedSkolems: List[Symbol] = List() var capturedParams: List[Symbol] = List() - @inline private def skipPrefixOf(pre: Type, clazz: Symbol) = ( + private def skipPrefixOf(pre: Type, clazz: Symbol) = ( (pre eq NoType) || (pre eq NoPrefix) || !isPossiblePrefix(clazz) ) override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = { @@ -5117,9 +5117,9 @@ trait Types extends api.Types { self: SymbolTable => // in addition to making subtyping "more correct" for type vars, // it should avoid the stackoverflow that's been plaguing us (https://groups.google.com/d/topic/scala-internals/2gHzNjtB4xA/discussion) // this method is only called when subtyping hits a recursion threshold (subsametypeRecursions >= LogPendingSubTypesThreshold) - @inline def suspend(tp: Type) = + def suspend(tp: Type) = if (tp.isGround) null else suspendTypeVarsInType(tp) - @inline def revive(suspension: List[TypeVar]) = + def revive(suspension: List[TypeVar]) = if (suspension ne null) suspension foreach (_.suspended = false) val suspensions = Array(tp1, stp.tp1, tp2, stp.tp2) map suspend @@ -5621,7 +5621,7 @@ trait Types extends api.Types { self: SymbolTable => case _: SingletonType => tp2 match { case _: SingletonType => - @inline def chaseDealiasedUnderlying(tp: Type): Type = { + def chaseDealiasedUnderlying(tp: Type): Type = { var origin = tp var next = origin.underlying.dealias while (next.isInstanceOf[SingletonType]) { diff --git a/src/reflect/scala/reflect/internal/package.scala b/src/reflect/scala/reflect/internal/package.scala index 99b837152d..63568f6a6b 100644 --- a/src/reflect/scala/reflect/internal/package.scala +++ b/src/reflect/scala/reflect/internal/package.scala @@ -2,5 +2,5 @@ package scala.reflect package object internal { - type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] + type MirrorOf[U <: scala.reflect.api.Universe with Singleton] = scala.reflect.api.MirrorOf[U] } diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index cc5b5bb406..977398909f 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -203,28 +203,26 @@ trait Erasure { def specialErasure(sym: Symbol)(tp: Type): Type = if (sym != NoSymbol && sym.enclClass.isJavaDefined) erasure(sym)(tp) - else if (sym.isTerm && sym.owner.isDerivedValueClass) - specialErasureAvoiding(sym.owner, tp) - else if (sym.isValue && sym.owner.isMethodWithExtension) - specialErasureAvoiding(sym.owner.owner, tp) + else if (sym.isClassConstructor) + specialConstructorErasure(sym.owner, tp) else specialScalaErasure(tp) - def specialErasureAvoiding(clazz: Symbol, tpe: Type): Type = { + def specialConstructorErasure(clazz: Symbol, tpe: Type): Type = { tpe match { case PolyType(tparams, restpe) => - specialErasureAvoiding(clazz, restpe) + specialConstructorErasure(clazz, restpe) case ExistentialType(tparams, restpe) => - specialErasureAvoiding(clazz, restpe) + specialConstructorErasure(clazz, restpe) case mt @ MethodType(params, restpe) => MethodType( - cloneSymbolsAndModify(params, specialErasureAvoiding(clazz, _)), - if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) - else specialErasureAvoiding(clazz, (mt.resultType(mt.paramTypes)))) + cloneSymbolsAndModify(params, specialScalaErasure), + specialConstructorErasure(clazz, restpe)) case TypeRef(pre, `clazz`, args) => typeRef(pre, clazz, List()) - case _ => - specialScalaErasure(tpe) + case tp => + assert(clazz == ArrayClass || tp.isError, s"unexpected constructor erasure $tp for $clazz") + specialScalaErasure(tp) } } diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index 0268881be7..1621fb84d4 100644 --- a/src/reflect/scala/reflect/internal/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -7,7 +7,7 @@ package scala.reflect.internal.util import scala.reflect.ClassTag -import scala.reflect.base.Attachments +import scala.reflect.api.Attachments import scala.reflect.api.PositionApi object Position { diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala index 9a71e02e08..788c7532d1 100644 --- a/src/reflect/scala/reflect/internal/util/SourceFile.scala +++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala @@ -6,7 +6,7 @@ package scala.reflect.internal.util -import scala.tools.nsc.io.{ AbstractFile, VirtualFile } +import scala.reflect.io.{ AbstractFile, VirtualFile } import scala.collection.mutable.ArrayBuffer import scala.annotation.tailrec import java.util.regex.Pattern diff --git a/src/reflect/scala/reflect/internal/util/ThreeValues.scala b/src/reflect/scala/reflect/internal/util/ThreeValues.scala index d89f11c407..f89bd9e199 100644 --- a/src/reflect/scala/reflect/internal/util/ThreeValues.scala +++ b/src/reflect/scala/reflect/internal/util/ThreeValues.scala @@ -9,6 +9,6 @@ object ThreeValues { final val NO = -1 final val UNKNOWN = 0 - @inline def fromBoolean(b: Boolean): ThreeValue = if (b) YES else NO - @inline def toBoolean(x: ThreeValue): Boolean = x == YES + def fromBoolean(b: Boolean): ThreeValue = if (b) YES else NO + def toBoolean(x: ThreeValue): Boolean = x == YES } diff --git a/src/reflect/scala/tools/nsc/io/AbstractFile.scala b/src/reflect/scala/reflect/io/AbstractFile.scala index 018a017c6d..e32207c58c 100644 --- a/src/reflect/scala/tools/nsc/io/AbstractFile.scala +++ b/src/reflect/scala/reflect/io/AbstractFile.scala @@ -4,7 +4,7 @@ */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream } @@ -13,6 +13,10 @@ import java.net.URL import scala.collection.mutable.ArrayBuffer /** + * An abstraction over files for use in the reflection/compiler libraries. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' + * * @author Philippe Altherr * @version 1.0, 23/03/2004 */ @@ -81,6 +85,8 @@ object AbstractFile { * all other cases, the class <code>SourceFile</code> is used, which honors * <code>global.settings.encoding.value</code>. * </p> + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ abstract class AbstractFile extends Iterable[AbstractFile] { diff --git a/src/reflect/scala/tools/nsc/io/Directory.scala b/src/reflect/scala/reflect/io/Directory.scala index ebd6edc8d8..a24534137d 100644 --- a/src/reflect/scala/tools/nsc/io/Directory.scala +++ b/src/reflect/scala/reflect/io/Directory.scala @@ -6,11 +6,13 @@ ** |/ ** \* */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ File => JFile } - +/** + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' + */ object Directory { import scala.util.Properties.{ tmpDir, userHome, userDir } @@ -34,6 +36,8 @@ import Path._ * * @author Paul Phillips * @since 2.8 + * + * ''Note: This is library is considered experimental and should not be used unless you know what you are doing.'' */ class Directory(jfile: JFile) extends Path(jfile) { override def toAbsolute: Directory = if (isAbsolute) this else super.toAbsolute.toDirectory diff --git a/src/reflect/scala/tools/nsc/io/File.scala b/src/reflect/scala/reflect/io/File.scala index fce0e339e0..9e306371f7 100644 --- a/src/reflect/scala/tools/nsc/io/File.scala +++ b/src/reflect/scala/reflect/io/File.scala @@ -7,7 +7,7 @@ \* */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ @@ -17,7 +17,9 @@ import java.io.{ File => JFile } import java.nio.channels.{ Channel, FileChannel } import scala.io.Codec import scala.language.{reflectiveCalls, implicitConversions} - +/** + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' + */ object File { def pathSeparator = java.io.File.pathSeparator def separator = java.io.File.separator @@ -74,6 +76,8 @@ import Path._ * * @author Paul Phillips * @since 2.8 + * + * ''Note: This is library is considered experimental and should not be used unless you know what you are doing.'' */ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) with Streamable.Chars { override val creationCodec = constructorCodec diff --git a/src/reflect/scala/tools/nsc/io/FileOperationException.scala b/src/reflect/scala/reflect/io/FileOperationException.scala index f23658efbc..6bce799cea 100644 --- a/src/reflect/scala/tools/nsc/io/FileOperationException.scala +++ b/src/reflect/scala/reflect/io/FileOperationException.scala @@ -7,7 +7,7 @@ \* */ -package scala.tools.nsc +package scala.reflect package io - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ case class FileOperationException(msg: String) extends RuntimeException(msg) diff --git a/src/reflect/scala/tools/nsc/io/NoAbstractFile.scala b/src/reflect/scala/reflect/io/NoAbstractFile.scala index 2af933c27b..d503328a37 100644 --- a/src/reflect/scala/tools/nsc/io/NoAbstractFile.scala +++ b/src/reflect/scala/reflect/io/NoAbstractFile.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.io.InputStream @@ -11,6 +11,8 @@ import java.io.{ File => JFile } /** A distinguished object so you can avoid both null * and Option. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object NoAbstractFile extends AbstractFile { def absolute: AbstractFile = this diff --git a/src/reflect/scala/tools/nsc/io/Path.scala b/src/reflect/scala/reflect/io/Path.scala index 0a27e49686..9a1ff395a3 100644 --- a/src/reflect/scala/tools/nsc/io/Path.scala +++ b/src/reflect/scala/reflect/io/Path.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ @@ -27,8 +27,9 @@ import scala.language.implicitConversions * * @author Paul Phillips * @since 2.8 + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ - object Path { def isExtensionJarOrZip(jfile: JFile): Boolean = isExtensionJarOrZip(jfile.getName) def isExtensionJarOrZip(name: String): Boolean = { @@ -83,6 +84,8 @@ import Path._ /** The Path constructor is private so we can enforce some * semantics regarding how a Path might relate to the world. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class Path private[io] (val jfile: JFile) { val separator = java.io.File.separatorChar diff --git a/src/reflect/scala/tools/nsc/io/PlainFile.scala b/src/reflect/scala/reflect/io/PlainFile.scala index a4f378ad5e..14cb09317c 100644 --- a/src/reflect/scala/tools/nsc/io/PlainFile.scala +++ b/src/reflect/scala/reflect/io/PlainFile.scala @@ -4,12 +4,12 @@ */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ FileInputStream, FileOutputStream, IOException } import PartialFunction._ - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object PlainFile { /** * If the specified File exists, returns an abstract file backed @@ -20,7 +20,7 @@ object PlainFile { else if (file.isFile) new PlainFile(file) else null } - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) { override def isDirectory = true override def iterator = givenPath.list filter (_.exists) map (x => new PlainFile(x)) @@ -28,6 +28,8 @@ class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) { } /** This class implements an abstract file backed by a File. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class PlainFile(val givenPath: Path) extends AbstractFile { assert(path ne null) diff --git a/src/reflect/scala/tools/nsc/io/Streamable.scala b/src/reflect/scala/reflect/io/Streamable.scala index 625429bdb3..a083890e09 100644 --- a/src/reflect/scala/tools/nsc/io/Streamable.scala +++ b/src/reflect/scala/reflect/io/Streamable.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.net.{ URI, URL } @@ -17,12 +17,15 @@ import Path.fail * * @author Paul Phillips * @since 2.8 + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ - object Streamable { /** Traits which can be viewed as a sequence of bytes. Source types * which know their length should override def length: Long for more * efficient method implementations. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ trait Bytes { def inputStream(): InputStream @@ -66,6 +69,8 @@ object Streamable { } /** For objects which can be viewed as Chars. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ trait Chars extends Bytes { /** Calls to methods requiring byte<->char transformations should be offered diff --git a/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala b/src/reflect/scala/reflect/io/VirtualDirectory.scala index fa016f86f4..e71c5cbb6b 100644 --- a/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala +++ b/src/reflect/scala/reflect/io/VirtualDirectory.scala @@ -2,7 +2,7 @@ * Copyright 2005-2012 LAMP/EPFL */ -package scala.tools.nsc +package scala.reflect package io import scala.collection.mutable @@ -11,6 +11,8 @@ import scala.collection.mutable * An in-memory directory. * * @author Lex Spoon + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class VirtualDirectory(val name: String, maybeContainer: Option[VirtualDirectory]) extends AbstractFile { diff --git a/src/reflect/scala/tools/nsc/io/VirtualFile.scala b/src/reflect/scala/reflect/io/VirtualFile.scala index 8a5114bfe7..4884561f4e 100644 --- a/src/reflect/scala/tools/nsc/io/VirtualFile.scala +++ b/src/reflect/scala/reflect/io/VirtualFile.scala @@ -4,7 +4,7 @@ */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, InputStream, OutputStream } @@ -14,6 +14,8 @@ import java.io.{ File => JFile } * * @author Philippe Altherr * @version 1.0, 23/03/2004 + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class VirtualFile(val name: String, override val path: String) extends AbstractFile { /** diff --git a/src/reflect/scala/tools/nsc/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala index 49d2200895..2512c4d92f 100644 --- a/src/reflect/scala/tools/nsc/io/ZipArchive.scala +++ b/src/reflect/scala/reflect/io/ZipArchive.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.net.URL @@ -20,6 +20,8 @@ import scala.annotation.tailrec * @author Philippe Altherr (original version) * @author Paul Phillips (this one) * @version 2.0, + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object ZipArchive { def fromPath(path: String): FileZipArchive = fromFile(new JFile(path)) @@ -57,7 +59,7 @@ object ZipArchive { } } import ZipArchive._ - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Equals { self => @@ -78,13 +80,14 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq } } def deepIterator = walkIterator(iterator) - + /** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ sealed abstract class Entry(path: String) extends VirtualFile(baseName(path), path) { // have to keep this name for compat with sbt's compiler-interface def getArchive: ZipFile = null override def underlyingSource = Some(self) override def toString = self.path + "(" + path + ")" } + /** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class DirEntry(path: String) extends Entry(path) { val entries = mutable.HashMap[String, Entry]() @@ -120,7 +123,7 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq else ensureDir(dirs, dirName(entry.getName), null) } } - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ final class FileZipArchive(file: JFile) extends ZipArchive(file) { def iterator: Iterator[Entry] = { val zipFile = new ZipFile(file) @@ -161,7 +164,7 @@ final class FileZipArchive(file: JFile) extends ZipArchive(file) { case _ => false } } - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ final class URLZipArchive(val url: URL) extends ZipArchive(null) { def iterator: Iterator[Entry] = { val root = new DirEntry("/") diff --git a/src/reflect/scala/reflect/macros/Reifiers.scala b/src/reflect/scala/reflect/macros/Reifiers.scala index bdc6687edc..c2a6c5be05 100644 --- a/src/reflect/scala/reflect/macros/Reifiers.scala +++ b/src/reflect/scala/reflect/macros/Reifiers.scala @@ -6,11 +6,6 @@ import scala.reflect.api.PositionApi trait Reifiers { self: Context => - /** Reification prefix that refers to the base reflexive universe, ``scala.reflect.basis''. - * Providing it for the ``prefix'' parameter of ``reifyTree'' or ``reifyType'' will create a tree that can be inspected at runtime. - */ - val basisUniverse: Tree - /** Reification prefix that refers to the runtime reflexive universe, ``scala.reflect.runtime.universe''. * Providing it for the ``prefix'' parameter of ``reifyTree'' or ``reifyType'' will create a full-fledged tree that can be inspected at runtime. */ @@ -20,7 +15,7 @@ trait Reifiers { * For more information and examples see the documentation for ``Universe.reify''. * * The produced tree will be bound to the specified ``universe'' and ``mirror''. - * Possible values for ``universe'' include ``basisUniverse'' and ``runtimeUniverse''. + * Possible values for ``universe'' include ``runtimeUniverse''. * Possible values for ``mirror'' include ``EmptyTree'' (in that case the reifier will automatically pick an appropriate mirror). * * This function is deeply connected to ``Universe.reify'', a macro that reifies arbitrary expressions into runtime trees. diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index 7fa2e7cbae..f84c11ee63 100644 --- a/src/reflect/scala/reflect/macros/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -7,7 +7,7 @@ abstract class Universe extends scala.reflect.api.Universe { trait AttachableApi { /** ... */ - def attachments: base.Attachments { type Pos = Position } + def attachments: scala.reflect.api.Attachments { type Pos = Position } /** ... */ def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type diff --git a/src/reflect/scala/reflect/macros/package.scala b/src/reflect/scala/reflect/macros/package.scala index 06ce0b3244..df93785d40 100644 --- a/src/reflect/scala/reflect/macros/package.scala +++ b/src/reflect/scala/reflect/macros/package.scala @@ -2,5 +2,5 @@ package scala.reflect package object macros { - type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] + type MirrorOf[U <: scala.reflect.api.Universe with Singleton] = scala.reflect.api.MirrorOf[U] } diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala index eaf7d8326f..44d9d94a46 100644 --- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala +++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala @@ -49,7 +49,7 @@ object ReflectionUtils { case cl: java.net.URLClassLoader => (cl.getURLs mkString ",") case cl if cl != null && isAbstractFileClassLoader(cl.getClass) => - cl.asInstanceOf[{val root: scala.tools.nsc.io.AbstractFile}].root.canonicalPath + cl.asInstanceOf[{val root: scala.reflect.io.AbstractFile}].root.canonicalPath case null => inferBootClasspath case _ => diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 7705610efb..3c2885a9f4 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -1,7 +1,7 @@ package scala.reflect package runtime -import scala.tools.nsc.io.AbstractFile +import scala.reflect.io.AbstractFile trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index 49c272cc28..a514f0d5a1 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -97,9 +97,14 @@ class Main { */ def process(args: Arguments, path: ClassPath[AbstractFile])(classname: String): Unit = { // find the classfile - val encName = NameTransformer.encode( - if (classname == "scala.AnyRef") "java.lang.Object" - else classname) + val encName = classname match { + case "scala.AnyRef" => "java.lang.Object" + case _ => + // we have to encode every fragment of a name separately, otherwise the NameTransformer + // will encode using unicode escaping dot separators as well + // we can afford allocations because this is not a performance critical code + classname.split('.').map(NameTransformer.encode).mkString(".") + } val cls = path.findClass(encName) if (cls.isDefined && cls.get.binary.isDefined) { val cfile = cls.get.binary.get |